8

我以前从未使用过 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
4

2 回答 2

3

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

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

需要注意的是,这些缓冲区的大小可能会有很大的不同。某些系统可能默认为 4 KB,而其他系统则为 2 MB。getsockopt()您可以使用withSO_SNDBUF或找到当前大小SO_RCVBUF,同样使用setsockopt(). 但是许多系统会限制缓冲区的大小,有时会限制为任意小量。这通常是一个内核值,例如net.core.wmem_maxor net.core.rmem_max,但确切的引用会因系统而异。

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

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

于 2012-09-12T17:12:13.637 回答
0

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

于 2012-09-06T12:28:03.960 回答