接收使用C套接字发送的所有数据

时间:2011-02-25 23:53:10

标签: c++ c sockets winsock winsock2

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

先谢谢了。

6 个答案:

答案 0 :(得分:4)

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

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

答案 1 :(得分:1)

send的一次通话不等于对recv的一次通话。要么发送标题,要么接收者知道要预期多少数据,要么发送某种标记值,以便接收者知道何时停止阅读。

答案 2 :(得分:1)

这取决于您希望如何设计协议。

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

答案 3 :(得分:1)

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

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

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

由于TCP不保留消息边界,因此调用send的次数无关紧要。在收到N size(2 bytes)之前,您必须先致电接听,然后才能继续致电接收,直到您发送N bytes data

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

答案 4 :(得分:1)

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

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

答案 5 :(得分:0)

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

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

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