通过TCP套接字发送任意长度的多个数据的适当技术

时间:2011-11-09 02:30:52

标签: c sockets tcp

我很好奇在C中的套接字上发送任意长度的多个数据的正确方法。例如,如果要发送任意长度的“用户名”,任意长度的“主题”和任意长度的“消息”,发送这些消息的正确过程是什么。此外,我试图发送的数据可能不一定是空终止的,所以我不相信我可以仅基于空字节重新组装它。

我提出的方法将涉及读取服务器上接收的输入的前4个字节,并将其解释为第一个数据的大小,并从套接字读取该数据量并将其解释为第一个字符串,再读取4个字节并将其解释为第二个字符串的长度,然后准确读取多个字节并将其解释为第二个字符串,依此类推。但是,这似乎可能容易出错或者有一些可能导致错误的实现细节。有没有更好的方法来实现这一目标?

3 个答案:

答案 0 :(得分:2)

您想阅读有关序列化的内容。一些可能有用的链接:

http://en.wikipedia.org/wiki/Serialization

http://en.wikipedia.org/wiki/External_Data_Representation

http://en.wikipedia.org/wiki/Protocol_buffers

还有很多其他人。只要选择你的毒药。或者像你似乎在尝试一样写自己的,作为一种学习练习。

答案 1 :(得分:2)

您的提案是解决问题的一种方法。如果套接字正在使用像TCP这样的可靠传输,那么它不会“容易出错”,因为网络层可以保证数据以正确的顺序无损地传送。另一种方法是发送固定大小的结构,这样接收器将始终读取X字节并知道它已收到完整的消息。另一种方法是使用字段终止符,NUL(如您所建议的)或换行符;这是许多互联网协议所做的事情(例如HTTP,FTP)。另一个是使用序列化方法(如另一个答案所示)。这完全取决于您计划发送的数据类型以及不同类型系统之间数据的可移植性。

答案 2 :(得分:1)

为了避免您的发送/接收例程变得非常复杂,因为您的数据结构变得更加精细,我建议将问题分成不同的步骤:

  1. 写入可以通过TCP连接构建并发送N个字节的任意缓冲区的例程。 (这将涉及发送4字节长度前缀,然后发送N个字节,如您所述)。您可能还希望包含一个4字节的类型代码头,接收器可以使用它来轻松识别接收字节所代表的数据结构。

  2. 编写一个例程,将(您最喜欢的数据结构)转换为一系列保存在RAM中的N个字节。然后编写一个关联的例程,将RAM中保存的一系列N个字节反转换回(您最喜欢的数据结构)。

  3. 对要通过线路发送的任何其他数据结构重复步骤(2)。请注意,一旦有多种数据类型,(1)中提到的类型代码字段将使接收器更容易知道在完全接收到字节缓冲区后要调用哪个解转换例程。

    < / LI>

    完成上述操作后,您可以使用(1)中的通用发送/接收字节缓冲区代码从(2)​​传输任何数据结构,因此您不必为每个数据结构编写单独的发送/接收代码,这是一个很大的胜利。

    请注意,如果您担心可移植性,则需要确保将要发送的任何多字节整数或浮点值转换为big-endian(或小端,只要你是无关紧要的在发送它们之前,然后在接收它们之后将它们反转换回接收器上的本机端(但在你使用它们之前)。 (你还需要避免让memcpy()将C结构放入字节缓冲区的诱惑,因为不同的平台甚至不同的编译器版本可能会在内存中以不同的方式填充C结构,这将导致灾难性的结果,如果你的发件人和收件人没有运行完全相同的可执行文件)