2
\$\begingroup\$

I'm trying to make a UDP game server using the SDL_net library. This library offers SocketSets which are, according to the documentation, an analogy to the select function. Right now I have successfuly made a simple server which has just one UDPsocket and dumps every message to stdout.

Can I use those SocketSets somehow to make the server responsive, or am I just fine using only one UDPsocket for everything?

\$\endgroup\$

2 Answers 2

2
\$\begingroup\$

I guess the baseline you want any improvements in responsiveness of your service to be compared to is this:

You currently have a service which receives packets on a single UDP port. As each packet has been received it is processed and answers (if any) are sent. Once processing of a packet has completed, the main event loop starts over processing the next packet.

This is a quite reasonable starting point, because it will usually be the easiest way to implement the service, and in many cases it will be sufficient to serve the needs.

Assuming you already performed measurements on this implementation and found it to not be responsive enough under load, there are a few ways you can improve responsiveness. I will assume you are dealing with a large load from legitimate clients. How to protect a UDP services from DoS attacks is also an interesting question, but it does not sound like that is what you are asking.

Possible solutions include:

Drop some requests

This is not a great way to handle high load. But if the load goes high enough it will happen whether you want it to or not. You don't have to implement dropping of requests in your service. If your service can't keep up with incoming requests, the network layer will drop packets for you. You only need to implement dropping of requests in your service, if you feel you can do a better job at choosing which requests to drop than the network layer would do for you.

A properly implemented client will usually implement some retransmission strategy with an exponential backoff. So the dropped requests will keep coming until you are able to process them.

Prioritize requests

This is desirable compared to dropping requests. Prioritization means that some requests will get improved responsiveness while other requests gets worse responsiveness. You have to decide which requests are most important to get improved responsiveness for.

Using multiple ports is one way to implement prioritization, but not necessarily the best. It is not a very flexible way to prioritize, because you can only prioritize based on which of the ports packets arrive at.

A different way to prioritize is to receive all packets from the socket and use a priority queue inside your service. This can be done using a single UDP port. As long as there are packets available on the port you receive a packet from the port and put it in your service' priority queue. When there are no more packets available from the port you process the highest priority request, and send responses (if any).

There is a few caveats to this approach. First of all, you need to ensure your priority queue doesn't grow too large. You don't want the priority queue to get written to swap, so it is better to drop the lowest priority (or the oldest) requests from the queue before it grows too large.

Secondly you need to ensure that you can receive packets from the networking layer into your priority queue at line-speed. Otherwise you may end up in a situation where all the service has time to do is prioritize incoming requests to decide in which order to drop them, because it never finds the time to process any of them.

So though prioritization can be somewhat flexible, it still has to be lightweight enough to not become a bottleneck. If prioritization of requests consume as much CPU time as processing requests, it is not very useful.

If you are going down this route, then the use of more than one UDP port will make it more work for you to implement the prioritization of requests.

Identify and drop obsolete requests

Sometimes under load it is possible you end up processing requests which are no longer relevant. It may be the client already retransmitted the request or that a later request makes the data you are processing in an earlier request obsolete.

If a request from one client requires the service to send updated data to multiple other clients, it could be that there are multiple such requests in the queue, and it would be more efficient to process all of them and only then send updates to the clients.

By queuing requests inside your service, such optimizations become possible. But this is highly application specific, so only you know whether such optimizations apply to you.

Optimize your processing

If you can reduce the time needed to process each individual request, that may improve responsiveness more than any prioritization ever could. But of course there are limits to how much improvement is feasible.

In conclusion

Using multiple UDP ports can be useful in some situations. But if your goal is to improve responsiveness, then using multiple UDP ports is not the first approach you should consider.

Unless you already know what the difference between the packets you want send to the two ports is, there is little reason to use two UDP ports.

Using multiple UDP ports is usually done for other reasons such as the communication used on the two UDP ports is so different in nature that you are essentially using two different protocols on the two ports.

\$\endgroup\$
0
\$\begingroup\$

One socket should be enough, but you could split traffic between them, e.g. handling chat on a separate port, so you could later move that to its own server more easily (although I'd use TCP for that).

\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .