C++ 为posix recv设置超时是否会导致udp数据包丢失?

C++ 为posix recv设置超时是否会导致udp数据包丢失?,c++,sockets,posix,C++,Sockets,Posix,我找到了如何为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文档中的引用: 设置超时值,该值指定输入函数在完成之前等待的最长时间。它接受一个timeval 结构的秒数

我找到了如何为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文档中的引用:

设置超时值,该值指定输入函数在完成之前等待的最长时间。它接受一个timeval 结构的秒数和微秒数指定 限制等待输入操作完成的时间。如果 接收操作在没有接收的情况下被阻止了这么长时间 附加数据,返回时应将部分计数或errno设置为 [EAGAIN]或[EWOULDBLOCK],如果未收到数据。此选项的默认值 选项为零,表示接收操作不应 时间到。此选项采用timeval结构。请注意,并非所有 实现允许设置此选项

我不明白的是:这会导致udp包丢失吗? 如果在接收udp包时达到超时怎么办

还涉及:


PS:我知道UDP本质上是不可靠的,所以我的问题主要是关于在处理UDP消息时超时的情况

No;这不会让你更容易丢包

查看网络传输如何在较低级别发生;你有一张网卡。当该卡接收数据时,无论您的程序在做什么,它都会将数据存储到自己的存储区域中。当你呼叫recv时;您要求操作系统将数据从网卡内存移动到程序内存。这意味着,如果一个包在线程执行其他操作时传入;它不仅会被删除,而且会在下次线程获取数据时被处理

如果你的线程没有足够频繁地调用recv;然后网卡的内存将变满。当这种情况发生时,不能存储新的数据包;如果它使用TCP,那么路由器将被告知它无法处理它;如果它是UDP,那么它将被简单地删除。正是这一部分使得UDP天生不可靠,因为它可能在数据包传输过程中的任何时候发生


超时影响线程等待数据出现在网卡存储区的时间;除非你再也不给recv打电话;不会影响丢弃的数据包。

否;这不会让你更容易丢包

查看网络传输如何在较低级别发生;你有一张网卡。当该卡接收数据时,无论您的程序在做什么,它都会将数据存储到自己的存储区域中。当你呼叫recv时;您要求操作系统将数据从网卡内存移动到程序内存。这意味着,如果一个包在线程执行其他操作时传入;它不仅会被删除,而且会在下次线程获取数据时被处理

如果你的线程没有足够频繁地调用recv;然后网卡的内存将变满。当这种情况发生时,不能存储新的数据包;如果它使用TCP,那么路由器将被告知它无法处理它;如果它是UDP,那么它将被简单地删除。正是这一部分使得UDP天生不可靠,因为它可能在数据包传输过程中的任何时候发生


超时影响线程等待数据出现在网卡存储区的时间;除非你再也不给recv打电话;不会影响丢弃的数据包。

答案是否,丢失UDP数据将违反:

函数的作用是:返回写入缓冲区参数所指向的缓冲区的消息长度对于基于消息的套接字,如SOCK_DGRAM和SOCK_SEQPACKET,应在一次操作中读取整个消息

当使用
MSG_WAITALL
选项时,“部分计数”可能只发生在基于连接的套接字上

也就是说,通常不赞成使用
SO\u RECVTIMEO
,而在套接字上实现超时的“正确”方法是使用非阻塞套接字和
select()
。这是出于历史原因,而不是因为设置超时在某种程度上天生就是一种糟糕的设计或其他东西。如果您坚持使用
,请注意潜在的可移植性问题:

  • POSIX提到了
    所以_RECVTIMEO
    ,但是
  • 在Windows上,rcv()中会出现超时,您应该立即将其关闭。根据我的经验,在POSIX上,在
    导致超时后,您仍然可以使用套接字,但有人可能会说,规范并不能100%保证这一点

答案是否定的,丢失UDP数据将违反:

函数的作用是:返回写入缓冲区参数所指向的缓冲区的消息长度对于基于消息的套接字,如SOCK_DGRAM和SOCK_SEQPACKET,应在一次操作中读取整个消息

当使用
MSG_WAITALL
选项时,“部分计数”可能只发生在基于连接的套接字上

也就是说,通常不赞成使用
SO\u RECVTIMEO
,而在套接字上实现超时的“正确”方法是使用非阻塞套接字和
select()
。这是出于历史原因,而不是因为设置超时在某种程度上天生就是一种糟糕的设计或其他东西。如果您坚持使用
,请注意潜在的可移植性问题:

  • POSIX提到了
    所以_RECVTIMEO
    ,但是
  • 在Windows上,rcv()中会出现超时,您应该立即将其关闭。根据我的经验,在POSIX上,在
    导致超时后,您仍然可以使用套接字,但有人可能会说,规范并不能100%保证这一点

这正是我所希望的。只有“…它将返回一个部分计数…”让我有点困惑,我仍然没有真正理解
SO_RCVTIMEO