代码之家  ›  专栏  ›  技术社区  ›  463035818_is_not_an_ai

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

  •  0
  • 463035818_is_not_an_ai  · 技术社区  · 6 年前

    我发现 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
    

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

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

    也相关: setting timeout for recv fcn of a UDP socket

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

    2 回复  |  直到 6 年前
        1
  •  4
  •   UKMonkey    6 年前

    不这不会让你更容易丢包。

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

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

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

        2
  •  0
  •   FrancoVS    3 年前

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

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

    可以推测,“部分计数”只发生在基于连接的套接字中 MSG_WAITALL 使用选项。

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

    • POSIX提到 SO\U RECVTIMEO 但是 does not require it
    • 在Windows上,rcv()中的超时将 put the socket in a bad state 然后你应该立即关闭它。根据我的经验,在POSIX上,您可以在由 SO\U RECVTIMEO ,但有人可能会争辩说,规范并不能百分之百保证这一点