关于非阻塞的Socket.Send() msdn里面对Socket.Send所引发的SocketException没有做任何进一步的说明。按照VC6的惯例,只要有字节被发送,则Send不会返回-1。如果照此逻辑,则在C#里面只有当Socket.Send连一个字节也发不动的时候它才能产生SocketException。以上是我的猜想,应该是对的。但是该死的msdn为什么不做一下说明呢?也许我就猜错了。 解决方案 » 免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货 你能够告诉我你的程序架构是什么样的吗,你是如何在程序里面非阻塞的调用Send方法的,是否使用了Delegate回调的方法。希望能够贴一些比较完整的代码 如果是异步方法,EndSend()的返回值就是已发送字节数 protected bool TrySend(SocketOp op, byte[] buf, int offset, int size) { lock(this) { if(op == null) { return false; } if(!op.socket.Connected) { return false; } bool ret = false; if(GetCanSend(op) > size) { Array.Copy(buf, offset, op.sendBuf, op.sendSize, size); op.sendSize += size; ret = true; } try { int send = op.socket.Send(op.sendBuf, op.sendOffset, op.sendSize - op.sendOffset, SocketFlags.None); op.sendOffset += send; while(send > 0 && op.sendOffset < op.sendSize) { send = op.socket.Send(op.sendBuf, op.sendOffset, op.sendSize - op.sendOffset, SocketFlags.None); op.sendOffset += send; } } catch(SocketException se) { if(se.NativeErrorCode == 10035) //would block { return ret; } else { System.Diagnostics.Trace.WriteLine(se); return false; } } if(op.sendOffset == op.sendSize) { op.sendOffset = 0; op.sendSize = 0; } return ret; } } 出现异常后我们不用知道到底传输了多少数据,而是将整个要传输的数据缓存重新在传输。这是因为,对于TCP协议,它是以字节流方式传输的,所有数据的传输都是由操作系统中的TCP层来负责的,TCP层将会一个数据包一个数据包的传送,然后接受端的TCP层也会一个数据包一个数据包的接收,它是一个比较可靠的协议,保证了接收的数据包不会次序混乱,而且不会丢失,如果丢失一个数据包TCP会将整个数据缓存都会重新传输,接收到的数据将会被丢弃。 如果是UDP,UDP层不会负责这些重传等操作,所以重传的任务就由你的应用程序负责了,而且UDP层也会将出错的数据包丢弃掉。 所以我们应该重传整个数据包。 我上面的那个函数有个假设:当发送抛出异常的时候,认为socket没有发送成功任何字节。如果有任何字节被成功发送,则发送函数应该返回发送成功字节数,并且不会抛出异常。在近期的使用中,我上面的那个函数工作很正常。因此,我对socket发送异常的假设,应该是正确的。但是没有ms的文档,我也不能就确信我的假设就一定是正确的。 C#如何传递函数,在别的类中执行 向高手求助, 与验证码识别关相, 请问如何实现字符的切分 求...Enumerable.Join方法讲解 C#Random的疑问 dataGridView 行选定的问题 删除问题 什么导出来文本里包含HTML源码? 求教:现在很多网站都有那种在线咨询功能,请问是怎么实现的? 急求一本书windows forms programming in c#(电子版) 利用字体生成Code128C 条码_亲测可用! 数据库操作时,用数据组件设计时写好参数好,还是在程序动态生成组件并自己写SQL好呀。 如何创建表间关系(datarelation)
{
lock(this)
{
if(op == null)
{
return false;
} if(!op.socket.Connected)
{
return false;
} bool ret = false;
if(GetCanSend(op) > size)
{
Array.Copy(buf, offset, op.sendBuf, op.sendSize, size);
op.sendSize += size;
ret = true;
} try
{
int send = op.socket.Send(op.sendBuf, op.sendOffset, op.sendSize - op.sendOffset, SocketFlags.None);
op.sendOffset += send;
while(send > 0 && op.sendOffset < op.sendSize)
{
send = op.socket.Send(op.sendBuf, op.sendOffset, op.sendSize - op.sendOffset, SocketFlags.None);
op.sendOffset += send;
}
}
catch(SocketException se)
{
if(se.NativeErrorCode == 10035) //would block
{
return ret;
}
else
{
System.Diagnostics.Trace.WriteLine(se);
return false;
}
} if(op.sendOffset == op.sendSize)
{
op.sendOffset = 0;
op.sendSize = 0;
} return ret; } }
如果是UDP,UDP层不会负责这些重传等操作,所以重传的任务就由你的应用程序负责了,而且UDP层也会将出错的数据包丢弃掉。
所以我们应该重传整个数据包。