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。
如二楼所说的回调是新线程,看看这边处理的时候那边是不是又回调了,然后你还。