我正在构建一个库,用于维护c ++中应用程序之间的网络连接。在一些debuging期间,我发现从socket获得的一些信息似乎不完整。至关重要的是这个信息是完整的,因为如果我用协议缓冲区的库解码它,我需要完整的消息。
这种现象并不是一成不变的。有时我从套接字获取所有数据,有时不是。测试过程如下:启动服务器,多次启动客户端。我得到的是函数receive()
的输出,它描述了一些变量的值如何变化。其中一个是我用来存储数据的缓冲区的大小。该大小告诉我缓冲区中有多少数据。在此特定测试中,客户端发送两个大小为3(字节)的消息。我希望缓冲区大小是3的倍数。但是,有时大小是4!这意味着程序读取一个完整的消息和第二个消息的1/3。我不明白为什么我总是先完成消息。否则,protobuf将终止程序。
我认为tcp / ip应该注意我得到完整的消息。我的问题是我不知道提前的大小。我希望收到完整的信息,以便我能将其解释为核心。
答案 0 :(得分:11)
TCP是基于流的协议,而不是基于消息的协议。 TCP不知道您的消息何时开始或结束,因此没有保证您将在一次通话中获得完整的消息。也没有任何保证,您只能 一条完整的消息。您必须缓冲收到的数据,并自行将其拆分为消息。如果您没有收到完整的消息,请存储您收到的数据,并等待其余数据到达。
答案 1 :(得分:2)
允许TCP将您的数据分段成多个数据报,这些数据报在收件人中按顺序汇编。您可以保证您的数据最终会按照发送顺序到达。但是,您发送的部分数据可能比其他部分提前到达。
您的体验可能是,当您致电receive
时,您发送的部分数据已经到达您的计算机,但部分数据仍在通过网络发送。您必须缓冲收到的数据部分,并等到收到完整的“消息”。您可以处理此问题的一种方法是在每条消息的开头发送一个固定长度的记录,该记录对消息中剩余字节的长度进行编码。例如,您可以发送一个4字节的无符号长网络字节顺序,然后是那么多字节的数据。