Three short questions about UDP

Started by
9 comments, last by GameDev.net 17 years, 10 months ago
(I'm using VB.NET and the UDPClient object) Please also note that all the following is regarding SERVER application only. I read the following from the FAQ: Should I spawn a thread per connection in my game code? A10) The short answer is "likely no." The longer answer is that, if you're using UDP, you should only need a single socket, from which you can read a packet, process a packet, repeat. 1) It says I can use UDP as a single socket. Does this mean I can use a single socket for 1000 users to both send & receive? 2) When binding a port to a UDP Server does that port always remain the same? 3) In a server application using UDP, is it standard to have two UDP sockets. One for send & one for receive which handles the work for up to a 1000 users? OR Should each user connected to my server have their own set of UDPClient objects? One for send and one for receive? So the data goes exclusively to each user (since I have created a new class for each connected user). In conclusion If I have only two UDP sockets, one for receive & one for send and 32 users are connected, I will be receiving messages from all the users on one port in which then I have to redirect the received message to the right user (which involves a loop of some kind). Is it better for each user to have their own set of UDP sockets (their own ports) or just use one set of UDP sockets for all users. Sorry if this is a totally off the wall question. [Edited by - luzarius on May 31, 2006 3:12:49 AM]
Advertisement
1. Yes. I don't know about VB, but in C/C++, the functions you use are recvfrom() and sendto(). Both of them take a socket and an address. That allows you to send data to anyone, and recv data from anyone.

2. For the duration of the socket, yes. If you restart your application, that port might be in use by another application (Although it's pretty unlikely). Generally, you want to bind to a port right after creating the socket, and then you shouldn't have ro re-bind.

3. It's standard to use one socket, which is used for both send and recv. You call recvfrom() in a loop (Again, that's in C, but VB should be similar), and you get returned the data recieved, and the address of the user it's from.
In addition to Steve's answers, under .Net you can use Socket.RecvFrom() and Socket.SendTo() for UDP communication through a single socket. I've never used it but UdpClient.Send() and .Receive() seem to be equivalent.
Warning: if you use two sockets, then your application will likely not be NAT compliant, as the "source" address of your outgoing datagrams will not have the same port as the "destination" of the incoming datagram.

Typically, you'll use a single socket, and a single read loop. The read loop will use a hash table to look up clients based on the address received from RecvFrom(). If the address is "new" (not previously recognized) then do whatever you need to do to authenticate the client, and create a new entry in the hash table.
enum Bool { True, False, FileNotFound };
Quote:Original post by hplus0603
Warning: if you use two sockets, then your application will likely not be NAT compliant, as the "source" address of your outgoing datagrams will not have the same port as the "destination" of the incoming datagram.

Typically, you'll use a single socket, and a single read loop. The read loop will use a hash table to look up clients based on the address received from RecvFrom(). If the address is "new" (not previously recognized) then do whatever you need to do to authenticate the client, and create a new entry in the hash table.


Sounds good. I'll use a single socket like you said with the table to look up clients based on the address received.

Is it ok to throw a 4 byte unique ID in each UDP packet to identify the user with ease?

About the unique ID, 2 bytes should be enough. According to some faq, q3 uses 2 byte random ID. 4 bytes sound like a waste of bandwidth :)
Though, baking an ID into the packet is dangerous from a security standpoint. A user could spoof another user by tossing a known or random ID. It's safer to go by unique address.
[sub]My spoon is too big.[/sub]
You should go by unique address. Unique ID is not safe, because someone else can guess it and send you spoofed packets.

However, if someones firewall re-sets itself, and generates a new external UDP port for the session, you will get packets from the middle of a session from some user you don't know who he is. This is rare, but does happen. Here's one way to resolve it (there are plenty others, too):

1) put 2 byte uniqe IDs in each packet
2) normally, you check that data from a specific IP has the appropriate ID -- if not, just drop the packet
3) when receiving data from a new IP/port combination, check the ID. if it's non-0, and you haven't heard from the old client using that ID for at least 5 seconds, update the address of that client
4) if you receive an unknown IP/port with a 0 id, this means a new client is trying to connect; allocate a new ID and send it to him
5) if you receive an unknown IP/port with an existing ID, but have received a packet from the previous address in the last 5 seconds, drop the packet

enum Bool { True, False, FileNotFound };
Well, I guess if you really had the time you could implement a sort of cryptographic algorithm to help you with your security. You could try out some way to provide an encryption/decryption method, such as a public key algorithm or hashing algorithm that will at least discourage anybody who wanted to spoof an ID. I'm not sure you want to do that for just one ID though. And I know there are ways to do this for TCP, but I'm not sure for UDP.

Anyway, I agree with Renderer and hplus0603 about using the address:port pair. It's a lot simpler.

[Edited by - Hanatarou on June 1, 2006 1:10:17 AM]
Quote:Original post by hplus0603
You should go by unique address. Unique ID is not safe, because someone else can guess it and send you spoofed packets.

However, if someones firewall re-sets itself, and generates a new external UDP port for the session, you will get packets from the middle of a session from some user you don't know who he is. This is rare, but does happen. Here's one way to resolve it (there are plenty others, too):

1) put 2 byte uniqe IDs in each packet
2) normally, you check that data from a specific IP has the appropriate ID -- if not, just drop the packet
3) when receiving data from a new IP/port combination, check the ID. if it's non-0, and you haven't heard from the old client using that ID for at least 5 seconds, update the address of that client
4) if you receive an unknown IP/port with a 0 id, this means a new client is trying to connect; allocate a new ID and send it to him
5) if you receive an unknown IP/port with an existing ID, but have received a packet from the previous address in the last 5 seconds, drop the packet


Thanks so much that sounds good.

This topic is closed to new replies.

Advertisement