1

如果我编写一个服务器,如果我不知道该客户端如何发送数据,我如何实现接收功能以获取特定客户端发送的所有数据?
我正在使用 TCP/IP 协议。

4

6 回答 6

4

如果您确实没有定义协议,那么您所能做的就是在客户端到达时接受来自客户端的字节组。如果没有定义的协议,就无法知道您已收到客户端发送的“所有字节”,因为在传输过程中客户端和服务器之间的某处总是有可能发生网络故障,导致最后一部分流不到达服务器。在这种情况下,您会从 TCP 套接字获得通常的流结束指示(例如,如果您使用的是非阻塞套接字,则 recv() 返回 0 或 EWOULDBLOCK),因此您会知道您不会从客户端接收更多数据(因为 TCP 连接现在已断开)......但那不是

根据您的应用程序,这可能就足够了。如果没有,那么您必须制定一个协议,并相信您的客户会遵守该协议的规则。让客户端首先发送一个标头,说明它计划发送多少字节是一个好方法;或者让它发送一些特殊的“好的,这就是我要发送的全部”指示也是可能的(尽管如果你这样做,如果特殊指示可能偶然出现在数据本身中,你必须注意误报)

于 2011-02-26T01:01:11.197 回答
1

一次调用send不等于一次调用recv。要么发送一个标头,让接收者知道需要多少数据,要么发送某种标记值,让接收者知道何时停止读取。

于 2011-02-25T23:56:03.657 回答
1

这取决于你想如何设计你的协议。

ASCII 协议通常使用特殊字符来分隔数据的结尾,而二进制协议通常首先将数据的长度作为固定大小的整数(双方都知道这个大小)发送,然后是可变长度的数据。

于 2011-02-26T00:01:29.033 回答
1

您可以将大小与数据合并到一个缓冲区中,然后调用一次发送。人们通常使用前 2 个字节来表示数据包中的数据大小。像这样,

|size N (2 bytes) | data (N bytes) |

在这种情况下,您可以包含 65535 字节长的自定义数据。

由于 TCP 不保留消息边界,因此调用 send 多少次都没有关系。您必须在收到之前调用接收,N size(2 bytes)然后您可以继续调用接收直到N bytes data您发送。

更新:这只是展示如何在 TCP 中检查消息边界的示例。安全/加密是一个完全不同的故事,它值得一个新的话题。也就是说,不要简单地复制这个设计。:)

于 2011-02-26T00:01:44.493 回答
1

TCP 是基于流的,因此没有“完整消息”的概念:它由更高级别的协议(例如 HTTP)提供,或者您必须自己发明它。如果您可以随意使用 UDP(基于数据报),则无需多次执行 send() 或 receive()。较新的SCTP 协议本身也支持消息的概念。

使用 TCP,要实现消息,您必须告诉接收者消息的大小。它可以是前几个字节(通常是 2 个,因为它允许消息高达 64K ——但如果您可能在不同系统之间进行通信,则必须注意字节顺序),或者它可能更复杂。例如,HTTP 具有一整套规则,接收者根据这些规则确定消息的长度。其中之一是Content-LengthHTTP 标头,它包含一个字符串,表示消息正文中的字节数。仅包含标头的 HTTP 消息仅由空行分隔。如您所见,没有简单(或标准)的答案。

于 2011-02-26T00:19:34.627 回答
0

TCP 是一种基于流的协议。因此,TCP 中没有数据长度的概念,就像键盘输入没有数据长度的概念一样。

因此,由更高级别的协议来指定消息的结尾。这可以通过在协议中包含数据包长度或指定特殊的消息结束字节序列来完成。

例如 HTTP 标头以双\r\n序列终止,并且可以从Content-Length标头中获取消息正文的长度。

于 2011-02-26T01:00:22.330 回答