我正在 Android 上编写一个网络应用程序。
我正在考虑使用单个 UDP 端口和数据报套接字来接收发送给它的所有数据报,然后对这些消息使用不同的处理队列。
我怀疑我是否应该有第二个或第三个 UDP 套接字待命。有些消息会很短(100 字节左右),但其他消息则必须传输文件。
我担心的是,如果 Android 内核忙于处理大消息,它会丢弃小消息吗?
更新 “后一个函数调用 sock_queue_rcv_skb()(在 sock.h 中),它将 UDP 数据包在套接字的接收缓冲区中排队。如果缓冲区中没有更多空间,则丢弃数据包。过滤也由这个函数执行,它像TCP一样调用sk_filter()。最后调用data_ready(),完成UDP数据包接收。”
最佳答案
让我们先了解一些基础知识:
每个套接字都有一个接收和发送缓冲区。当网络硬件发出新数据包到达的信号时, 接收缓冲区已满,数据包将被丢弃。缓冲区大小通过 SO_RCVBUF
和 SO_SNDBUF
套接字选项控制,参见 setsockopt(3)
.操作系统设置了一些默认值(还有 /etc/sysctl.conf
文件)。这是在 BSD 系统上:
~$ sysctl -a|grep space net.inet.tcp.recvspace=16384 net.inet.tcp.sendspace=16384 net.inet.udp.recvspace=41600 net.inet.udp.sendspace=9216
TCP 和 UDP 之间的区别在于前者负责数据的排序和丢弃数据包的重传,以及流量控制(慢速读取器减慢快速写入器), 而后者则没有。
所以是的,使用 UDP 传输文件不是最好的选择,但可行。人们只需要重新发明 TCP 的一部分,并权衡重新发明的开销与 TCP 的开销。话又说回来,普遍的看法是 UDP 最适合可以容忍某些数据包重新排序/丢失的应用程序(例如音频/视频流)。
还有一种错误的观念,即每个套接字都需要一个单独的线程来发送/接收数据,这与事实相去甚远。许多优秀的高性能网络应用程序都是在没有线程的情况下编写的,而是使用非阻塞套接字和一些轮询机制(参见 select(2)
、poll(2)
、epoll(7)
)。
问题本身:
是的,如果应用程序太忙而无法在套接字的接收缓冲区中保留足够的可用空间,内核可能会丢弃数据包。但是由于每个套接字都有自己的套接字,因此控制流和数据流的分离会有所帮助。尽管我个人会选择一个简单的 TCP 服务器设置——监听一个端口,接受每个客户端的连接,在 TCP 流之上实现一个有意义的协议(protocol)。我同意玩 UDP 和低级协议(protocol)状态机很有趣,但它已经完成了,并且数十年的研究都用于调整 TCP 性能。归根结底,重要的是应用程序的可靠性(第一)和性能(第二)。
希望这对您有所帮助。
关于android - 在待机状态下拥有多个 UDP 数据报套接字有意义吗? "simultaneous"数据包是否被内核丢弃或排队?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2574366/