C套接字原子非阻塞读

C socket atomic non-blocking read

我正在实现一个 TCP/IP 服务器应用程序,它在边缘触发模式下使用 epoll 并执行非阻塞套接字操作。客户端正在使用没有 epoll 的简单阻塞操作。

我不知道如何在服务器端实现 "atomic reads"。要解释我对 "atomic read" 的意思,请看这个简单阻塞操作的例子:

但在 epoll + 非阻塞操作的情况下,可能会发生这种情况:

在这种情况下,读取不是 "atomic"。不能保证当数据是通过一次写入操作写入时,读取将 return 整体,一片。

是否可以知道数据何时是部分数据?我知道一种解决方案是始终将数据大小附加到开头,或者另一种可能是始终关闭并重新打开连接,但我不想这样做:因为我认为内核必须知道不是完整的"package"(那个单元怎么叫 BTW?)到了,因为它保证了阻塞操作的原子性。

非常感谢!

TCP 是基于流的,而不是面向消息的。即使在阻塞套接字的情况下,您也不能保证应用程序发送的内容会一次性完成。 TCP 将决定自己的路线。

因此,"atomic" 读取它的意愿取决于应用程序。例如:

应用程序协议应规定消息应以长度字节作为前缀。长度字节通知对等方感兴趣的应用程序数据的大小。当然,应用程序应该知道两字节长度指示符何时开始。

[2 byte msg length][Data bytes of interest]

基于此信息,正在读取的应用程序应采取行动。它应该轮询套接字,直到它接收到所有由 msg 长度字节指示的字节。然后才处理数据。

如果您需要 "atomic" 读取而不是部分读取,您可以在 recv 中使用 MSG_PEEK 标志。这不应从套接字缓冲区中删除数据。应用程序查看套接字,根据 return 值查看套接字缓冲区中是否包含所需数量的数据。

ret = recv(sd, buf, MAX_CALL_DATA_SIZE, MSG_PEEK);