TCPStream.Read会一直阻塞,直到接收完整个发送消息的所有数据吗?

5

我写了一个使用以下技术的多线程简单服务器:

clientStream.Read(message, 0, 4096);

阻塞直到客户端发送消息。然后代码继续处理该消息。

到目前为止,我只使用它来发送短命令。

ex. "#login[username][login]"

但我担心当我发送大量表格数据时,代码可能在所有数据接收之前继续运行。

那么,.Read方法会一直阻塞直到整个消息被接收,还是在开始接收任何数据时就解除阻塞?


请记住,TCP并不能让您发送/接收消息,它只是一个流 - 就像读/写文件一样。 - nos
是的,我知道,消息是一个byte[],但我的协议运行在字符串上。 - Adrian Seeley
1个回答

8
依赖Send to finish来区分消息是不好的做法,即使是最简单的原因也是如此。我可以通过Telnet进入您的服务器并轻松崩溃它。
您需要创建一个协议。您有几个选项。
- 始终将消息大小作为无符号32位整数作为前4个字节进行读取,然后读取直到填充了该数据量。 - 指定消息结束分隔符。这意味着您将保留缓冲区。您从线路上获取数据并快速扫描其是否为消息的结尾。一旦找到消息,就将其传递给消息处理器,然后继续使用缓冲区中剩余的字节,重复步骤1。
您可以查看STOMP以获取易于使用的基于文本的协议。
不要指望您的数据包以良好定义的块形式发送作为消息分隔符。

这正是我想到的,谢谢你节省了我数小时寻找那个小细节的时间。因此,一个更好的示例数据包可能看起来像这样: #login[用户名][密码]$ - Adrian Seeley
另一个选择是,如果消息处理器接受TextReader(假设协议是基于文本的)。这样,您在读取消息之前不必知道消息大小,也不必拥有消息结束分隔符,并且您可以潜在地读取大量消息而不使用太多内存。当然,这意味着必须有明确的方法来找到消息的结尾,但它不必在字符级别上清晰可见。 - svick
我很好奇你如何通过telnet访问我的服务器来使其崩溃。我认为我已经非常小心了...但我仍在学习中! - Adrian Seeley
@Adrian,我在我的陈述中过于夸张了。如果你认为所有的读取都会导致完整的消息,那么我可以使用telnet发送不完整或空的消息。 - Andrew T Finnell
哈哈!我的流程有点不同:尝试(阻塞直到读取)捕获所有异常,然后分析坏数据。 - Adrian Seeley

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接