如果我没有主动从 DatagramSocket 接收数据包,数据包是否会被丢弃?
我访问了很多网站和教程(和文档),但仍有一个问题没有得到解答。当我当前没有运行 socket.receive(...) 时,如果 UDP 数据包到达,会发生什么?它会以某种方式缓冲直到我调用 socket.receive(...) 还是完全丢失?
Android 的 DatagramSocket 实现是否是线程安全的,即您可以在侦听套接字时写入套接字,也可以不写入套接字?
I've visited so many websites and tutorials (and docs), but I still have one question unanswered. What happens, if UDP packet arrives, when I'm not currently running socket.receive(...)? Will it buffer somehow until I invoke socket.receive(...) or is it completely lost?
Also is Android's DatagramSocket implementation thread-safe in meaning, that you can write to socket when listening to it, or not?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
内核网络堆栈为每个套接字保留一个接收缓冲区。您可以使用
SO_RCVBUF
选项到setsockopt(2)
系统调用(您必须弄清楚它的 Java API 是什么)。因此,只要缓冲区中有足够的空间,传入的数据包就会在内核中排队。应用程序不需要在该特定时刻执行“接收”函数。如果应用程序没有足够快地使数据包出队(即读取),则缓冲区溢出并且内核开始丢弃数据包。在 Linux(通常是 Unix)上,您应该能够使用
netstat -s
查看丢包计数 命令。我还请注意,该缓冲区并不是唯一可能丢弃数据包的地方。如果 NIC 内存中没有足够的空间,硬件可能会丢弃数据包。然后,如果内核太忙并且不处理其通用网络输入队列,设备驱动程序可能会丢弃数据包。不过,您需要严格的消息发送率才能实现这一点。
TCP 尝试通过完全排序和重传(如有必要)来解决所有这些问题。 UDP 是简单的“发送后不管”,不会为您处理丢弃的数据包(除了在已连接的 UDP 套接字上的第二个
send(2)
中收到错误的极端情况)并且仅当 ICMP 正常工作时)。最重要的是,数据包会被缓冲,但到此为止,然后被丢弃。
The kernel network stack keeps a receive buffer per socket. You have control over the size of it with
SO_RCVBUF
option to thesetsockopt(2)
system call (you'll have to figure out what's the Java API for it).So the incoming packets are queued in the kernel as long as there's enough space in that buffer. It's not required for the application to be executing the "receive" function at that particular moment. If the application is not de-queuing (i.e. reading) the packets fast enough, the buffer overflows and kernel starts dropping the packets. On Linux (and generally Unix) you should be able to see the packet drop count with
netstat -s
command.Let me also note that this buffer is not the only place where packets can get dropped. The hardware might drop packets if there's not enough space in its on-NIC memory. Then the device driver can drop packets if the kernel is too busy and not processing its general network input queue. You need serious message rates for this to happed though.
TCP tries to get around all this with total sequencing and, if necessary, retransmission. UDP, being bare-bones "send and forget", does not do anything about dropped packets for you (except in corner cases where you get an error from the second
send(2)
on a connected UDP socket and only if ICMP works properly).The bottom line is that packets are buffered, but up to the point, then discarded.