UDP发送的数据存储在哪里?

nat*_*tli 8 c# udp

我之前从未使用过UDP,所以我试了一下.为了看看会发生什么,我让"服务器"每半秒发送一次数据,客户端每隔3秒接收一次数据.因此,即使服务器发送速度远远超过了客户端可以接收数据时,客户端仍然都一个个整齐地接受它.

谁能解释为什么/如何发生这种情况?数据缓冲在哪里?

发送

class CSimpleSend
{
    CSomeObjServer obj = new CSomeObjServer();

    public CSimpleSend()
    {
        obj.changedVar = varUpdated;
        obj.threadedChangeSomeVar();
    }

    private void varUpdated(int var)
    {
        string send = var.ToString();
        byte[] packetData = System.Text.UTF8Encoding.UTF8.GetBytes(send);

        string ip = "127.0.0.1";
        int port = 11000;

        IPEndPoint ep = new IPEndPoint(IPAddress.Parse(ip), port);
        Socket client = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
        client.SendTo(packetData, ep);

        Console.WriteLine("Sent Message: " + send);
        Thread.Sleep(100);
    }
}
Run Code Online (Sandbox Code Playgroud)

所有CSomeObjServer都是每半秒递增一个整数

接收

class CSimpleReceive
{
    CSomeObjClient obj = new CSomeObjClient();

    public Action<string> showMessage;
    Int32 port = 11000;
    UdpClient udpClient;


    public CSimpleReceive()
    {
        udpClient = new UdpClient(port);

        showMessage = Console.WriteLine;
        Thread t = new Thread(() => ReceiveMessage());
        t.Start();
    }

    private void ReceiveMessage()
    {                      
        while (true)
        {
            //Thread.Sleep(1000);
            IPEndPoint remoteIPEndPoint = new IPEndPoint(IPAddress.Any, port);
            byte[] content = udpClient.Receive(ref remoteIPEndPoint);

            if (content.Length > 0)
            {
                string message = Encoding.UTF8.GetString(content);
                if (showMessage != null)
                    showMessage("Recv:" + message);

                int var_out = -1;
                bool succ = Int32.TryParse(message, out var_out);
                if (succ)
                {
                    obj.alterSomeVar(var_out);
                    Console.WriteLine("Altered var to :" + var_out);
                }
            }
            Thread.Sleep(3000);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

CSomeObjClient存储变量并具有一个函数(alterSomeVar)来更新它

输出继电器:

Sent Message: 1
Recv:1
Altered var to :1
Sent Message: 2
Sent Message: 3
Sent Message: 4
Sent Message: 5
Recv:2
Altered var to :2
Sent Message: 6
Sent Message: 7
Sent Message: 8
Sent Message: 9
Sent Message: 10
Recv:3
Altered var to :3
Run Code Online (Sandbox Code Playgroud)

Set*_*ble 3

操作系统内核为每个 UDP 和 TCP 套接字维护单独的发送和接收缓冲区。如果你用谷歌搜索SO_SNDBUFSO_RCVBUF你会发现很多关于它们的信息。

当您发送数据时,数据会从您的应用程序空间复制到发送缓冲区中。它从那里复制到网络接口卡,然后复制到线路上。接收端则相反:NIC 接收缓冲区,它会在那里等待,直到您读取它。此外,根据操作系统的不同,也可能会发生复制和缓冲。

值得注意的是,这些缓冲区的大小可能会有很大差异。有些系统可能默认为 4 KB,而其他系统则为 2 MB。getsockopt()您可以使用或找到当前大小SO_SNDBUFSO_RCVBUF并同样使用 进行设置setsockopt()。但许多系统限制缓冲区的大小,有时限制为任意小量。这通常是一个内核值,例如net.core.wmem_maxnet.core.rmem_max,但确切的参考值会因系统而异。

另请注意,setsockopt()即使您请求的金额低于假定的限制,也可能会失败。因此,要真正获得所需的大小,您需要setsockopt()使用递减的数量重复调用,直到最终成功。

以下页面是我公司的技术说明,其中稍微涉及此主题并提供一些常见系统的参考:http://www.dataexpedition.com/support/notes/tn0024.html