Advertisement

UDP networking

Started by March 03, 2017 01:41 PM
8 comments, last by hplus0603 7 years, 8 months ago

Hello,

After some times of research about network and TCP vs UDP for games (and in general). I started to understand that UDP have a lot of advantages over TCP for some points. But two questions stay unanswered for me at this time, maybe you have them?

My first question is mostly oriented around this article, it explain that using TCP and UDP at the same time is not a good idea because it increase the loss of UDP paquets because TCP tend to use all the network available for himself. The thing i didn't find however is what is concerned by this problem? Is it for the whole computer (so, the subject is mostly a failure since every server have almost always one TCP connexion active), or is it by application? And so the problem is more manageable.

The other question is about the UDP liaison and how to manage it programatically, if you are in a subnetwork and start a TCP connexion, there is no problem with the server responses since the connexion is already open and active, it can just use it. But in the case of UDP, how did that work? There is no alive connexions, so if the server respond it is possible that it just can't reach the player in his subnetwork, of course that can be fixed with some router configuration done by the player, but that's not ideal, or have i missed something about how UDP work?

I was thinking about using uPnP for that, but i'm not sure how to use it. Did some of you have some experiences with UDP C/C++ sockets and it's use behind a router/in a subnet?


My first question is mostly oriented around this article, it explain that using TCP and UDP at the same time is not a good idea because it increase the loss of UDP paquets because TCP tend to use all the network available for himself.

Read the article more carefully. It is dealing with a saturated network connection. Unless you have people streaming video next to you as you play a game, you probably don't have the saturated connection.

If you have saturated your connection, the article discusses how both systems suffer packet loss but TCP's protocol incorporates retransmission with sliding windows, but UDP's simpler solution does not incorporate retransmission with sliding windows.

There is nothing inherently different between how they use the network, it is only that TCP automatically does some things behind your back. Many games implement exactly the same thing --- or an even better variant --- so they don't suffer that problem.

The typical solution is that data is resent until acknowledged. There have been many posts on it (search the forums) but it looks like this:


Send: {A}  // Send block A
Recv: {Ack A} // Acknowledged, they got through that block.
Send: {B} // Send block B
Recv: {Ack B} // Acknowledged, they got through that block.
Send: {C} // Send block C.
Send: {C D} // Send block D plus unacknowledged blocks
Send: {C D E} // Send block E plus unacknowledged blocks
Recv: {Ack D} // Acknowledged, they got through that block
Send: { E F } // Send block F plus unacknowledged blocks 
Recv: {Ack F} // Acknowledged, they got through that block.
Send: { G } ...

When data is not acknowledged this requires a little more bandwidth than TCP's sliding windows, but the latency of the sliding window protocol is eliminated. For games the latency is usually a bigger issue than the bandwidth so it tends to work well.

There are ways to resend less data if the packets are deltas rather than full values, but that's more advanced than this conversation.


if you are in a subnetwork and start a TCP connexion, there is no problem with the server responses since the connexion is already open and active, it can just use it. But in the case of UDP, how did that work? There is no alive connexions, ... have i missed something about how UDP work?

Both work the same as far as the Internet Protocol goes, so as far as the routers care they're the same type of traffic, they're all Internet Protocol traffic. Some IP datagrams contain TCP content, others have UDP content, others have DCCP content, others have SCTP content, others may have other content.

The difference to you is that your TCP library keeps track of a bunch of other data for you. It handles the sliding windows and error correction data in a way similar to what was described above, it handles packing up small transmissions and combining them into a single datagram, it handles buffering data so it works as a stream rather than working as packets. The TCP libraries do all this behind your back.

If you are using UDP you can still do exactly the same type of work, you just need to do it all on your own instead of relying on a library to do it.


I was thinking about using uPnP for that, but i'm not sure how to use it.

Because of the questions you are asking, writing your own uPnP code is currently beyond your skills. You'll need to either use a library that does it for you, or continue to learn about networking until you reach the point where you can understand the uPnP protocol before using it.

Advertisement

Read the article more carefully. It is dealing with a saturated network connection. Unless you have people streaming video next to you as you play a game, you probably don't have the saturated connection.

I see, with the subject and this article and the network subject on Gaffer on Game i was thinking it was really something to be more concerned about that it seem.

If you ... that's more advanced than this conversation.

Thanks for the explanation, and sorry for the return of the subject, i didn't search well enough on the forum apparently :(

Both work the same as far as the Internet Protocol goes, so as far as the routers care they're the same type of traffic, they're all Internet Protocol traffic. Some IP datagrams contain TCP content, others have UDP content, others have DCCP content, others have SCTP content, others may have other content.

I see, my error was to look at the protocol level instead of the IP one, thanks for pointing that to me.

Because of the questions you are asking, writing your own uPnP code is currently beyond your skills. You'll need to either use a library that does it for you, or continue to learn about networking until you reach the point where you can understand the uPnP protocol before using it.

With networking being my most worked on and prefered domain and my skills up to forging paquets and filtering (In progress for this one), it's harsh to hear, but i admit it's true, i still have a lot of work to do before being at a good level. But my goal was at least to understand how it is implemented and use a library to do the work, not writting it myself. But if i understand well what you have tell before, it's not something necesary to use for what i want to do

The technical aspect is not too difficult if you know what you're doing. The first step (the harder of the two) is service discovery. Once you discover where your uPnP gateway is, you request a port mapping lease as briefly covered by this RFC if you want to implement it yourself.

It is generally easier to use a library, using existing code to find the service if it exists, request a port mapping lease, and release it when you are done. But if you want to implement all the details under the hood, go for it. There are several open source implementations you can study if you get stuck.

However, I still feel like if you are asking questions about how connections stay established similarly between TCP and UDP, I really do suspect that writing uPnP discovery and mapping code at the raw socket layer is currently beyond you.

With networking being my most worked on and prefered domain and my skills up to forging paquets and filtering (In progress for this one), it's harsh to hear, but i admit it's true, i still have a lot of work to do before being at a good level. But my goal was at least to understand how it is implemented and use a library to do the work, not writting it myself.

These two books will get you more than a running start:
https://www.amazon.com/TCP-Illustrated-Vol-Addison-Wesley-Professional/dp/0201633469
https://www.amazon.com/TCP-IP-Illustrated-Implementation-Vol/dp/020163354X

void hurrrrrrrr() {__asm sub [ebp+4],5;}

There are ten kinds of people in this world: those who understand binary and those who don't.

Thank you for the directions frob and katharr :)

However, I still feel like if you are asking questions about how connections stay established similarly between TCP and UDP, I really do suspect that writing uPnP discovery and mapping code at the raw socket layer is currently beyond you.

That's why i said

But my goal was at least to understand how it is implemented and use a library to do the work

I have miniupnpc available in my library (MSYS2), i will take a look at it to see how it work and use it if needed.

But first i will look at how connections stay established in UDP like you said, since i almost never used it i lack some knowledge about that part, for me UDP was just something that was sending packets to the designed IP/Port, and since there was no checking about reception. it was just simple not connected in any ways

Advertisement

But first i will look at how connections stay established in UDP like you said, since i almost never used it i lack some knowledge about that part, for me UDP was just something that was sending packets to the designed IP/Port, and since there was no checking about reception. it was just simple not connected in any ways


I'm not sure if you meant to say TCP here, but UDP is indeed a connectionless protocol. It's a small address layer on otherwise raw sock packets. If you're wondering how it is that you can send a UDP packet and get a response on the same socket through a NAT router, it's because the router looks at the address of the outgoing packet and remembers it for a short period of time so that it can route return traffic to the correct machine/service.

The UDP layer includes destination host/port and source host/port. When NAT gets an outgoing packet to 1.2.3.4:80 from 10.10.10.2:4567 it makes a note in a table with an expiration time. When an incoming packet arrives from 1.2.3.4:80 targeting port 4567 it looks that up in the table (assuming it hasn't expired) and knows to route the packet to 10.10.10.2:4567.

void hurrrrrrrr() {__asm sub [ebp+4],5;}

There are ten kinds of people in this world: those who understand binary and those who don't.

When NAT gets an outgoing packet to 1.2.3.4:80 from 10.10.10.2:4567 it makes a note in a table with an expiration time. When an incoming packet arrives from 1.2.3.4:80 targeting port 4567 it looks that up in the table (assuming it hasn't expired) and knows to route the packet to 10.10.10.2:4567.

That's exactly what i wanted to know when i asked if i was missing something about how work UDP when the server respond to the client! I was not aware that routers and other network device managed that part by themselves.

I start to think that my main problem with this post was how i asked this question (i should really work my english more ><) and maybe also to not have tried it before asking to see if that worked by default...

UDP packets are supposed have priority over TCP packets.
Not sure if they actually implement it that way though.

- The trade-off between price and quality does not exist in Japan. Rather, the idea that high quality brings on cost reduction is widely accepted.-- Tajima & Matsubara

UDP packets are supposed have priority over TCP packets.

There is no general rule that says this is true. Some particular routers or links may implement that kind of policy in the case of congestion, but that's not something you can rely upon in general.

enum Bool { True, False, FileNotFound };

This topic is closed to new replies.

Advertisement