2013-07-25 75 views
0

我想在C#中使用System.Net.SocketsTcpClient类来编写我的游戏的网络部分。TcpClient缺失数据

  • 每个更新服务器正在向客户端发送信息。
  • 所有信息都内置到2kb数据包中,因此在1个更新中可以发送1-2-3-5-10个数据包。
  • 客户正在检查信息,如果信息有正确的格式 - 然后阅读。
  • 一切工作正常,直到服务器开始尝试发送太多的数据包。
  • 发生客户端不时发送的数据包通常是20-50数据包的错误数据1。
  • 例如,1个更新的1-2个数据包通常会被正常接收,3-10个数据包会导致错误的数据流更新。
  • 如果我一次启动多个客户端,应该从服务器获得相同的数据流 - 它们会获得不同数量的成功和失败数据流。

我在做什么错,我该如何逃避这个错误的数据流?

我只是在1毫秒内发送太多的数据,需要随时发送它?

这是发送信息:

这是接收信息:

byte[] readBuffer; 
int byfferSize = 2048; 

private void StartListening() 
    { 
     client.GetStream().BeginRead(readBuffer, 0, bufferSize, StreamReceived, null); 
    } 

    private void StreamReceived(IAsyncResult ar) 
    { 
     int bytesRead = 0; 
     try 
     { 
      lock (client.GetStream()) 
      { 
       bytesRead = client.GetStream().EndRead(ar); // просмотр длины сообщения 
      } 
     } 
     catch (Exception ex) 
     { MessageBox.Show(ex.Message); } 

     //An error happened that created bad data 
     if (bytesRead == 0) 
     { 
      Disconnect(); 
      return; 
     } 

     //Create the byte array with the number of bytes read 
     byte[] data = new byte[bytesRead]; 

     //Populate the array 
     for (int i = 0; i < bytesRead; i++) 
      data[i] = readBuffer[i]; 

     //Listen for new data 
     StartListening(); 

     //Call all delegates 
     if (DataReceived != null) 
      DataReceived(this, data); 
    } 

它是主网络的代码。

+3

你为什么使用:lock(client.GetStream())??? –

+0

看起来错误的东西(不知道它会导致你的问题,但我怀疑它可能)是对BeginWrite的调用。这是一个ASYNC(非阻塞)调用,所以在写入完成之前释放锁定,可能导致并发问题。尝试用正常的Write()调用替换它。 – Xcelled194

+0

此外,使用Buffer.BlockCopy,而不是一个for循环,从readbuffer获取字节到数据 – Xcelled194

回答

2

在收到数据后,我不知道您对数据做了什么,但很有可能您没有读取连接中的所有数据。您有:

bytesRead = client.GetStream().EndRead(ar); 

无法保证您读取的字节数是服务器发送的所有字节。例如,服务器可能发送了2,048字节,但当您调用Read时,仅有1,024字节可用。其余的人仍然“在途中”。作为documentation for NetworkStream.Read说:如可用,直到由尺寸参数

你可能会得到部分数据包中指定的字节数

读操作读取尽可能多的数据。如果您的DataReceived处理程序假定data缓冲区包含完整的数据包,那么您将遇到问题。

要可靠地从网络流中读取数据,您需要知道您应该读取多少数据,或者您需要记录分隔符。有些事情必须确保,如果您希望在您尝试处理完整数据包之前完成一个完整的数据包,您将获得。你的代码只是检查bytesRead是不是0.如果是其他任何东西,你只需传递它。除非你的DataReceived处理程序知道如何缓冲部分数据包,否则这将是一个问题。

另一个说明,你真的不需要锁定网络流。除非你可以从同一个流中读取多个线程。那将是灾难性的。放开锁。你不需要它。

+0

谢谢,吉姆,快速收到数据的样子,看起来好像它是时时刻刻切割和混合的流,所以假设它是问题所在。将尽力改善明天收到的数据。 不能投票给你,至今还没有足够的声望:-( –