【问题标题】:Will TCPStream.Read block until ALL data is received in send message?TCPStream.Read 在发送消息中收到所有数据之前会阻塞吗?
【发布时间】:2011-09-13 09:49:18
【问题描述】:

我编写了一个多线程的简单服务器,它使用:

clientStream.Read(message, 0, 4096);

在客户端发送消息之前阻塞。然后代码继续处理该消息。

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

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

但我担心当我通过线路发送大量表格数据时,代码可能会在全部接收之前继续。

.Read 会阻塞直到收到整个发送的消息,还是在任何数据开始接收时解除阻塞?

【问题讨论】:

  • 请记住,TCP 不能让您发送/接收消息,它是一个流——很像读/写文件
  • 是的,我知道,消息是一个字节[],我的协议在字符串上运行。

标签: c# .net sockets tcp stream


【解决方案1】:

依靠发送来完成消息之间的描述是不好的形式。如果不是出于最简单的原因。我可以 telnet 进入你的服务器,然后很容易崩溃。

您需要创建一个有线协议。你有几个选择。

  • 始终期望消息的大小为无符号 32 位整数作为前 4 个字节,然后读取直到您填充了该数据量。

  • 指定消息结束分隔符。这意味着您将维护一个缓冲区。你用线外的数据填充它,快速扫描它以查找消息的结尾。找到消息后,将其扔给消息处理器,然后继续处理缓冲区中剩余的字节,重复第 1 步。

您可以查看STOMP 以获得基于文本的简单协议。

不要依赖您的数据包以良好定义的块作为消息分隔符发送。

【讨论】:

  • 这正是我的想法,感谢您为我节省了数小时的搜索时间,试图找出这个小消息。所以也许一个更好的示例数据包看起来像这样:#login[username][password]$
  • 另一个选项是消息处理器是否接受TextReader(假设协议是基于文本的)。这样,您不必在阅读之前知道消息的大小,也不必有消息结束分隔符,并且您可以在不使用太多内存的情况下读取大量消息。当然,这意味着必须有明确的方法来查找消息的结尾,而不必在字符级别上明确。
  • 我很好奇你会如何通过 telnet 进入我的服务器。我想我已经相当小心了......但我还在学习!
  • @Adrian 我的陈述过于戏剧化了。如果您假设所有读取都会产生完整的消息,我可以使用 telnet 发送不完整或空的消息。
  • 哈哈!我的流程有点多:try(Block until read)catch all,然后分析不良数据。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-12-23
  • 2011-07-05
  • 2023-04-11
  • 2014-10-07
  • 2013-08-25
  • 1970-01-01
相关资源
最近更新 更多