gpt4 book ai didi

c# - 重用 UdpClient 与处置它

转载 作者:行者123 更新时间:2023-12-03 12:03:46 27 4
gpt4 key购买 nike

我正在创建一个聊天应用程序,其中用户位于路由器 (NAT) 后面。所以主要问题是向这些客户发送消息。服务器接收消息没有问题。

这是我的协议(protocol)(规则):

  • UdpServer监听来自 client A 的 udp 数据包
  • Serverclient A 接收数据包并回复一个数据包以打开 NAT
  • Server现在成为客户端(服务器不断向 client A 发送数据包,客户端回复服务器通知它收到了他的消息)我现在反转客户端和服务器,因为 NAT 已打开 .这是因为 client A总是可以通过tcp向服务器发送消息。
  • 如果 Server看到 client A不回复它不断发送它标记的数据包client A断开连接并停止发送数据包。

  • 这是代码
    // class that holds infor about client
    class ClientBehindNat
    {
    public IPEndPoint EndpointListening;
    public string Id;
    }

    监听新客户端(连接)的线程:
    while(true)
    {
    IPEndPoint ep = new IPEndPoint(IPAddress.Any, 1234);
    // create a new udpServer
    using(var udpServer = new UdpClient())
    {
    // allow reusing port 1234
    udpServer.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
    // wait to receive data
    var data = udpServer.Receive(ref ep);

    // analyze data make sure it is reliable....

    // maybe data is a reply from a client
    if(data.IsReply())
    {
    // mark that client replied
    // ....
    continue;
    }
    else
    {
    // save new client
    ConnectedClients.Add(new ClientBehindNat(){EndpointListening=ep});
    }

    udpServer.Connect(ep);
    udpServer.Send( // data notifying client that we got his message)

    }
    }

    不断向客户端发送 udp 数据包以保持 nat 开放的线程
    // send packets every 15 seconds in order to leave nat open
    timer.elapsed += (a,b)=> {

    foreach (var c in connectedClients)
    {
    // create a copy of udp server so that client can get our response
    using (var copySocket = new UdpClient())
    {
    // allow reusing port 1234
    copySocket.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
    copySocket.Client.Bind(new IPEndPoint(IPAddress.Any, 1234));
    // log that we will send this request
    // Requests[someId] = ....

    // send it
    copySocket.Send(someData, someData.Length, c.EndpointListening);

    // first thread should be responsible for receiving this response

    // dispose this client
    }
    }
    }

    这是问题

    一切正常但是为每个请求创建一个新的套接字(UdpClient)是不是很糟糕?如果我收到 100 个请求,我会创建 100 个新套接字并处理所有这些。当我尝试重用更新其端点的 udp 客户端时,我得到一个异常。我经常需要给 Client A发消息或者也许 Client Z这就是为什么我存储它的端点以知道如何到达它。 如何重用 udpClient 更新其端点,以便能够访问我感兴趣的客户端?

    最佳答案

    我应该再次推荐使用 Socket s 直接,它给你很大的灵 active 。查看以下示例,该示例使用一个套接字进行发送和接收的 UDP 连接:

        private static readonly List<EndPoint> clients = new List<EndPoint>();
    private static readonly SocketAsyncEventArgs receiveEventArgs = new SocketAsyncEventArgs();
    private static Socket socket;

    private static void Main(string[] args)
    {
    receiveEventArgs.Completed += OnReceive;
    socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
    socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
    socket.Bind(new IPEndPoint(IPAddress.Any, 6000));
    Receive();

    while (true)
    {
    Thread.Sleep(3000);
    lock (clients)
    {
    foreach (var endPoint in clients)
    socket.SendTo(Encoding.ASCII.GetBytes("PING"), endPoint);
    }
    }
    }

    private static void Receive()
    {
    receiveEventArgs.SetBuffer(new byte[256], 0, 256);
    receiveEventArgs.RemoteEndPoint = new IPEndPoint(IPAddress.Any, 6000);
    socket.ReceiveFromAsync(receiveEventArgs);
    }

    private static void OnReceive(object sender, SocketAsyncEventArgs e)
    {
    if (e.BytesTransferred > 0)
    {
    // Is reply?
    var isReply = true/false;
    if (isReply)
    {
    // Do domething
    }
    else
    lock (clients)
    {
    clients.Add(e.RemoteEndPoint);
    }
    }
    else
    {
    lock (clients)
    {
    clients.Remove(e.RemoteEndPoint);
    }
    }
    Receive();
    }

    关于c# - 重用 UdpClient 与处置它,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47440622/

    27 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com