首页 文章

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

提问于
浏览
4

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

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

我怀疑我是否应该备用第二个或第三个UDP套接字 . 有些消息会很短(100字节左右),但其他消息必须传输文件 .

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

Update “后一个函数调用sock_queue_rcv_skb()(在sock.h中),它将UDP数据包排入套接字的接收缓冲区. If no more space is left on the buffer, the packet is discarded. 过滤也由这个函数执行,它像TCP一样调用sk_filter() . 最后,data_ready( )调用,UDP包接收完成 . “

3 回答

  • 7

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

    每个套接字都有一个接收和一个发送缓冲区 . 当网络硬件发信号通知新数据包到达且接收缓冲区已满时,数据包将被丢弃 . 缓冲区大小通过 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性能 . 最重要的是您的应用程序的可靠性(第一)和性能(第二) .

    希望这可以帮助 .

  • 0

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

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

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

  • 1

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

相关问题