UDP发送()到Winsock丢弃数据包下的localhost?

时间:2016-10-21 21:15:35

标签: c++ c udp send winsock2

情景相当简单......不允许使用" sendto()"所以使用" send()"代替...

winsock2.2下,在运行Windows 7 Professional的全新i7机器上正常运行......

使用SOCK_DGRAM套接字,客户端和服务器控制台应用程序通过localhost127.0.0.1)进行连接以测试...

必须使用不变大小的数据包...

客户端套接字使用connect(),服务器套接字使用bind() ...

客户端使用一系列BLOCKING send()次呼叫发送N个数据包。服务器仅使用ioctlsocketFIONREAD进行调用,在while循环中运行,以等待接收的printf()字节数不断增加...

PACKETS丢失,除非我将SLEEP()置于可考虑的时间内...... 我的意思是接收套接字上的字节数在运行之间有所不同,如果我这样做的话不要使用SLEEP() ...

玩过更改缓冲区大小,情况没有太大变化,除非现在没有溢出,但延迟问题仍然存在...

我已经看到很多关于send()recv()之间问题的讨论,但在这种情况下,recv()甚至没有参与......

有人想到吗?

(PS由于我无法控制的原因,我需要编程的约束,因此没有WSA.NETMFCSTL,{{1} },BOOST或其他东西)

这不是缓冲区溢出的问题,原因有三个:

  1. 设置并检查传入和传出缓冲区 显着大于发送的所有信息。
    1. 没有QT,只通过recv()调用检查传入缓冲区,在用户输入后很久就会调用recv()。
    2. ioctl() - s之间添加Sleep()的{​​{1}}时,整个过程都有效,即如果出现溢出,则无法满足 >40ms会有所帮助(send()

1 个答案:

答案 0 :(得分:0)

  

PACKETS失去了我,但我睡着了()有可观的数量   TIME ...我的意思是接收套接字上的字节数   如果我不使用SLEEP()......

,则运行之间会有所不同

这是预期的行为;正如其他人在评论中所说,UDP数据包可以并且确实因任何原因而被丢弃。但是,在仅使用localhost的通信环境中,原因通常是某个固定大小的数据包缓冲区已满,无法保留传入的UDP数据包。请注意,UDP没有流控制的概念,因此如果您的接收程序无法跟上您的发送程序,一旦缓冲区满了,肯定会发生数据包丢失。

关于如何处理,插入呼叫睡眠()解决方案并不是特别好,因为你没有好的方法知道"权利"睡眠持续时间应该是。 (要缩短睡眠时间(),你仍然会丢弃数据包;睡眠时间过长()并且你传输数据的速度比你原来要慢得多;当然还有#34;最佳&#34 ;值可能会因计算机而异,或者从一台计算机到下一个计算机,或者以一种非显而易见的方式发生。

您可以做的一件事是切换到不同的传输协议,例如TCP,或者(因为您只在localhost内进行通信),简单的管道或套接字对。这些协议具有您正在寻找的无损FIFO语义,因此它们可能是适合该工作的正确工具。

假设您需要使用UDP,但UDP丢包对您来说是事实,但您可以采取一些措施来减少数据包丢失:

  1. 发送()处于阻塞模式,或者如果使用非阻塞发送(),请务必等到UDP套接字select()作为准备写入,然后再调用send()。 (我知道你说你以封锁模式发送();我只是为了完整而包含这个)
  2. 在接收UDP套接字上使SO_RCVBUF设置尽可能大。缓冲区越大,填充容量的可能性就越小。
  3. 在接收程序中,确保调用recv()的线程不执行任何其他操作,以免再次返回到下一个recv()调用。特别是,没有阻塞操作(甚至printf()是一个阻塞操作,可以减慢你的线程,特别是在Windows提示臭名昭着加载缓慢滚动的Windows下)
  4. 在一个单独的线程中运行接收器的网络recv()循环,除了调用recv()之外什么都不做,并将接收到的数据放到某个FIFO队列(或其他共享数据结构)中。然后,另一个线程可以执行检查和解析FIFO中数据的时间要求较低的工作,而不用担心会丢失数据包。
  5. 以最高优先级运行UDP接收线程,您可以说服操作系统让您运行。可以容纳UDP接收线程的其他任务越少,在这些延迟期间丢弃数据包的机会就越少。
  6. 请记住,无论您在减少UDP数据包丢失的机会方面多么聪明,UDP数据包丢失仍然会发生。因此,无论您需要设计哪种设计,即使数据包丢失,您的程序仍能以合理有用的方式运行。这可以通过实现某种自动重发机制来实现,或者(取决于你想要完成的工作)通过设计协议使得丢包可以简单地被忽略。