0

Linux 缓冲所有在套接字上接收到的消息。但在收到之前,这条消息有一个开始和一个结束。Linux 将这些消息顺序写入缓冲区,因此丢失了消息末尾的信息。

我知道在 Linux 中我可以使用 cmsg_header。但 Windows 不提供 send-/recvmsg() 程序。如何确定缓冲区平台无关的消息结束?

4

5 回答 5

5

我不确定 TCP/IP 连接是否正在交换分隔良好的消息。路由器可以对数据包进行分段。(所以cmsg_header可能不可靠)。

我所知道的所有基于 TCP/IP 的协议(HTTP、SMTP、X11、RPCXDR)都在应用程序级别处理消息组织。您的应用程序库需要以某种方式知道“消息”何时以及何时开始或结束。

于 2012-11-11T16:29:50.683 回答
4

只需按网络顺序在前 4 个字节中发送消息的长度。那么你就不会有这个问题了。

于 2012-11-11T16:31:49.020 回答
2

我认为 Winsock 等价于sendmsg,recvmsgWSASendMsgWSARecvMsgLPWSAMSG根据文档,他们采用的参数是基于 Posix.1g 规范的 msghdr 结构的结构。

于 2012-11-11T16:41:49.843 回答
1

面向网络的应用程序通常具有清晰的传输/业务逻辑分离。

业务层只操作整个消息。传输将整个消息传递到上游业务层,可能会从片段中组装连续的流,重新切片并将其重新解释为一系列消息。

传输层通常使用 [size(length=S)][payload(variable length)] 形式的协议消息与远程传输层通信。其中 [size] 是单个数字,其编组长度 S 为所有通信方所知。

传输层做的第一件事是等待从下游(异步或同步,无关紧要)接收 S 字节到临时缓冲区。完成后,它会解组接收到的数据并知道要接收的有效载荷 L 的长度。

一旦已知有效载荷 L 的长度,传输将等待从下游接收 L 个字节到临时缓冲区(可能必须组合多次读取),一旦完成,它就会通知应用层将整个组装消息传递到单个缓冲区中。

于 2012-11-11T16:37:49.130 回答
1

Linux 将这些消息顺序写入缓冲区,因此丢失了消息末尾的信息。

这是不正确的。接收端永远不会丢失任何“[关于]消息结尾的信息”。TCP 是一种字节流协议。您send()的 s 或write()s在 sender 处连接到其套接字发送缓冲区,然后从那里以 TCP 段和 IP 数据包的形式传输数据,但是传输决定这样做。

如果你想通过 TCP 发送消息,你必须完全自己实现它们。常用技术:

  • 在消息前发送一个长度字
  • 封装消息,例如在 STX 和 ETX 之间,如果它出现在消息中,对 ETX (ESC ETX) 进行适当的转义,因此在消息中出现时对 ESC 本身 (ESC ESC) 进行转义
  • 使用自描述协议,例如 XML。
于 2012-11-13T07:34:04.373 回答