Jump to content
  • Advertisement
Sign in to follow this  
Florian22222

combine tcp&udp

This topic is 2643 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

hi. i have a general question about network gameprogramming. how i red in an article about the basics the author said that you shouldnt use udp and tcp together. but when i write an action-mmo where i can shoot a fireball how can i be sure that the server got the command?

only using tcp would be too slow. but combining both can cause a conflict on the ip-layer.

Share this post


Link to post
Share on other sites
Advertisement
The common solution is to use UDP only, and write your software so that it knows how to keep track of whether packets are lost.

One way to do this is to categorize your messages into 'reliable' and 'unreliable' data. In each packet, you send some reliable and some unreliable data.

The unreliable data is stuff that you send often enough that you don't care if you lose some packets. For example, if you're sending absolute positions of players, you can usually use unreliable data.

The reliable section of a packet contains a sequence number, saying which order the reliable messages are meant to be read in. Each endpoint stores the sequence number that they're expecting to receive next. If they receive a packet, they can see if they've lost data or received a duplicate by comparing the expected sequence number with the one in the packet.

When sending reliable data, you keep sending it until the other guy responds with a packet that says 'I have received up to sequence number X'. You keep sending the same reliable data until it's acknowledged.



There are lots of different variations on this idea, but that's generally how you can have both reliable and unreliable data using only UDP.

Share this post


Link to post
Share on other sites

hi. i have a general question about network gameprogramming. how i red in an article about the basics the author said that you shouldnt use udp and tcp together. but when i write an action-mmo where i can shoot a fireball how can i be sure that the server got the command?

only using tcp would be too slow. but combining both can cause a conflict on the ip-layer.


you can implement reliable protocols on top of udp aswell.

Share this post


Link to post
Share on other sites

only using tcp would be too slow. but combining both can cause a conflict on the ip-layer.


Only using TCP is not too slow.
Combining both can not cause a conflict on the ip-layer.

Share this post


Link to post
Share on other sites

[quote name='Florian22222' timestamp='1316720148' post='4864817']
only using tcp would be too slow. but combining both can cause a conflict on the ip-layer.


Only using TCP is not too slow.
Combining both can not cause a conflict on the ip-layer.
[/quote]

The difference between TCP and UDP is that you don't control the size of the packet with TCP. If you have a 33 kbps modem, a single MTU of 1500 bytes on the modem could lock up the transmission channel for half a second (500 ms). Even with 500 byte MTUs, you'd get blocked for almost 200 milliseconds per TCP segment.

On modern broadband, the effect of this problem is much less noticeable.

TCP is not "slow," however, it may cause "lag" in the messaging layer, because the kernel will withhold newer information that it has, waiting for older information that it missed, so that it can deliver the data in sequence. For many games, even action-like games, this can still be sufficient. Only real FPS games *need* UDP data streams.

Maybe you could check out the Enet library, which gives you "channels" and delivery classes (reliable vs not) for messages, over UDP. It, and other libraries, are suggested in the forum FAQ.

Share this post


Link to post
Share on other sites
Thank you for your answers. do i need to start a new thread for all the networking stuff or can i do the whole networking stuff in update() if i use non-blocking calls?

Share this post


Link to post
Share on other sites

Thank you for your answers. do i need to start a new thread for all the networking stuff or can i do the whole networking stuff in update() if i use non-blocking calls?


Udp should be fine, [s]but tcp could easily block the thread if there is some kind of connection problems, or the sender has a slow connection. non-blocking only means that it want block the thread if nothing is received, but as soon as the user in the other end starts sending data to you, it will block until everything is received.[/s] For udp there is no risk of the other person timing out while you're receiving the data, since you don't need to tell the sender that the data was received.

If your game depends on receiving all data between each step - like some rts and tbs - then there's nothing wrong with running the tcp connection from the same thread.

Edit: My bad :/

Share this post


Link to post
Share on other sites

[quote name='Florian22222' timestamp='1316751008' post='4865013']
Thank you for your answers. do i need to start a new thread for all the networking stuff or can i do the whole networking stuff in update() if i use non-blocking calls?


Udp should be fine, but tcp could easily block the thread if there is some kind of connection problems, or the sender has a slow connection. non-blocking only means that it want block the thread if nothing is received, but as soon as the user in the other end starts sending data to you, it will block until everything is received. For udp there is no risk of the other person timing out while you're receiving the data, since you don't need to tell the sender that the data was received.
[/quote]

I don't understand this caution. When used correctly (with select(), or I/O completion ports, or non-blocking sockets), then there is no risk of blocking. select() simply will not return a socket as readable, or writable. Once select() returns a socket as readable, you are guaranteed that at least one call to recv() will not block, and may return 1 or more bytes. This is why recv() often returns less than your full buffer size -- it simply returns what's in the socket receive buffer, without waiting for more, if there's at least on byte in that buffer.

So, if send() may send less than you want, or in fact if select() may decide that you can't send() at all, what do you do? You buffer in the application layer. This means that, if a recipient has less available bandwidth than you try to send to him/her, your application-level queue will grow in RAM. Thus, you should have a maximum queue size in RAM, and if any connection goes above that size, you should simply drop that user -- that user cannot keep up with the necessary data rate.

This is one reason it's important to build your networking to use the least bandwidth possible -- it makes more users able to actually play your game without lag or disconnections!

Share this post


Link to post
Share on other sites

[quote name='VildNinja' timestamp='1316758587' post='4865036']
[quote name='Florian22222' timestamp='1316751008' post='4865013']
Thank you for your answers. do i need to start a new thread for all the networking stuff or can i do the whole networking stuff in update() if i use non-blocking calls?


Udp should be fine, but tcp could easily block the thread if there is some kind of connection problems, or the sender has a slow connection. non-blocking only means that it want block the thread if nothing is received, but as soon as the user in the other end starts sending data to you, it will block until everything is received. For udp there is no risk of the other person timing out while you're receiving the data, since you don't need to tell the sender that the data was received.
[/quote]

I don't understand this caution. When used correctly (with select(), or I/O completion ports, or non-blocking sockets), then there is no risk of blocking. select() simply will not return a socket as readable, or writable. Once select() returns a socket as readable, you are guaranteed that at least one call to recv() will not block, and may return 1 or more bytes. This is why recv() often returns less than your full buffer size -- it simply returns what's in the socket receive buffer, without waiting for more, if there's at least on byte in that buffer.

So, if send() may send less than you want, or in fact if select() may decide that you can't send() at all, what do you do? You buffer in the application layer. This means that, if a recipient has less available bandwidth than you try to send to him/her, your application-level queue will grow in RAM. Thus, you should have a maximum queue size in RAM, and if any connection goes above that size, you should simply drop that user -- that user cannot keep up with the necessary data rate.

This is one reason it's important to build your networking to use the least bandwidth possible -- it makes more users able to actually play your game without lag or disconnections!
[/quote]

but send() blocks as long as you get the confirmation from the other side...so i have to start a thread if i use tcp..

Share this post


Link to post
Share on other sites

but send() blocks as long as you get the confirmation from the other side...so i have to start a thread if i use tcp..


Of course it doesn't. It would make TCP useless. Or more accurately, with non-blocking socket it reports when socket would block and only sends part of data, allowing you to schedule the rest for later. Send also only blocks until it can move data into send buffer, not until it's send let alone acknowledged. It indicates data was moved to kernel.

Even if blocking, sockets do not wait for confirmation, which is a bit of issue if dealing with reliable data (think bank transactions), since despite API reporting it completed the send(), the data is not guaranteed to be acknowledged by host.

The way TCP works it's also impossible to make such guarantee. TCP will, at some point in future, acknowledge that segment arrive to network layer unchanged and in proper order and that it was put into socket's buffer. But it cannot in any way guarantee that this data was processed, which is the important part.

To acknowledge receipt of some data application needs to manually send confirmation. TCP merely guarantees that data transfers correctly and if any errors are detected, attempts to recover them or signals failure.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!