为 posix recv 设置超时会导致丢失 udp 数据包吗?
Can setting a timeout for posix recv cause lost udp packets?
我发现 this answer 如何为 posix 套接字设置超时。该答案的 linux 部分:
// LINUX
struct timeval tv;
tv.tv_sec = timeout_in_seconds;
tv.tv_usec = 0;
setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, (const char*)&tv, sizeof tv);
以及 posix 文档中的引述:
SO_RCVTIMEO
Sets the timeout value that specifies the maximum amount of time an input function waits until it completes. It accepts a timeval
structure with the number of seconds and microseconds specifying the
limit on how long to wait for an input operation to complete. If a
receive operation has blocked for this much time without receiving
additional data, it shall return with a partial count or errno set to
[EAGAIN] or [EWOULDBLOCK] if no data is received. The default for this
option is zero, which indicates that a receive operation shall not
time out. This option takes a timeval structure. Note that not all
implementations allow this option to be set.
我不明白的是:这会导致丢失 udp 包吗?
收到udp包超时怎么办?
还相关:setting timeout for recv fcn of a UDP socket
PS:我知道UDP本质上是不可靠的,所以我的问题实际上主要是关于处理udp消息时发生超时的情况。
否;它不会让你更有可能丢包。
查看网络传输如何在较低级别发生;你有网卡。当此卡接收数据时,无论您的程序在做什么,它都会将数据存储到自己的内存区域中。当你打电话给 recv;您要求 OS 将数据从网卡内存移动到您的程序内存。这意味着如果您的线程正在做其他事情时有一个数据包进来;它不仅会被丢弃,还会在您的线程下次获取数据时进行处理。
如果您的线程没有足够频繁地调用 recv;那么网卡的内存就会变满。发生这种情况时,无法存储新数据包;如果它使用 TCP,那么路由器将被告知它无法处理它;如果它是 UDP,那么它将被简单地丢弃。正是这一部分使 UDP 本质上不可靠,因为它可能在数据包传输过程中的任何时候发生。
超时会影响线程等待数据出现在网卡内存区域的时间;除非你再也不打电话给 recv;不影响丢弃的数据包。
答案是否定的,丢失 UDP 数据将违反 POSIX:
The recv() function shall return the length of the message written to the buffer pointed to by the buffer argument. For message-based sockets, such as SOCK_DGRAM and SOCK_SEQPACKET, the entire message shall be read in a single operation.
据推测,当使用 MSG_WAITALL
选项时,“部分计数”只会发生在基于连接的套接字上。
话虽这么说,SO_RECVTIMEO
的使用通常不受欢迎,在套接字上实现超时的“正确”方法是使用非阻塞套接字和 select()
。这是出于历史原因,而不是因为设置超时在某种程度上本质上是糟糕的设计或其他原因。如果您坚持使用 SO_RECVTIMEO
,请注意潜在的可移植性问题:
- POSIX 提及
SO_RECVTIMEO
,但 does not require it
- 在 Windows 上,rcv() 中的超时将 put the socket in a bad state,您应该在之后立即关闭它。在 POSIX 上,您可以(根据我的经验)在
SO_RECVTIMEO
引起的超时后仍然使用套接字,但有人可能会争辩说这不是规范 100% 保证的
我发现 this answer 如何为 posix 套接字设置超时。该答案的 linux 部分:
// LINUX
struct timeval tv;
tv.tv_sec = timeout_in_seconds;
tv.tv_usec = 0;
setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, (const char*)&tv, sizeof tv);
以及 posix 文档中的引述:
SO_RCVTIMEO
Sets the timeout value that specifies the maximum amount of time an input function waits until it completes. It accepts a timeval structure with the number of seconds and microseconds specifying the limit on how long to wait for an input operation to complete. If a receive operation has blocked for this much time without receiving additional data, it shall return with a partial count or errno set to [EAGAIN] or [EWOULDBLOCK] if no data is received. The default for this option is zero, which indicates that a receive operation shall not time out. This option takes a timeval structure. Note that not all implementations allow this option to be set.
我不明白的是:这会导致丢失 udp 包吗? 收到udp包超时怎么办?
还相关:setting timeout for recv fcn of a UDP socket
PS:我知道UDP本质上是不可靠的,所以我的问题实际上主要是关于处理udp消息时发生超时的情况。
否;它不会让你更有可能丢包。
查看网络传输如何在较低级别发生;你有网卡。当此卡接收数据时,无论您的程序在做什么,它都会将数据存储到自己的内存区域中。当你打电话给 recv;您要求 OS 将数据从网卡内存移动到您的程序内存。这意味着如果您的线程正在做其他事情时有一个数据包进来;它不仅会被丢弃,还会在您的线程下次获取数据时进行处理。
如果您的线程没有足够频繁地调用 recv;那么网卡的内存就会变满。发生这种情况时,无法存储新数据包;如果它使用 TCP,那么路由器将被告知它无法处理它;如果它是 UDP,那么它将被简单地丢弃。正是这一部分使 UDP 本质上不可靠,因为它可能在数据包传输过程中的任何时候发生。
超时会影响线程等待数据出现在网卡内存区域的时间;除非你再也不打电话给 recv;不影响丢弃的数据包。
答案是否定的,丢失 UDP 数据将违反 POSIX:
The recv() function shall return the length of the message written to the buffer pointed to by the buffer argument. For message-based sockets, such as SOCK_DGRAM and SOCK_SEQPACKET, the entire message shall be read in a single operation.
据推测,当使用 MSG_WAITALL
选项时,“部分计数”只会发生在基于连接的套接字上。
话虽这么说,SO_RECVTIMEO
的使用通常不受欢迎,在套接字上实现超时的“正确”方法是使用非阻塞套接字和 select()
。这是出于历史原因,而不是因为设置超时在某种程度上本质上是糟糕的设计或其他原因。如果您坚持使用 SO_RECVTIMEO
,请注意潜在的可移植性问题:
- POSIX 提及
SO_RECVTIMEO
,但 does not require it - 在 Windows 上,rcv() 中的超时将 put the socket in a bad state,您应该在之后立即关闭它。在 POSIX 上,您可以(根据我的经验)在
SO_RECVTIMEO
引起的超时后仍然使用套接字,但有人可能会争辩说这不是规范 100% 保证的