当前位置: 首页 > 面试题库 >

是什么导致UDP数据包在发送到本地主机时被丢弃?

芮祺
2023-03-14
问题内容

我正在发送非常大的数据报(64000字节)。我意识到MTU远小于64000字节(根据我的阅读,典型值约为1500字节),但我怀疑会发生以下两种情况之一-
要么没有数据报都能通过(所有大于1500字节)会被静默丢弃或导致引发错误/异常),否则64000字节数据报将被分拆成大约43 1500字节消息并透明地传输。

从长远来看(2000+
64000字节数据报),约有1%的数据报(甚至对于LAN来说似乎都异常高)被丢弃了。我可能希望通过网络进行此操作,在该网络中,数据报可能会乱序到达,被丢弃,被过滤等。但是,在localhost上运行时,我没有想到这一点。

是什么导致无法在本地发送/接收数据?我意识到UDP是不可靠的,但是我没想到UDP在本地主机上是如此不可靠。我想知道这是否只是时间问题,因为发送和接收组件都在同一台机器上。

为了完整起见,我包括了发送/接收数据报的代码。

正在发送:

DatagramSocket socket = new DatagramSocket(senderPort);

int valueToSend = 0;

while (valueToSend < valuesToSend || valuesToSend == -1) {
    byte[] intBytes = intToBytes(valueToSend);

    byte[] buffer = new byte[bufferSize - 4];

     //this makes sure that the data is put into an array of the size we want to send
    byte[] bytesToSend = concatAll(intBytes, buffer);

    System.out.println("Sending " + valueToSend + " as " + bytesToSend.length + " bytes");

    DatagramPacket packet = new DatagramPacket(bytesToSend,
                        bufferSize, receiverAddress, receiverPort);

    socket.send(packet);

    Thread.sleep(delay);

    valueToSend++;
}

接收:

DatagramSocket socket = new DatagramSocket(receiverPort);

while (true) {
    DatagramPacket packet = new DatagramPacket(
            new byte[bufferSize], bufferSize);

    System.out.println("Waiting for datagram...");
    socket.receive(packet);

    int receivedValue = bytesToInt(packet.getData(), 0);

    System.out.println("Received: " + receivedValue
            + ". Expected: " + expectedValue);

    if (receivedValue == expectedValue) {
        receivedDatagrams++;
        totalDatagrams++;
    }
    else {
        droppedDatagrams++;
        totalDatagrams++;
    }

    expectedValue = receivedValue + 1;
    System.out.println("Expected Datagrams: " + totalDatagrams);
    System.out.println("Received Datagrams: " + receivedDatagrams);
    System.out.println("Dropped Datagrams: " + droppedDatagrams);
    System.out.println("Received: "
            + ((double) receivedDatagrams / totalDatagrams));
    System.out.println("Dropped: "
            + ((double) droppedDatagrams / totalDatagrams));
    System.out.println();
}

问题答案:

是什么导致无法在本地发送/接收数据?

主要是缓冲空间。想象一下,发送恒定的10MB /秒,而仅消耗5MB
/秒。操作系统和网络堆栈无法跟上,因此数据包被丢弃。(这不同于TCP,TCP提供了流控制和重新传输来处理这种情况。)

即使在没有溢出缓冲区的情况下使用数据时,也可能会有很小的时间片无法使用数据,因此系统将丢弃数据包。(例如,在垃圾回收期间,或者当OS任务暂时切换到更高优先级的过程时,等等。)

这适用于网络堆栈中的所有设备。当队列已满时,非本地网络,以太网交换机,路由器,集线器和其他硬件也会丢弃数据包。通过100MB / s以太网交换机发送10MB
/ s的流,而其他人试图通过同一物理线路填充100MB / s的流将导致丢包。

增加套接字缓冲区的大小和操作系统的套接字缓冲区的大小。

的Linux

默认的套接字缓冲区大小通常128K或更少,这让 非常 小房间暂停数据处理。

系统控制

使用sysctl增加发送(写内存[wmem])和接收(读内存[rmem])缓冲区:

  • net.core.wmem_max
  • net.core.wmem_default
  • net.core.rmem_max
  • net.core.rmem_default

例如,将值增加到8 MB:

sysctl -w net.core.rmem_max=8388608

要保持设置不变,请同时进行更新/etc/sysctl.conf,例如:

net.core.rmem_max=8388608

一个深入的文章有关调整网络堆栈潜入更为细节,触及了如何包从内核的网络驱动程序通过环缓冲区接收和处理在Linux下一路到C的多层次的recv电话。本文介绍了在诊断网络问题时要监视的其他设置和文件。(见下文。)

在进行以下任何调整之前,请务必了解它们如何影响网络堆栈。 确实有可能使您的网络无法使用。 选择适合您的系统,网络配置和预期流量负载的数字:

  • net.core.rmem_max = 8388608
  • net.core.rmem_default = 8388608
  • net.core.wmem_max = 8388608
  • net.core.wmem_default = 8388608
  • net.ipv4.udp_mem =‘262144 327680 434274’
  • net.ipv4.udp_rmem_min = 16384
  • net.ipv4.udp_wmem_min = 16384
  • net.core.netdev_budget = 600
  • net.ipv4.ip_early_demux = 0
  • net.core.netdev_max_backlog = 3000

ethtool

此外,ethtool对于查询或更改网络设置很有用。例如,如果${DEVICE}eth0(使用ip addressipconfig确定您的网络设备名称),则可以使用以下方法增加RX和TX缓冲区:

  • ethtool -G $ {DEVICE}接收4096
  • ethtool -G $ {DEVICE} TX 4096

iptables

默认情况下,iptables它将记录有关数据包的信息,尽管这是最少的,但它消耗了CPU时间。例如,您可以使用以下命令禁用端口6004上UDP数据包的日志记录:

iptables -t raw -I PREROUTING 1 -p udp --dport 6004 -j NOTRACK
iptables -I INPUT 1 -p udp --dport 6004 -j ACCEPT

您的特定端口和协议将有所不同。

监控方式

几个文件包含有关在发送和接收的各个阶段网络数据包发生了什么的信息。在下面的列表中${IRQ}是中断请求号,并且${DEVICE}是网络设备:

  • /proc/cpuinfo -显示可用的CPU数量(有助于IRQ平衡)
  • /proc/irq/${IRQ}/smp-affinity -显示IRQ关联
  • /proc/net/dev -包含常规数据包统计信息
  • /sys/class/net/${DEVICE}/queues/QUEUE/rps_cpus -与接收数据包导向(RPS)有关
  • /proc/softirqs -用于元组过滤
  • /proc/net/softnet_stat -用于数据包统计信息,例如丢弃,时间压缩,CPU冲突等。
  • /proc/sys/net/core/flow_limit_cpu_bitmap -显示数据包流量(可以帮助诊断大小流量之间的丢弃)
  • /proc/net/snmp
  • /proc/net/udp

摘要

缓冲区空间是丢弃数据包的最可能元凶。在整个网络堆栈中散布着许多缓冲区,每个缓冲区对发送和接收数据包都有自己的影响。网络驱动程序,操作系统,内核设置和其他因素可能会影响数据包丢弃。没有银弹。

进一步阅读

  • https://github.com/leandromoreira/linux-network-performance-parameters
  • http://man7.org/linux/man-pages/man7/udp.7.html
  • http://www.ethernetresearch.com/geekzone/linux-networking-commands-to-debug-ipudptcp-packet-loss/


 类似资料:
  • 我正在尝试编写一个非常简单的UDP客户机/服务器对,它将在同一台计算机上一起工作(目前),但是我的包没有一个被传送。以下代码是一个100%完整的VB.NET控制台应用程序。它运行时不会抛出错误,但是mListener。接收命令从不返回。 问题 1:为什么我没有收到任何数据包? 问题2:为什么我不能让我的客户使用IP地址。有没有终点?当我尝试连接到NewIPEndPoint(IPAddress.An

  • 根据Stevens(图示为TCP/IP),traceroute程序用增量TTL(1、2、3等)向目的主机发送UDP数据包,以从ICMP TTL过期消息中获取中间跳信息。 “到达目的地”条件是ICMP端口无法到达的消息,因为traceroute寻址的随机端口数量很高(也就是说,不太可能有人在那里监听) 所以我的问题是:是否有技术原因(缺点、RFCs等)使用UDP数据包而不使用例如ICMP回送请求消息

  • 我正在Cooja中运行一个模拟。我的模拟只有2个motos:一个rpl边界路由器,一个rpl udp-server。我使用的是Contiki中给出的示例代码:bord-router. c和udp-server. c。 我正在使用“tunslip6”工具在moto和我的本地机器(在Ubuntu 18.04上运行)之间建立一个桥梁。现在,我想访问rpl udp服务器moto,并希望从本地计算机获得回复

  • 问题内容: 当我尝试从to进行AJAX调用时,它将引发以下错误。 XMLHttpRequest无法加载 http:// localhost:8000 / project / login / uid = bimt; token = KAMWMS151UWP67Q 。Access- Control-Allow-Origin不允许使用原始http:// localhost。 问题答案: 由于端口不同,因

  • 我编写了一个简单的UDP服务器程序来了解更多可能的网络瓶颈。 UDP客户端:我使用hping如下所示: HPING 3 192.168.1.2-UDP-P 9996--洪水-D 100 当我以每秒100个数据包的速度发送udp数据包时,我没有发现任何udp数据包丢失。但是当我泛洪udp数据包时(如上面的命令所示),我会看到大量的数据包丢失。 因此,为了减少数据包丢失,我尝试了以下操作: -使用re