日期:2014-05-17  浏览次数:21190 次

C# socket异步接收数据丢失的问题
Socket sock = (Socket)ar.AsyncState;
   
  int nBytesRec = sock.EndReceive(ar);  
  if (nBytesRec > 0)
  {
  try
  {
  //把当前接收到的缓存放到 tempByt
  Array.Copy(this._buffer, 0, tempByt,this._position, nBytesRec);
  this._position += nBytesRec;
   
  //报文长度数据
  byte[] lenByt = new byte[4];
  Array.Copy(tempByt, 0, lenByt, 0, 4);

  string bufferstr = Encoding.ASCII.GetString(tempByt);//测试
  string allstr = Encoding.ASCII.GetString(this._buffer);//测试

  //报文长度
  this._length = int.Parse(Encoding.ASCII.GetString(lenByt));
  if (this._position < this._length)
  {
  if (sock.Poll(-1, SelectMode.SelectRead)) // 已经有数据等待接收
  {
  //继续接收数据
  ReceiveMessage();
  }  
  }
  else
  {
  //接收到的数据
  byte[] recByt = new byte[this._length-8];
  Buffer.BlockCopy(tempByt, 0, recByt, 8, this._length - 8);
  packetList.Enqueue(recByt);//放进队列  

  //移除当前已处理的数据包
  Array.Clear(tempByt, 0, this._length);
  this._position = this._position - this._length;

  if (sock.Poll(-1, SelectMode.SelectRead)) // 已经有数据等待接收
  {
  //继续接收数据
  ReceiveMessage();
  }  
  }
  }
  catch (Exception ex)
  {
  this.Close();
  throw new Exception(ex.ToString());
  }
  }
  else
  {
  sock.Shutdown(SocketShutdown.Both);
  sock.Close();
  }

比如我发送了320字节长度的Byte[]数据,第一次总是接收到期15个字节,经调试第二次接收的时候第16,17个字节丢失.请问如何才能完全接收呢?

------解决方案--------------------
TCP是流式协议,所以对端通过多个包发送的数据的确可能在接收端只用一次recv就全部收到,尤其是异步方式的情况。也可能只收到一个包的一部分。 

所谓流式协议就是说没有所谓的包的概念,通信双方只能将数据作为流来处理。数据中的语义必须自己定义边界。 

另外,就我所知异步方式就不存在什么阻塞问题了。.net的框架自动帮你解决了这个事情。需要注意的是回调函数实际上是处于另一个线程的上下文。因此你需要注意异步回调函数执行过程的线程同步问题,以及STAThreading下窗口控件的调用问题。
------解决方案--------------------
if (this._position < this._length) 

if (sock.Poll(-1, SelectMode.SelectRead)) // 已经有数据等待接收 

//继续接收数据 
ReceiveMessage(); 
}

ReceiveMessage();
这个里面做了什么,

可以在接收一个包长度后,同步读取该包的剩下部分。
------解决方案--------------------
我猜你对数组的操作有问题,丢掉了些内容。
请试验不做任何处理,一直观察接收的_buffer。
如二楼所说的回调是新线程,看看这边处理的时候那边是不是又回调了,然后你还。