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

时间:2012-09-06 12:20:24

标签: 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);
    }
}

所有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);
        }
    }
}

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

2 个答案:

答案 0 :(得分:3)

操作系统内核为每个UDP和TCP套接字维护单独的发送和接收缓冲区。如果您使用Google SO_SNDBUFSO_RCVBUF,则可以找到有关它们的大量信息。

发送数据时,会将数据从应用程序空间复制到发送缓冲区。从那里将它复制到网络接口卡,然后复制到电线上。接收方是相反的:接收缓冲区的NIC,它等待你读取它。此外,还可能发生复制和缓冲,具体取决于操作系统。

值得注意的是,这些缓冲区的大小可以根本不同。有些系统可能默认为4千字节,而其他系统则为2兆字节。您可以使用getsockopt()SO_SNDBUF使用SO_RCVBUF找到当前大小,同样使用setsockopt()设置它。但是许多系统限制缓冲区的大小,有时限制为任意少量。这通常是内核值,如net.core.wmem_maxnet.core.rmem_max,但具体参考值因系统而异。

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

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

答案 1 :(得分:0)

在我看来,UdpClient-Class为接收到的数据提供了一个缓冲区。尝试直接使用套接字。您可能还希望将套接字ReceiveBufferSize设置为零,即使我认为它仅用于TCP连接。