Using both TCP and UDP?

Started by
6 comments, last by hplus0603 11 years, 9 months ago
To learn both protocols I had recently made two server/client models each using the UPD/TCP to practice interpolating movement and chat message packet handling. Now that I understand both protocols more I'm curious how best to go about my actual game server architecture. The server generates the world procedurally and will need to send large chunks of data: when a player first logs in, or when a player moves to a new cell and needs that cell's height for vertices, and static models, etc. (Cells will be saved on client's computer once downloaded)

While making the two test server/clients I came to really like UDP more however I can't just stuff 80k+ worth of data into a single packet and I need reliablity for the packets. So I figured instead of trying to implement a layer over UDP to make sure I get several packets' worth of data for a single cell, I could use TCP for those packets and just stream the data.

However, I prefer UDP for movement and other details that are time sensitive so my question is - Can't I just use two separate ports, one for TCP traffic and one for UDP traffic? Have the client send requests for cell data on TCP port, and clients/server communicate over UDP for position, action responses, etc? Is there some none-obvious hurdles I might come across?
Advertisement
You probably can, I'm not sure. However, there are many other reasons to not use TCP for any real time data. It would be better to make your own reliability layer/big packet handling layer over UDP that suits your needs better. There are, of course, many libraries out there that do this already. I used ENet in my code and it worked fine, although it wasn't quite as flexible as I wished (I had some weird requirements though)
Sure, it's possible to simultaneously use both UDP and TCP.

We use that technique, but mostly for compatibility fallback purposes: clients primarily connect through UDP, but if firewalls/NATs don't allow, then go through TCP (and finally very brutishly through TCP 80). Our networking uses the kNet library, which abstracts the underlying TCP/UDP choice and exposes a message-based API.

To solve sending messages larger than the IP MTU, we manually fragment the messages to several UDP datagrams, and reassemble them on the receiving end. It's doable, and an alternative to using TCP.

If you're looking to utilize two socket connections, one TCP and one UDP simultaneously (also the same if you used two TCP ports), perhaps the first problem is that you won't have ordering, (or atomicity, when TCP is involved) guarantees across the two ports. E.g. sending to port A, then to port B, might be seen on the other end as receiving (even partially!) first from port B, then (again partially!) from port A, then from port B, port A, and so on.
Is the procedural generation deterministic? If so, can you just send the random seed used to generate the block, and let the client calculate the terrain itself? You could even pre-send block seeds for blocks "around" where you currently can see, so they're ready by the time you move there.

Another option is to send a reference to a block (such as a URL) to the client using the UDP packet stream, and then have the client request the block data using TCP of some sort -- for larger data transfers, HTTP is pretty good!
enum Bool { True, False, FileNotFound };
A few years ago, TCP was considered inducing packet loss in UDP, which is why it was advised not to use the two together. Also UDP was considered inferior for bulk transfers because routers favoured TCP in their QoS. Or so the myth said... I've never experienced it.

In fact, I believe that in presence of voice-over-ip and video-on-demand, both of which send bulk data over UDP and have rather harsh requirements on real-time delivery of packets with not-so-much loss, the opposite is true nowadays.

Sending terrain patches is actually a good candidate for UDP, in my opinion. Reliability is no issue. Send out 20 patches, and let the client report back which ones it got, in the same way as with TCP. If packets are lost, they must be resent either way, TCP only does it without explicit interaction from your side, but it does not do magic (it still has to receive ACKs and resend). Or go to PGM way, send out 20 patches and let the client know how many you sent. It will complain (NACK) when it didn't get what it expected.

Humans, like most animals, are social. Put more than one in an empty space, and they will group together. It is none different in a virtual world. Which means many players are likely to need the same terrain patches at more or less the same time. Many small, identical messages sent to many receivers lends itself ideally to UDP.
Thanks for the responses guys, I'll just stick with UDP only then and keep it simple.

hplus, your answer is great but it also makes me go "Now why didn't I think of that!?", especially considering the terrain generation is still on the client side as I was testing it there to get it all working first... ugh tongue.png!

samoth - I guess I was first looking for an easier answer to trying to send all that data instead of creating a way to handle breaking the cells into parts and getting them all to the receiver and reassembling them. Thus my first thought was TCP since I can just pack the cell in one large array, stream it and let TCP handle the breaking and re-assembly and at receiving end just expect a certain size. Plus that's good advice about players hanging close together, I'll be keeping that in mind.

Thanks again everyone.

A few years ago, TCP was considered inducing packet loss in UDP, which is why it was advised not to use the two together. Also UDP was considered inferior for bulk transfers because routers favoured TCP in their QoS. Or so the myth said... I've never experienced it.


TCP does kill UDP and VOIP. So you have to be careful you're not starving your UDP channels with unthrottled TCP traffic.

Everything is better with Metal.

BTW, 'we' use TP and UDP sockets. The worse decision ever.

Stick with one or the other if you can.

Everything is better with Metal.

TCP does kill UDP and VOIP. So you have to be careful you're not starving your UDP channels with unthrottled TCP traffic.
Well, it doesn't for me. I can have 3 simultaneous phone calls (3 people sharing one 16 Mbit DSL access with telephone going exclusively over VoIP) and I can meanwhile download a Linux distro no problem, have a mail client running and roughly 15-20 browser windows open, and do whatever... who knows what the other two are doing in that time.

I never hear as much as a single dropout, and I've never heard anyone else complain about the "goddam crap telephone that isn't working again". Never, not once.
I never hear as much as a single dropout,[/quote]

This means one of two things:

1) Your available bandwidth is actually higher than the bandwidth the other end gives to the download, so you don't saturate the link.
or
2) Your router/network infrastructure actually makes proper use of QoS.

Note that this is a bitfield -- both could be true :-) Which would put you in the minority of the world's internet users.
enum Bool { True, False, FileNotFound };

This topic is closed to new replies.

Advertisement