11

再次初学者问题:对我不久前提出的问题的跟进。

我试图理解这个同步套接字教程http://msdn.microsoft.com/en-us/library/6y0e13d3.aspx,特别是下面代码中的一行。

问题: 我想确保我正确理解程序流程。handler.Receive (bytes) 什么时候返回?当它“溢出”并接收到超过 1024 字节时,它是否返回并存储int bytesRec** 中接收到的字节数?**如果是这样,这听起来可能很傻,如果更多字节到达,因为它将 1024 字节存储在 *数据* 变量中并且不监听当时可能到达的更多字节,会发生什么?还是我不应该担心,让 .net 来处理?

Socket handler = listener.Accept();
data = null;

// An incoming connection needs to be processed.
while (true) {
    bytes = new byte[1024];
    int bytesRec = handler.Receive(bytes);
    // My question is WHEN does the following line
    // get to be executed
    data += Encoding.ASCII.GetString(bytes,0,bytesRec);
    if (data.IndexOf("<EOF>") > -1) {
        break;
    }
}
4

1 回答 1

12

handler.Receive(bytes) 什么时候返回?

文档:

如果没有数据可供读取,Receive 方法将阻塞直到数据可用,除非使用 Socket.ReceiveTimeout 设置了超时值。如果超过了超时值,接收调用将抛出一个 SocketException。如果您处于非阻塞模式,并且协议栈缓冲区中没有可用的数据,则 Receive 方法将立即完成并抛出 SocketException。您可以使用 Available 属性来确定数据是否可供读取。当 Available 为非零时,重试接收操作。


当它“溢出”并接收到超过 1024 个字节时,它是否返回并存储在 int bytesRec 中接收到的字节数?

不,它总是返回已读取的字节数。如果没有,你怎么知道哪些部分bytes包含有意义的数据,哪些部分仍未使用?

了解套接字通常如何工作非常重要:字节可能会以数据包的形式到达,但就接收方而言,每个字节都应该被独立考虑。这意味着不能保证您将获得发送者发送的块中的字节,当然也不能保证有足够的数据来填满您的缓冲区。

如果您只想处理 1024 字节块中的传入数据,则您有责任继续调用Receive,直到它向您释放总共 1024 字节。

如果是这样,这听起来可能很愚蠢,如果更多字节到达,因为它将 1024 字节存储在变量中,而不是监听当时可能到达的更多字节,会发生什么?

让我们重申一下,Receive不会在缓冲区中存储 1024 个字节,因为那是缓冲区的大小。它将存储多达1024 个字节。

如果网络堆栈内部缓冲的数据多于缓冲区可以容纳的数据,则将返回 1024 个字节,其余的将保留在网络堆栈的缓冲区中,直到您Receive再次调用。如果Receive已经开始将数据复制到您的缓冲区,并且此时从网络接收到更多数据,那么很可能会发生这些将不得不等待下一次Receive调用。

毕竟,从来没有人提供任何保证Receive可以为您提供所有数据(尽管这当然是可取的,而且大多数情况下都会发生这种情况)。

于 2013-03-20T12:58:32.253 回答