在待机状态下有多个UDP数据报套接字是否有意义? “同时”数据包是由内核丢弃还是排队?

时间:2010-04-04 12:31:21

标签: android networking sockets udp kernel

我在Android上编写网络应用程序。

我正在考虑使用单个UDP端口和数据报套接字来接收发送给它的所有数据报,然后为这些消息提供不同的处理队列。

我怀疑是否应该在待机状态下使用第二个或第三个UDP套接字。有些消息会很短(大约100字节),但其他消息则必须传输文件。

我担心的是,如果Android内核忙于处理较大的消息,它会丢弃小消息吗?

更新 “后一个函数调用sock_queue_rcv_skb()(在sock.h中),它将UDP数据包排入套接字的接收缓冲区。如果缓冲区上没有剩余空间,则丢弃该数据包。过滤也由此函数执行,它像TCP一样调用sk_filter()。最后,调用data_ready(),并完成UDP数据包接收。“

3 个答案:

答案 0 :(得分:8)

让我们首先了解一些基础知识:

每个套接字都有一个接收和一个发送缓冲区。当网络硬件发出新数据包到达时,接收缓冲区已满,数据包将被丢弃。缓冲区大小由SO_RCVBUFSO_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性能。最重要的是您的申请的可靠性(第一)和表现(第二)。

希望这有帮助。

答案 1 :(得分:1)

UDP对于传输文件是个坏主意,因为您不能保证接收数据包的顺序,或者根本不会接收数据包。如果您正在考虑在此基础上构建容错传输层,则应该使用TCP / IP,因为这正是它所做的。

UDP不会缓冲或排队收到的数据包。如果收到数据包并且您正在等待数据,您将收到它。如果在程序忙于执行其他处理时收到数据包,则根本不会收到数据包。因此,如果您收到两个“同步数据包”(好吧,两个非常接近),如果您对每个数据包进行任何重要处理,很可能会错过其中一个数据包。

我不知道如何打开额外的端口对你有多大帮助。如果您正忙于处理来自端口1的数据包,那么您将错过任何正在观看的其他端口上的数据包,除非每个端口都在专用线程上运行。将数据包快速复制到自己的缓冲区并将其传递给另一个线程来处理它会更好,所以你的监听器线程可以尽快回到监听状态。

答案 2 :(得分:0)

TCP的流量控制将帮助您减少丢弃的数据包。它具有容错能力,可确保数据包按顺序到达。