C# 处理在同一端点上侦听的多个UDP套接字

C# 处理在同一端点上侦听的多个UDP套接字,c#,c,sockets,udp,dtls,C#,C,Sockets,Udp,Dtls,我一直在(大致)遵循一些示例代码,编写一个可以处理多个客户机的DTLS服务器。在这个例子中,它工作得很好(我尝试过),服务器监听INADDR\u ANY和端口0 fd = socket(server_addr.ss.ss_family, SOCK_DGRAM, 0); setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (const void*) &on, (socklen_t) sizeof(on)); bind(fd, (const struct soc

我一直在(大致)遵循一些示例代码,编写一个可以处理多个客户机的DTLS服务器。在这个例子中,它工作得很好(我尝试过),服务器监听
INADDR\u ANY
和端口
0

fd = socket(server_addr.ss.ss_family, SOCK_DGRAM, 0);
setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (const void*) &on, (socklen_t) sizeof(on));
bind(fd, (const struct sockaddr *) &server_addr, sizeof(struct sockaddr_in))
当接收到DGRAM时,服务器通过OpenSSL方法运行它以生成cookie,并验证客户机实际位于他们所说的地址。完成后,服务器将创建一个绑定到同一端点的新套接字,并将
connect()
连接到新客户端的端点。

bind(fd, (const struct sockaddr *) &pinfo->server_addr, sizeof(struct sockaddr_in))
connect(fd, (struct sockaddr *) &pinfo->client_addr, sizeof(struct sockaddr_in))
因此,此时有两个UDP套接字绑定到相同的IP地址和端口。其中一个是
connect()
ed,另一个仅绑定

我也试着做同样的事情(在C中):

请记住,为了简洁起见,我删掉了大部分代码

此时,运行我的应用程序失败得很惨。似乎为客户机创建的套接字从未收到消息。基本上,对
wait clientSock.ReceiveAsync()的任何调用都会无限期挂起

但是,如果我调试并逐步执行,代码将正常工作。这让我相信这是插座之间的“竞赛”。基本上,可以在下一个DGRAM进入并发送到原始套接字之前创建、绑定和连接客户机套接字

好了,UDP套接字在计分系统上工作。内核根据给定DGRAM的路由具体程度计算分数,并将其发送到分数最高的套接字。所以,在我看来,我的服务器应该和示例一样工作。。。但事实并非如此

所以我并不是在问我的代码本身是否正确,但我想知道我所做的是否有意义。还有,如果有什么我没有考虑的因素。套接字的行为是否与我提到的一样


如果这种方法不能成功,我的替代方法是使用单个套接字,维护端点的哈希表,并在数据进入时将数据发送到适当的客户机。但是,我真的很喜欢利用套接字为我完成“繁重的工作”的想法。

保证这种排序的唯一方法是,如果更高层协议实现停止和等待。即使打开新套接字以快捷方式发送未来的数据包,您也最好从基本套接字执行数据包分派。要使服务器“连接()”到客户端,客户端必须已执行
socket()
bind()
listen()
accept()
。注意:端口0用于通信是一个非常糟糕的主意。事实上,任何小于1024的端口号都是一个非常糟糕的主意。给出了“保留”端口号(0…1023)的用法一般来说,要在这些端口上通信,“防火墙”必须设置为允许这样做communication@user3629249我们在这里讨论的是udp。。。。端口0既不是一个坏主意,也不是一个好主意。它允许套接字引擎选择临时端口。如果这适合应用程序,那么应该使用它。@user3629249显然您从未听说过UDP的
connect()
。确保这种排序的唯一方法是上层协议实现停止和等待。即使打开新套接字以快捷方式发送未来的数据包,您也最好从基本套接字执行数据包分派。要使服务器“连接()”到客户端,客户端必须已执行
socket()
bind()
listen()
accept()
。注意:端口0用于通信是一个非常糟糕的主意。事实上,任何小于1024的端口号都是一个非常糟糕的主意。给出了“保留”端口号(0…1023)的用法一般来说,要在这些端口上通信,“防火墙”必须设置为允许这样做communication@user3629249我们在这里讨论的是udp。。。。端口0既不是一个坏主意,也不是一个好主意。它允许套接字引擎选择临时端口。如果这适合应用程序,那么应该使用它。@user3629249显然您从未听说过UDP的
connect()
_sock = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
_sock.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
_sock.Bind(localEp);

var clientEndpoint = await DtlsListenAsync(ssl, _sock);

var clientSock = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
clientSock.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
clientSock.Bind(_localEp);
clientSock.Connect(clientEndpoint);