【问题标题】:UDP Socket reading last incoming byteUDP 套接字读取最后一个传入字节
【发布时间】:2017-08-19 09:16:29
【问题描述】:

我有一个套接字,它在字节之间发送一个massiv,经常重复相同的信息,但接收器一次无法获得所有这些字节。我有办法减慢发送方的速度,但现在我有延迟,因为没有足够的字节来。我需要实时传输。

有没有办法让接收者读取最后一个传入的字节并丢弃其他字节然后在程序中继续执行?

while (sock->isConnect() && tcpsock->isConnect()) {
    // with while instead of if, stuck in the loop
    if (sock->RecData(buff, 14)) { //receiving 14 bytes from UDP
        sendAngles2(buff);
        logger->setLatenz(logger->RECV);
    }
    logger->setLatenz(logger->MAIN);
    logger->LogData();
    // rest of the code 
}

【问题讨论】:

  • 这是在专用线程中运行,还是作为更大主循环的一部分?
  • no这个循环是main()中最大的循环
  • UDP 是流而不是块协议。您必须读取所有字节才能到达您想要的字节。
  • 愚蠢的问题,但是......每个数据报发送的大小总是 14字节吗?
  • @RichardCritten UDP不是流协议。 UDP 是一种数据报协议,这意味着您可以获取单独的消息。没有关于订购或可靠性的保证。您收到整条消息或根本没有消息。另一方面,TCP 是一种流协议。

标签: c++ sockets udp


【解决方案1】:

有没有办法让接收者读取最后一个传入的字节并丢弃其他字节然后在程序中继续执行?

是的。设置套接字非阻塞。如果需要,请使用select 等待数据到达。

然后在循环中继续调用recv(或recvfrom),直到它返回EWOULDBLOCK 错误。然后使用您从上一次调用中收到的数据(确保保存其长度)。

【讨论】:

  • 或者他可以在 recv() 使用 MSG_PEEK 选项返回 > 0 时循环,然后在循环内读取,但这当然会使系统调用加倍。
  • @user207421 这不起作用。这是UDP,UDP数据报可以被丢弃。因此,如果数据报在他的recv(MSG_PEEG) 之后和最后的recv 之前被丢弃,他的最后一次读取可能会阻塞。一些真实的平台实际上是这样做的! (例如,如果校验和被全局禁用,并且接收到具有错误校验和的数据报,然后在两个recv 调用之间启用校验和。使用状态报告功能就好像它提供了未来的保证一样是错误的。他们只是不这样做。)
【解决方案2】:

不幸的是,没有标准/正常的方法来做到这一点1 -- 当接收到具有完整接收缓冲区的 UDP 套接字的新数据包时,新数据包将被丢弃,即使它最好丢弃旧的(缓冲的)数据包。

您可以做的一件事是使用setsockopt(fd, SOL_SOCKET, SO_RECVBUF,... 来减小套接字接收缓冲区的大小。这样做会导致它在接收方落后时更快地开始丢弃数据包,从而减少处理数据包的延迟,类似于bufferbloat 缓解技术。


1在我知道的 Linux 或 BSD 上没有办法做到这一点;一些实时操作系统可能有办法做到这一点

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-09-24
    • 2016-04-22
    • 1970-01-01
    • 2021-04-25
    • 1970-01-01
    • 1970-01-01
    • 2010-10-30
    • 1970-01-01
    相关资源
    最近更新 更多