问题
I've been following (roughly) some example code here on writing a DTLS server that can handle multiple clients. In this example, which works quite well (I tried), the server listens on INADDR_ANY
and port 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))
When a DGRAM is received, the server runs it through an OpenSSL method to generate a cookie and verify the client is actually at the address they say they are. Once that's done, the server creates a new socket bound to the same endpoint and does connect()
to the new client's endpoint.
bind(fd, (const struct sockaddr *) &pinfo->server_addr, sizeof(struct sockaddr_in))
connect(fd, (struct sockaddr *) &pinfo->client_addr, sizeof(struct sockaddr_in))
So at this point, there are 2 UDP sockets bound to the same IP address and port. One of them is connect()
ed and the other is only bound.
I've tried to do the same thing (in 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);
Keep in mind, I've edited out most of the code for brevity.
At this point, running my application fails miserably. It seems the socket created for the client never gets the messages. Basically any call to await clientSock.ReceiveAsync()
hangs indefinitely.
However, if I debug and step through the code works. This leads me to believe that its a "race" between the sockets. Basically, can the client socket be created, bound and connected before the next DGRAM comes in and gets sent to the original socket.
AFAIK, UDP sockets work on a score system. The kernel calculates a score based on how specific the rout is for a given DGRAM and sends it to the highest scoring socket. So, it seems to me that my server should work as well as the example... But it doesn't.
So I'm not really asking if my code is right per se, but I'd like to know if what I'm trying to do makes any sense. Also if there are any considerations I haven't taken into account. Do sockets behave as I mentioned?
My alternative if this method doesn't pan out is to use a single socket and maintain a hashtable of endpoints and dispatch the data to the appropriate client as it comes in. But TBH, I really like the idea of leveraging sockets to do the "heavy lifting" for me.
来源:https://stackoverflow.com/questions/57281657/handling-multiple-udp-sockets-listening-on-the-same-endpoint