msdn里面对Socket.Send所引发的SocketException没有做任何进一步的说明。按照VC6的惯例,只要有字节被发送,则Send不会返回-1。如果照此逻辑,则在C#里面只有当Socket.Send连一个字节也发不动的时候它才能产生SocketException。以上是我的猜想,应该是对的。但是该死的msdn为什么不做一下说明呢?也许我就猜错了。

解决方案 »

  1.   

    你能够告诉我你的程序架构是什么样的吗,你是如何在程序里面非阻塞的调用Send方法的,是否使用了Delegate回调的方法。希望能够贴一些比较完整的代码
      

  2.   

    如果是异步方法,EndSend()的返回值就是已发送字节数
      

  3.   

    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; } }
      

  4.   

    出现异常后我们不用知道到底传输了多少数据,而是将整个要传输的数据缓存重新在传输。这是因为,对于TCP协议,它是以字节流方式传输的,所有数据的传输都是由操作系统中的TCP层来负责的,TCP层将会一个数据包一个数据包的传送,然后接受端的TCP层也会一个数据包一个数据包的接收,它是一个比较可靠的协议,保证了接收的数据包不会次序混乱,而且不会丢失,如果丢失一个数据包TCP会将整个数据缓存都会重新传输,接收到的数据将会被丢弃。
        如果是UDP,UDP层不会负责这些重传等操作,所以重传的任务就由你的应用程序负责了,而且UDP层也会将出错的数据包丢弃掉。
        所以我们应该重传整个数据包。
      

  5.   

    我上面的那个函数有个假设:当发送抛出异常的时候,认为socket没有发送成功任何字节。如果有任何字节被成功发送,则发送函数应该返回发送成功字节数,并且不会抛出异常。在近期的使用中,我上面的那个函数工作很正常。因此,我对socket发送异常的假设,应该是正确的。但是没有ms的文档,我也不能就确信我的假设就一定是正确的。