我在Android上编写网络应用程序.
我正在考虑使用单个UDP端口和数据报套接字来接收发送给它的所有数据报,然后为这些消息提供不同的处理队列.
我怀疑我是否应该备用第二个或第三个UDP套接字.有些消息会很短(100字节左右),但其他消息必须传输文件.
我担心的是,如果Android内核忙于处理较大的消息,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流之上实现一个有意义的协议.我同意使用UDP和低级协议状态机很有趣,但它已经完成,并且已经进行了数十年的研究来调整TCP性能.最重要的是您的应用程序的可靠性(第一)和性能(第二).
希望这可以帮助.