2016-09-25 140 views
1

遗憾的英语不好怪异的行为

为什么,如果我有服务器上的两个send() -s,并在客户端上的两个recv() -s,有时第一recv()将从服务器获取第二个send()的内容,而不是仅仅取第一个的内容,并让其他recv()采取其他send()的“适当和适当的”内容?

如何以其他方式获得此项工作?

回答

1

这是设计。

TCP流是可以在两个端点之间发送字节的通道,但传输是基于流而不是基于消息的。

如果你想发送消息,那么你需要对它们进行编码......例如,通过预先设置一个“大小”字段来通知接收方有多少字节可以用于主体。

如果您发送100个字节,然后发送其他100个字节,接收器很可能会一次看到200个,或者甚至在两个不同的读取命令中看到50个150个。如果你想要消息边界,那么你必须自己将它们放入数据中。

有一个允许发送消息的较低层(数据报),但是它们的大小是有限的,并且不能保证传送(即可能会丢失一条消息,将被复制或者发送两条消息将以不同的顺序到达)。 TCP流构建在此数据报服务之上,并实现在两个端点之间可靠传输数据所需的所有逻辑。

作为替代方案,有一些库设计用于在端点之间提供可靠的消息传递,如ZeroMQ

+0

但是我怎么能告诉第二个'send()'不发送任何东西到第一个'rec()'?你的解决方案让我用'send()2'做到“text 2”,而不是与'recv()1'中接受的“text 1”混合。但后来我放弃了'send()2'的数据,因为它的发送没有人等待它发送文本。我如何syncronized之间确切的发送和确切的recv? –

+0

@dfsfg你不能。这就是答案的要点。这些功能不会那样工作。 –

0

很可能你使用SOCK_STREAM类型的套接字。这是一个TCP套接字,这意味着您将数据推送到一边,并以相同的顺序从另一边获取数据,而不会丢失数据块,但是没有分隔符。所以send()只是发送数据而recv()接收当前可用的所有数据。

您可以使用SOCK_DGRAM,然后使用UDP。但是在这种情况下,每个send()都将发送一个数据报,并且recv()将收到它。但你不能保证你的数据报不会被洗牌或丢失,所以你将不得不自己处理这些问题。最大数据报大小也有限制。

或者你可以坚持TCP连接,但你必须自己发送分隔符。