我一直在(大致)遵循一些示例代码here编写可以处理多个客户端的DTLS服务器。在这个例子中,效果很好(我尝试过),服务器监听
INADDR_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))
因此此时,有 2 个 UDP 套接字绑定到相同的 IP 地址和端口
。其中一个是 connect()
ed 的,另一个只是绑定的。
我尝试做同样的事情(在 C# 中):
_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);
请记住,为了简洁起见,我已经删除了大部分代码。
此时,运行
my 应用程序惨败。似乎为客户端创建的套接字永远不会收到消息。基本上任何对 await clientSock.ReceiveAsync()
的调用都会无限期挂起。
但是
,如果我调试并单步执行,代码就可以工作。这让我相信这是套接字之间的“竞赛”。基本上,可以在下一个 DGRAM 进入并发送到original套接字之前创建、绑定和连接客户端套接字吗? 据我所知,UDP 套接字在
score系统上工作。内核根据给定 DGRAM 的路由具体程度来计算分数,并将其发送到得分最高的套接字。所以,在我看来,我的服务器应该和示例一样工作......但事实并非如此。 所以我并不是真的在问我的
code本身是否正确,但我想知道我想做的事情是否有意义。另外,如果还有什么我没有考虑到的因素。套接字的行为是否像我提到的那样? 如果此方法不起作用,我的替代方案是使用单个套接字并维护端点的哈希表,并将数据发送到适当的客户端。但是说实话,我真的很喜欢利用套接字来执行以下操作的想法对我来说“举重”。