Quick UDP Questions for D!mb@sses

Started by
9 comments, last by starbasecitadel 11 years, 2 months ago

I've been doing a lot of reading and research on UDP as opposed to TCP.

My problem is how to UDP Multicast. So I just have a few straight forward questions I'm hoping anyone can help me with.

  • Q1: UDP Multicasting only works on Local Networks, there is no way to "Broadcast" clients over the web. Correct?
  • Q2: If I can't Multicast, then my only solution is to have a small database of users, and loop through their IP Addresses and send a packet one at a time to each client over the web?
  • Q3: If I have to do this loop solution, then I have to keep an eye out for CPU usage and network usage?
  • Q4: People say a dedicated server is not needed for UDP in any case. Is this correct?

Let me know if I'm missing something important in my quest to experiment more with this protocol.

What i'm trying do to [DotNet/C#]:

Have 1k users divided by 5 or so different broadcast rooms, (Like a chat room). And users in their specific rooms receive their messages without using a broadcast loop.

Since Multicasting only works on Local Networks... there's my new obstacle.

Thanks in advance for the help!

Advertisement

Q1: Yes, my understanding is Multicast only works on local networks and/or networks with the right router configuration. On the internet, there are too many routers that won't properly pass through a Multicast message for it to be effective, perhaps except for a tiny number of people. Maybe someone else can chime in here definitively, but that is what I have found having quickly researched it several times.

Q2: Yes. Even if it's the exact same message, you have to loop through every IP/port you want to send it to and fire it off to each person.

Q3: Yes, however with something as a simple loop, the network side is going to be the bottleneck, not the CPU time. You have to calculate the number of bytes per UDP datagram and multiple that by the number of users and again by the number of messages to send per second/minute. You will end up with bytes per second, which you can then convert into mbps (megabits per second) and MB / TB per month which are the figures web hosting companies will use to price their network service in terms of bandwidth and network interface cards needed.

Q4: I don't understand this question exactly. No, you don't need a dedicated server to develop or run UDP applications, but in some cases (where your hardware requirements are greater than a VPS can easily accommodate) you can run into situations where you need dedicated hardware. In your particular case, you should be fine with a VPS or running the server on a personal desktop with still enough room to spare other applications running at the same time.

Hey StarbaseCitadel,

Thanks for the in depth responses. Will really come in handy going forward.

Quick Follow Up:

My application is relatively small, the largest packet is about 100 bytes. I don't see it getting larger anytime in the future.

  • If each room has about 1,000 people (I know, unlikely), and I send that packet each second, that's about 781.25 Kbps right?
  • Is it fair to assume most clients should be able to handle something like that? Or should I shift my focus to a dedicated server. Clients send their signal once to that server. And that server does the relay/loop?

I guess my question is at what point should a UDP Dedicated server come into play?

Thanks,

-T

Yes, that is roughly 781 - 825 or so Kbps (including 28 bytes for overhead per UDP packet too), looks good.

This assumes that 100 byte packet contains all the information for all the updates for every player for that second. In other words, that assumes every second, at most 10 players out of the 1000 will send a 10 byte message, or 5 players will send a 20 byte message etc. If that is what you have in mind, then yes, that will come to 781-825 Kbps.

I think your overall question is whether to design the architecture as "peer-to-peer", or "client-server".

In peer-to-peer, there is no centralized server. Each client, when sending a new text message to the chart room, fires off a message to the 999 other players. In this instance, they aren't receiving 1 packet containing a summarized list of all messages from everyone else, they instead receive 1 packet for each individual message.

So they might get messages like this:

(username | room # | message )

"David|3|Hey there!" - 18 bytes + 28 bytes of overhead = 46 byte UDP packet

"Sonya|7|brb" - 11 bytes + 28 bytes of overhead = 39 byte UDP packet

etc

The overhead of 28 bytes per packet really starts adding up, since each individual text message (I assume?) is on average so small. So let's take an average of 10 messages per second altogether, of each being 10 bytes (which I sort of arbitrarily came up with). In that case you are looking at 38 bytes per packet, with 10 packets per second. That is 388 bytes per second, or about 3,100 Kbps (3 Mbps).

In terms of can a typical client handle it? I'm at a coffeeshop now and speedtest.net gives me 17 Mbps download and 4 Mbps upload, but it is a nice connection. I'm seen several places that have a tenth of that. I think if your requirement is 3 Mbps that is fine for broadband users and most coffeeshops etc. But, it will fail for 3G wireless users and places with relatively poor connections.

With a client/server model, the network requirements are lower (it uses less bandwidth), because it is more efficient in terms of combining the message. Also, the clients have far less upload network usage. They just upload to a single IP (the server), instead of all the other clients. So with the server model, it is much easier for you to support a larger variety of clients since you are looking at only about 1 Mbps instead of 3 Mbps, since you are sending less overhead (the single packet combines multiple text messages into 1).

Keep in mind you will probably need some kind of client/server model regardless. That is because you will need some sort of lobby so that clients know all the IP/ports of all the other clients currently connected. The networking requirements to handle that lobby (getting a list of all IP/ports, users entering and leaving chat etc) might take nearly as much as the main chat server anyways, so you may as well just do client/server.

So I'll more than likely need a way to Authenticate those packets, so I think you're right, a Client/Server model is the way to go anyway. Thanks for the wealth of information again StarbaseCitadel. Will really help me to make a great game.

Welcome!

Also in case you are new to the programming side of it, here is a very good explanation on UDP game programming using the Lua language (but the logic applies to any language):

https://love2d.org/wiki/Tutorial:Networking_with_UDP

One final thing to mention is what is called the MTU limit. The MTU is a router setting after which number of bytes messages get broken up (fragmented) automatically. The bottom line is due to problems that can occur with fragmentation it is considered good design to limit the size of any UDP message to 800 bytes or less (so including overhead, that is 772 bytes or less in the message). You should split up larger messages into separate packets if you exceed that, to be safe. In your case, you should be fine as is, but just be aware once you exceed around that number like getting to 900 bytes, 1500 bytes etc, there is a greater and greater chance of either complete packet loss or a delay, say latency increasing from 50ms to 400ms etc.

Hey thanks for the link and the tip about the MTU Limit. Would you happen to have any links that describe how to:

  • Detect that a packet was not Sent.
  • Send another one after such an event.

Basically the whole idea of how to deal with "Packet Loss" in UDP in general. (C# Preferably)

I read somewhere that you can include a number in the packet, some kind of ID number.

I do appreciate the clarification on this. :)

No problem!

I don't have any links for those, but can add a bit on the logic side of it.

You basically have to add your own code to handle both those cases.

For the first case, detecting whether a packet was sent or not. There are various ways to do it. A rigorous way is the server not only sends the message, but also adds a unique auto-incrementing number as a header and keeps that message stored in memory along with a timestamp of when it sent it.

The server continues to resend that message, say once every 2 seconds for up to 10 seconds and then it discards it as unsendable.

The client, upon receiving the message, sends a response back to the server with that ID # (an "ACK" request basically) confirming it has been received. The server receives this "ACK", and then removes the message from its queue so it doesn't resend the message needlessly.

The client also keeps track in memory of a list of all these ID #'s it has received along with a timestamp, and it disregards any message it encounters multiple times. After say 30 seconds, it can delete this entry from memory.

There are more complex ways to do it, including various summarization schemes where the server sends to the client "here are the ID's of the last 10 messages I sent you, please confirm". But as you can see, at a certain point, this handshaking code might become more complex than the main logic itself. At that point you have to ask yourself is it worth spending the time implementing this, to increase the chances of delivery from 99% to 99.95% or whatever? Also, in some cases just using TCP is easier for this kind of thing if you require confirmed delivery, though you typically don't want to mix TCP and UDP. (It is easy enough to do but can cause minor network latency issues).

Most chat servers would just use TCP for this reason, not UDP, though this is an excellent project to begin to get familiar with UDP programming so from that point of view nothing wrong.

In terms of getting the order correct, that is again something TCP handles for you automatically but UDP will typically get 1% or less of messages out of order. Once again, using that same ID the client can make sure the ID # is the largest it has seen, otherwise it has to insert the message not at the bottom of the list of messages but somewhere in between, or it can choose to ignore it by discarding the message.

The messages I'm sending in this case are really combat only related messages. So I guess I have to ask myself if a message like that doesn't get there, "Is that even a problem?"

In these messages, i'm just sending "Player A Fired Weapon B", and small data related that that projectile.

I'm already sending "Player Died" via TCP, so that should be ok.

So let me recap:

  • The UDP Server Receives a Message
  • It then relays the message 5 times to 1k people (We're looking at two different loops, one apparently large, scary stuff to me)

And I need to make sure the Server's connection can handle that. I'm certainly worried about how long it'll take to go through a loop like that. But from what I've learned in this topic, it's the only way when dealing with UDP.

Let me know if you have any additional thoughts, and thanks again for the eye opener.

I'm just wondering if this is possible. In my testing, im seeing a lot of packets lost. Because of the insane amount of packets being sent per second, I'm wondering if this is UDP blocking i've been reading about? Could it be something else?

CPU usage is down, so is network usage.

It only comes up when sending a 60 byte packet to 20 people each second.

This topic is closed to new replies.

Advertisement