2010-12-05 62 views
5

我已经试验了两个程序之间的异步TCP套接字消息,用于传递数据,数字和/或文本。我所做的是在每封邮件的开头使用一个关键字,然后用“|”分隔这些值。字符。因此,一个消息可能是这样的:如何分离TCP套接字消息

“数据| 490 | 40517.9328222222 | 1 | 6 | 11345 | 11347 | 11344 | 11345 | 106 | 40517.8494212963”

我设置读取缓冲区大小为1024,作为最的消息将在这个长度内。但是有时我可能会发送很多短消息,其中几个消息的长度小于1024个字符,看起来它会一次读取。如果我发送超过1024个字符的消息,它将被拆分。所以我正在寻找一些关于如何处理这个问题的建议。我应该使用一些特殊字符来开始和/或结束每封邮件吗?希望你对此有所建议。

回答

5

最简单的方法是在每条消息的开头发送消息长度,这样就可以在小端和大端硬件上运行。

这可以帮助您的接收器有效地预分配其接收缓冲区。

+0

谢谢!序列化意味着什么?它适用于标准的Windows操作电脑吗?有了你最后的评论,这是否意味着我应该根据收到的消息更改缓冲区大小?这将如何工作。由于消息的长度在消息已经被读取之前是未知的,所以我不明白你的意思。顺便说一句,是否有必要在发送方分解消息,还是不会影响性能?大小将是每200毫秒50个字符的消息,并且很少有50,000-400,000个字符的消息。 – bretddog 2010-12-06 11:27:59

+0

序列化仅意味着“以字符串形式输出”。 @terminus的建议将是一种合理的方式 - 将消息长度转换为固定长度的字符串,以便在接收端轻松转换回'unsigned int'。您可以请求先将这么多字节读入一个固定大小的缓冲区,然后分配一个缓冲区来接收剩余的消息。不要在发送端分割消息 - TCP/IP堆栈将执行任何所需的分组。 – 2010-12-06 12:28:51

3

最简单的方法是在数据包的开头发送消息的大小。这样你就可以知道要读取多少数据。所以它看起来像:

00015MESSAGE|1|2 ... 

大小字段有一个固定的大小是很重要的。

您也可以将此大小字段设置为二进制,但您似乎正在发送纯文本,因此您可以通过这种方式获得可以人工读取的大小字段。

0

您可以通过将唯一字节(如255不以ASCII显示)填充到缓冲区大小并在接收端取消选中它们来解决该问题。 对我来说,这不是一个非常好的和聪明的解决方案,但它确实有效。

或者你也可以尝试在每个包的开头发送整个数据包的长度,这是一个更加混乱的动作,并且当填充技术正确完成时更有效地工作。然后 合并包会是这个样子(方案):

05|.....02|..03|... 
0

的方式TAR这么做,是使用固定大小的块。 TAR中的每个块都是512字节,并且文件(消息)可能完全包含在该块中。如果不是,则前512个字节包含一个标题,指定需要为该文件(消息)读取多少个附加块。

Tar显然不是TCP应用程序,但它具有类似的数据解析或处理要求。

此外,您的大小小于512字节,但也许它是有意义的,包括一个64字节的块,或128或其他,并将所有的数据包装在这种大小的包。你会因为“盒子大小”的开销而失去效率,但是你可能会获得数据处理算法的效率和简单性。

1

有几种方法。

  1. 以每条消息为前缀的长度字。

  2. 每个消息的STX/ETX样式包装,因此您可以看到它的起始位置和结束位置。这需要转义出现在数据中的ETX字​​节,而这又需要转义ESC字节。

  3. 自描述协议,例如XML或基于类型长度值的协议。

1

协议就是一切。对于我的聊天应用程序,我使用的参数协议,当您运行

shutdown.exe -s -f -t 30 

喜欢,但然后插槽我用这个

join John%20Doe   ' %20 for space 
msg This%20Is%20a%20test ' again %20 for space 

这样,它并不重要,如果你的数据是发送异步:d希望这帮助