我访问了很多网站和教程(和文档),但我还有一个问题没有答案.如果UDP数据包到达,当我当前没有运行socket.receive(...)时会发生什么?它会以某种方式缓冲,直到我调用socket.receive(...)或者它完全丢失了吗?
Android的DatagramSocket实现也是线程安全的意思,你可以在收听时写入套接字,或不是?
内核网络堆栈为每个套接字保留一个接收缓冲区.您可以通过系统调用SO_RCVBUF
选项来控制它的大小setsockopt(2)
(您必须弄清楚它的Java API是什么).
因此,只要该缓冲区中有足够的空间,传入的数据包就会在内核中排队.它并不需要为应用程序在该特定时刻被执行"接收"功能.如果应用程序没有足够快地对数据包进行出队(即读取),则缓冲区溢出并且内核开始丢弃数据包.在Linux(通常是Unix)上,您应该能够通过netstat -s
命令查看数据包丢弃计数.
我还要注意,此缓冲区不是唯一可以丢弃数据包的地方.如果其NIC内存中没有足够的空间,硬件可能会丢弃数据包.然后,如果内核太忙并且不处理其一般网络输入队列,则设备驱动程序可以丢弃数据包.你需要严重的消息率才能解决这个问题.
TCP尝试通过完全排序来解决所有这些问题,并在必要时进行重传.UDP是一种"发送并忘记",对于丢弃的数据包没有任何作用(除了在send(2)
连接的UDP套接字上从第二个获得错误并且仅在ICMP正常工作的情况下).
最重要的是数据包是缓冲的,但直到该点,然后被丢弃.