TCP vs UDP?

Discuss anything that is related to OpenArcanum.
Post Reply
User avatar
Crypton
Arronax's Best Friend
Arronax's Best Friend
Posts: 420
Joined: Wed Jul 08, 2009 5:04 am
Location: Abyss
Contact:

TCP vs UDP?

Post by Crypton » Sun Oct 03, 2010 12:36 pm

Howdy,

at this moment I'm thinking about switching from TCP to UDP, and it would be nice to get some suggestions/recommendations from you, community.

Arcanum uses TCP, OpenArcanum uses TCP as well, but many sites and tutorials recommends using UDP as communication protocol for MMORPG based games. On the other hand, some sites says that its possible to make MMORPG with TCP.

What do you think? I need some opinion before I jump into serious network programming, because later, it will be much harder to switch to UDP.

;)

evillive
Bunny
Bunny
Posts: 7
Joined: Mon Oct 04, 2010 12:21 am

Re: TCP vs UDP?

Post by evillive » Mon Oct 04, 2010 12:52 am

Hi Crypton! or ZeroBot? :D
ZeroBot wrote: Arcanum uses TCP, OpenArcanum uses TCP as well, but many sites and tutorials recommends using UDP as communication protocol for MMORPG based games. On the other hand, some sites says that its possible to make MMORPG with TCP.
Yes, with UDP u may get a better latency, but you also may get good enough via TCP with TCP_NODELAY flag enabled. There are many good MMORPG's on TCP, such as Lineage 2, and more recently - WoW (yes, i heard it is on TCP now).
ZeroBot wrote:
What do you think? I need some opinion before I jump into serious network programming, because later, it will be much harder to switch to UDP.

;)
Dependency Inversion Principle says "Program to an abstraction, not an implementation". Ideally, you shouldn't depend on underlying protocol and be able to switch easy in any time. I'm not a C++ developer, but i believe there are frameworks, like Netty for Java, that helps you to not depend on concrete transport protocol.

User avatar
Crypton
Arronax's Best Friend
Arronax's Best Friend
Posts: 420
Joined: Wed Jul 08, 2009 5:04 am
Location: Abyss
Contact:

Re: TCP vs UDP?

Post by Crypton » Mon Oct 04, 2010 2:31 am

evillive wrote:Hi Crypton! or ZeroBot? :D
Doesn't matter, call me Mr. Sissy if you want :D
Yes, with UDP u may get a better latency, but you also may get good enough via TCP with TCP_NODELAY flag enabled. There are many good MMORPG's on TCP, such as Lineage 2, and more recently - WoW (yes, i heard it is on TCP now).
Thank you for suggestion. I have TCP_NODELAY flag already enabled. But I found out that it causes that TCP headers are sent much more often, which causes bandwidth wastage.

Its dilemma, because OpenArcanum's network protocol, packet header has only 4 bytes (already contains fields: Id, Type, Size, Flags), so with UDP, I will send 8 + 4 bytes, but if I send, for example, a same packet via TCP, I send 20 + 4 bytes, which is a lot of useless bytes (12 exactly). I also optimized that protocol to save every bit (compression, bit fields, etc), so those 12 bytes is a lot of wastage.

Now question is: Is that acceptable?

I think that if I save those 12 bytes per packet, server may handle more players even when running on slow connection. What do you think?
Dependency Inversion Principle says "Program to an abstraction, not an implementation". Ideally, you shouldn't depend on underlying protocol and be able to switch easy in any time. I'm not a C++ developer, but i believe there are frameworks, like Netty for Java, that helps you to not depend on concrete transport protocol.
Thank you. I coded all networking stuff by myself, so I'm not using any frameworks. There is almost no difference in implementation between TCP and UDP socket classes, so its easy to switch in some places, problem will be logics and algorithms at server class.

btw, I started to doubt about TCP after reading this article:
http://trac.bookofhook.com/bookofhook/t ... rogramming

Its pretty good article, it seems that author is expert in networking and knows what he's talking about. It also recommends to accumulate packets and send them in batch, so you won't send more TCP headers that it's needed. So something like TCP_NODELAY, but on application level.

evillive
Bunny
Bunny
Posts: 7
Joined: Mon Oct 04, 2010 12:21 am

Re: TCP vs UDP?

Post by evillive » Mon Oct 04, 2010 2:57 pm

ZeroBot wrote: Thank you for suggestion. I have TCP_NODELAY flag already enabled. But I found out that it causes that TCP headers are sent much more often, which causes bandwidth wastage.
This flag just causes TCP to send data as soon as possible when send() called. If u do like this: send("packet header"); send("packet body"); , this causes socket (with TCP_NODELAY flag) to send 2 separate packets, each with its own TCP header. But if u call send() only when u have whole packet (application level packet) ready, it will cause socket to send only one packet (TCP level packet) and there will be no wastage.
ZeroBot wrote: Its dilemma, because OpenArcanum's network protocol, packet header has only 4 bytes (already contains fields: Id, Type, Size, Flags), so with UDP, I will send 8 + 4 bytes, but if I send, for example, a same packet via TCP, I send 20 + 4 bytes, which is a lot of useless bytes (12 exactly). I also optimized that protocol to save every bit (compression, bit fields, etc), so those 12 bytes is a lot of wastage.

Now question is: Is that acceptable?
I think, yes. But i have doubts about your packet header, and here's why:
1) What is "Id"? In UDP Id can help you to determine lost packets and its order. But in TCP "Id" is useless.
2) Size - byte. You may need much more than 256 bytes in one packet. For example, when your character teleports in new location, it will be nice if u can send information about all the NPC's in some range in one big packet (1-4 KiB), rather than sending 20-30 separate packets for each NPC.
3) Flags. I dunno why it is here. Not every packet must have some specific flags. it's should be in packet body.

Lineage 2 (MMORPG, that uses TCP) have the following packet header:
|size 2 bytes|type 1 byte|
That's all!

And don't forget, that if u chose UDP u have to have some extra fields in header. They are Packet ID to handle packets order and lost packets, and UserID, to handle those rare cases with weired NAT's from IntroductionToMultiplayerGameProgramming article.

And then u realize, that TCP is not so "fat", but much more easily.
ZeroBot wrote:
I think that if I save those 12 bytes per packet, server may handle more players even when running on slow connection. What do you think?
I don't think those 12 bytes per packet are essential.
ZeroBot wrote:
problem will be logics and algorithms at server class.
This can be isolated too. If u want a can tell u how.
ZeroBot wrote: btw, I started to doubt about TCP after reading this article:
http://trac.bookofhook.com/bookofhook/t ... rogramming

Its pretty good article, it seems that author is expert in networking and knows what he's talking about. It also recommends to accumulate packets and send them in batch, so you won't send more TCP headers that it's needed. So something like TCP_NODELAY, but on application level.
Yes, good article. Author is good, and he wrote about his successful experience with UDP, but this doesn't mean TCP sucks ;)

One thing that was not mentioned in article is NAT traversal, which is possible with UDP and allows to host games even if host hasn't public IP adress. You can read about STUN in wikipedia.

User avatar
Crypton
Arronax's Best Friend
Arronax's Best Friend
Posts: 420
Joined: Wed Jul 08, 2009 5:04 am
Location: Abyss
Contact:

Re: TCP vs UDP?

Post by Crypton » Tue Oct 05, 2010 1:11 am

evillive wrote:This flag just causes TCP to send data as soon as possible when send() called. If u do like this: send("packet header"); send("packet body"); , this causes socket (with TCP_NODELAY flag) to send 2 separate packets, each with its own TCP header. But if u call send() only when u have whole packet (application level packet) ready, it will cause socket to send only one packet (TCP level packet) and there will be no wastage.
I'm sending whole packet at once already, with header, body and footer in one send call. But still those 12 bytes per packet seems to be a lot of wastage.

I think, yes. But i have doubts about your packet header, and here's why:
1) What is "Id"? In UDP Id can help you to determine lost packets and its order. But in TCP "Id" is useless.
2) Size - byte. You may need much more than 256 bytes in one packet. For example, when your character teleports in new location, it will be nice if u can send information about all the NPC's in some range in one big packet (1-4 KiB), rather than sending 20-30 separate packets for each NPC.
3) Flags. I dunno why it is here. Not every packet must have some specific flags. it's should be in packet body.

Lineage 2 (MMORPG, that uses TCP) have the following packet header:
|size 2 bytes|type 1 byte|
That's all!
My header is more advanced:

Code: Select all

struct ANetPacketHeader
{
     AInt32u marker   : 8;
     AInt32u size     : 18;
     AInt32u type     : 4;
     AInt32u flags    : 2;
};
Marker (id) identifies OpenArcanum's network protocol and says if packet is corrupted or not. Everything that has invalid marker is thrown away. Also by this marker I can determine endianness.

Size is obvious, up to 256KB of compressed data, but I'll probably decrease it to 8KB, which is maximum size for Arcanum's packet as well.

Type says what kind of data (if any) are contained in data that follow header.

Flags contains bit flags, if packet is compressed or not, and if its encrypted or not.
Still have some doubts about that header?:)

Footer is much easier, 2 bytes for crc16 + 2 byte marker.
And don't forget, that if u chose UDP u have to have some extra fields in header. They are Packet ID to handle packets order and lost packets, and UserID, to handle those rare cases with weired NAT's from IntroductionToMultiplayerGameProgramming article.

And then u realize, that TCP is not so "fat", but much more easily.
You are probably right. I should stick with TCP for now, and if it became bottleneck, I will switch (hopefully painlessly) to UDP.

Anyway, thank you again, for your help, effort and suggestions. ;)

evillive
Bunny
Bunny
Posts: 7
Joined: Mon Oct 04, 2010 12:21 am

Re: TCP vs UDP?

Post by evillive » Tue Oct 05, 2010 2:40 am

ZeroBot wrote: Still have some doubts about that header?:)
Yep, i have :)
Marker (id) identifies OpenArcanum's network protocol and says if packet is corrupted or not. Everything that has invalid marker is thrown away. Also by this marker I can determine endianness.
I think id is unnecessary in this case. How can be packet corrupted? Both UDP and TCP guarantee the correctness of transfered data. Endianness should be defined in protocol description. Also there is no point to identify OpenArcanum's network protocol packet in TCP, and with UDP u can throw away all packets with wrong UserID.
Type says what kind of data (if any) are contained in data that follow header.
You really need more than 16 packet types.
Flags contains bit flags, if packet is compressed or not, and if its encrypted or not.
You can get all this information from packet type.
Footer is much easier, 2 bytes for crc16 + 2 byte marker.
Footer is unnecessary too. You have packet size field to determine end of packet. And i can't understand what is crc for?

User avatar
Crypton
Arronax's Best Friend
Arronax's Best Friend
Posts: 420
Joined: Wed Jul 08, 2009 5:04 am
Location: Abyss
Contact:

Re: TCP vs UDP?

Post by Crypton » Wed Oct 06, 2010 12:39 am

Well, I agree that some stuff is unnecessary if I use TCP. That marker/id var was also used in Arcanum, to identify that packet is send by Arcanum. That's by I included it in OpenArcanum header as well.

About that flags var, I need at least one bit, to identify if packed was compressed or not. When you compress packet with deflate, zlib may increase size if data are not compressible, so I rather send them in raw form, to save some bytes. That encryption flag is probably useless, you are right.

That footer & crc, is because I'm being paranoid about correctness of transfered data, even TCP ensures this.

So I will update that protocol. Thanks again :)

evillive
Bunny
Bunny
Posts: 7
Joined: Mon Oct 04, 2010 12:21 am

Re: TCP vs UDP?

Post by evillive » Wed Oct 06, 2010 1:30 am

you are welcome! ;)
ZeroBot wrote:Well, I agree that some stuff is unnecessary if I use TCP. That marker/id var was also used in Arcanum, to identify that packet is send by Arcanum. That's by I included it in OpenArcanum header as well.
Maybe Arcanum developers thought about UDP too :D
ZeroBot wrote: About that flags var, I need at least one bit, to identify if packed was compressed or not. When you compress packet with deflate, zlib may increase size if data are not compressible, so I rather send them in raw form, to save some bytes. That encryption flag is probably useless, you are right.
I think u sould know wich packet type could be compressed in advance, that is why i sad, that u can get this information from packet type.
ZeroBot wrote: That footer & crc, is because I'm being paranoid about correctness of transfered data, even TCP ensures this.
In most IP stack implementations UPD datagram has crc16 calculated, so if u receive broken packet it will be dropped by system and u can't read it. So, upd packet can be lost, but if u can read it, it will be ok.

Cheers

Post Reply