Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sockets/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 是否可能有多个具有相同localEndPoint的UDP c套接字?_C#_Sockets_Udp - Fatal编程技术网

C# 是否可能有多个具有相同localEndPoint的UDP c套接字?

C# 是否可能有多个具有相同localEndPoint的UDP c套接字?,c#,sockets,udp,C#,Sockets,Udp,我编写了一个工作正常的TCP客户机/服务器代码。TCP套接字侦听器接受连接并创建具有相同localEndPoint和不同RemoteEndPoint的多个套接字。现在我想扩展到UDP,但seerver代码中有一个问题。我必须为每个客户端对象将UDP套接字绑定到本地端点。但我遇到了一个错误:我不能将多个UDP套接字绑定到同一个localEndPoint。我发现UDP套接字的本质是: UDP服务器不会为每个并发服务的客户端创建新的子进程,但同一进程会通过同一套接字依次处理来自所有远程客户端的传入数据

我编写了一个工作正常的TCP客户机/服务器代码。TCP套接字侦听器接受连接并创建具有相同localEndPoint和不同RemoteEndPoint的多个套接字。现在我想扩展到UDP,但seerver代码中有一个问题。我必须为每个客户端对象将UDP套接字绑定到本地端点。但我遇到了一个错误:我不能将多个UDP套接字绑定到同一个localEndPoint。我发现UDP套接字的本质是:

UDP服务器不会为每个并发服务的客户端创建新的子进程,但同一进程会通过同一套接字依次处理来自所有远程客户端的传入数据包。这意味着UDP套接字不由远程地址标识,而仅由本地地址标识,尽管每条消息都有一个关联的远程地址

那么,我可以像为TCP套接字那样为每个客户端创建一个不同的UDP套接字吗? 注意:如果可能,请使用套接字类而不是UDPClient类进行解释

代码说明:我想在建立TCP连接connect/accept后,可以在客户端/服务器两侧绑定UDP套接字。服务器上只有一个客户机可以。对于新客户端,服务器会引发异常,因为它无法将多个套接字与一个localEndPoint绑定。客户端可以是所有可用端口以外的端口。因此,我无法为每个客户端将UDP套接字绑定到不同的localEndPoint。
我知道我可以创建一个唯一的UDP套接字,并将接收消息传递给服务器上相应的客户机对象,但这有点令人讨厌。谢谢

您可以根据唯一的源IP:端口组合运行任务。这将允许您轻松地为每个唯一的传入源IP:端口组合维护一个状态机。System.IO.Pipelines使得将其连接起来非常容易

首先设置一个类似于TCPListener的UDPListener任务,为每个新的IP:PORT设置一个任务来处理该端口,创建一个管道,每次数据来自该IPEndpoint时,将数据放入PipeWriter

为了完整性,一些客户端通常会在不同的机器上运行,但为了简单起见,我们将它们作为任务运行

    static async Task UdpClientClient(string messageToSend)
    {
        var client = new UdpClient();
        client.Connect("127.0.0.1", 33000);
        for(var i=0;i<5;i++)
        {
            var message = ASCIIEncoding.ASCII.GetBytes(messageToSend + " #"+ i.ToString());
            await client.SendAsync(message, message.Length);
            await Task.Delay(1000);
        }
    }
}
你会发现:

Server: 127.0.0.1:53183 Received: Me too server! #0
Server: 127.0.0.1:53182 Received: I am here server... #0
Server: 127.0.0.1:53181 Received: hi Server! #0
Server: 127.0.0.1:53182 Received: I am here server... #1
Server: 127.0.0.1:53183 Received: Me too server! #1
Server: 127.0.0.1:53181 Received: hi Server! #1
Server: 127.0.0.1:53182 Received: I am here server... #2
Server: 127.0.0.1:53183 Received: Me too server! #2
Server: 127.0.0.1:53181 Received: hi Server! #2
Server: 127.0.0.1:53182 Received: I am here server... #3
Server: 127.0.0.1:53181 Received: hi Server! #3
Server: 127.0.0.1:53183 Received: Me too server! #3
Server: 127.0.0.1:53183 Received: Me too server! #4
Server: 127.0.0.1:53181 Received: hi Server! #4
Server: 127.0.0.1:53182 Received: I am here server... #4

当然,您需要进行错误检查,查看客户端是否仍然存在等。

您的误解是:TCP是基于连接的。两个端点具有相互连接。相反,UDP连接较少。你有一个收件箱,所有的客户都可以在那里寄送明信片。您需要弄清楚是谁发送了它们,谁应该负责处理它们,以及处理顺序!如果少了一个。谢谢你@Fildor!我理解UDP和无连接协议的概念。但我希望我能找到一种方法,在更高的层次上以更干净的方式设置一对套接字,以模拟TCP连接。非常感谢您全面的回答!你是在含蓄地说,没有办法让内核像对待TCP那样对待这些员工!我说的对吗?对。你得自己滚。在我的示例中,我使用了RemoteEndpoint。更好的选择是在每个dgram的头中使用一些加密标识符。我建议检查一下通过UDP的TLS的DTL。这是一个很好的产品化协议,具有很多互操作性。
    static async Task UdpServerClient(string serverName,Pipe p)
    {
        while (true)
        {
            var readResult = await p.Reader.ReadAsync();
            var message = Encoding.ASCII.GetString(readResult.Buffer.FirstSpan.ToArray());
            Console.WriteLine($"Server: {serverName} Received: {message}");
            p.Reader.AdvanceTo(readResult.Buffer.End);
        }
    }
    static async Task UdpClientClient(string messageToSend)
    {
        var client = new UdpClient();
        client.Connect("127.0.0.1", 33000);
        for(var i=0;i<5;i++)
        {
            var message = ASCIIEncoding.ASCII.GetBytes(messageToSend + " #"+ i.ToString());
            await client.SendAsync(message, message.Length);
            await Task.Delay(1000);
        }
    }
}
    static async Task Main(string[] args)
    {
        _ = Task.Run(() => StartUdpListener());

        _ = UdpClientClient("hi Server!");
        _ = UdpClientClient("I am here server...");
        await UdpClientClient("Me too server!");
    }
Server: 127.0.0.1:53183 Received: Me too server! #0
Server: 127.0.0.1:53182 Received: I am here server... #0
Server: 127.0.0.1:53181 Received: hi Server! #0
Server: 127.0.0.1:53182 Received: I am here server... #1
Server: 127.0.0.1:53183 Received: Me too server! #1
Server: 127.0.0.1:53181 Received: hi Server! #1
Server: 127.0.0.1:53182 Received: I am here server... #2
Server: 127.0.0.1:53183 Received: Me too server! #2
Server: 127.0.0.1:53181 Received: hi Server! #2
Server: 127.0.0.1:53182 Received: I am here server... #3
Server: 127.0.0.1:53181 Received: hi Server! #3
Server: 127.0.0.1:53183 Received: Me too server! #3
Server: 127.0.0.1:53183 Received: Me too server! #4
Server: 127.0.0.1:53181 Received: hi Server! #4
Server: 127.0.0.1:53182 Received: I am here server... #4