通过c中的套接字原子地发送整数

Sending integer atomically over a socket in c

我有一个简单的客户端,它通过套接字从服务器接受单个 uint32_t。使用此处多次出现的解决方案(例如 transfer integer over a socket in C)似乎可行,但是:

在文件上调用 "read" 时,我知道系统不能保证一次读取消息的全部内容,因此它 returns 读取的字节数。通过网络套接字接受 4 个字节时不会发生同样的情况吗?

如果这不可能发生,那是为什么?如果可以,如何确保发送是 "atomic",或者是否有必要自己拼凑字节?

如果底层协议是TCP/IP,是面向流的(没有"packets"或"messages",只有两个字节流),那么是。

您需要注意管理读取的数据量,以便了解每个 "message"(在您的情况下为单个整数)的开始和结束位置。

When calling "read" on files I know that the system is not guaranteed to read the entire content of the message at once

这是错误的,如果请求的字节数可用,则读取它们:

POSIX read manual says: The value returned may be less than nbyte if the number of bytes left in the file is less than nbyte

这至少对于常规文件是正确的,对于管道等类似情况则不同。

Couldn't the same happen when accepting 4 bytes over a network socket?

(我想你在谈论 TCP 套接字。)套接字可能会发生这种情况,因为底层协议可能会以任何合适的方式传输你的字节(例如阅读 TCP 碎片),唯一确保的是如果接收到字节收到的顺序与发送的顺序相同。因此,要读取给定数量的字节,您必须尝试用几个 read 最终读取这些字节。这通常是通过遍历 read 直到接收并读取所需的字节来完成的。

根据套接字类型,可以使用不同的协议。 SOCK_STREAM(对应于网络套接字上的TCP)是一种面向流的协议,因此数据包可能会被发送方、接收方或中间的任何设备重新组合。

但是SOCK_DGRAM (UDP) 或SOCK_SEQPACKET 实际上发送的数据包是无法更改的。在那种情况下,同一个数据包中的 4 个字节保证在同一个读取操作中可用,除非接收缓冲区太小。来自 man socket:

If a message is too long to fit in the supplied buffer, excess bytes may be discarded depending on the type of socket the message is received from

因此,如果您想要 atomic 块,请使用数据包协议而不是流协议,并确保有足够大的接收缓冲区。