UDP handshaking

Started by
6 comments, last by hplus0603 19 years, 1 month ago
I want the client and server to know "ok, now we're connected." I've read about the 3 way handshake TCP does, and I'd like to do something like that with UDP, but I don't really know how to handle those initial packets getting lost. Imagine something like this happens: Client: SYN Server: SYN/ACK Client: ACK (gets lost, never arrives at server) Now what? The client doesn't know it never arrived at the server. I suppose the server could just resend the SYN/ACK message after a while, or should the server send a GOODBYE message after a while and make the client start over? This is sort of related, but how do you gracefully disconnect so that the client and server both know the other is going away? Something this: Client: BYE Server: CYA Client: L8R Even if the server never gets the L8R message it can still disconnect after a second or so. The problem is if CYA gets lost. The server will disconnect without the client realizing it. Thoughts? Advise?
I like the DARK layout!
Advertisement
The client sends a connection request. It keeps sending these once in a while until some timeout is reached or it's acknowledged.
When the server recieves a request it replys with an acknowledgement. It too continues to send these until a fixed timeout or a non-connect message is received from the client.
After this the normal reliable messaging system kicks in and everything is guaranteed (as long as the network is working anyway). Just make sure that the client sends some initial data packet such as the login information.

Don't worry about the disconnect packages getting lost, the probability of this happening is pretty low to begin with (I've heard reports of 10% in extreme cases) . Besides a disconnect can never "fail", it'll just take some more time until the program decides to disconnect on it's own due to an inactivity timeout.
So there's really no gain in using a compilicated multi-stage system to handle them. Simply sending a single disconnect packet is enough in almost all cases.
If the server (for some odd reason) has to accept disconnects then you should handle it through the normal reliable transfer system instead, there's no reason to invent another semi-reliable system just to handle disconnects.

That's how we do it anyway.
How do I keep track of multiple people trying to connect at the same time from behind the same IP? How can I tell them apart? For example, there's ClientA and ClientB, both from behind 1.2.3.4. When I look at the sockaddr_in address that recvfrom() gives me, both of their packets say 1.2.3.4, right? Once the connection is made I can just make each client send a unique identifier in each packet, but what about before then?

ClientA: Hello!
ClientB: Hello!
Server: (thinks it got two connection requests from the same client)

If I were to send a reply to 1.2.3.4, which client would get it?
I like the DARK layout!
The problem really isn't solvable in general. You quickly go into endless loops of "I'm can't be sure that he knows that I know that he knows that I know, etc, etc".

In practice you usually just assume that if you haven't heard from the other side after a certain amount of time then they're gone and tear down the connection. If there's a chance that packets coming in after that point will screw you up then you need to add a session id to your data and/or otherwise re-authenticate the other side and basically build a "new" connection.

I wouldn't spend much time thinking about the disconnect case. It doesn't really matter whether or not it's rare - it's that you have to handle this case regardless. There's absolutely nothing you can do in your code to prevent the other side from tripping over the powercord or something. You have to be able to handle non-graceful disconnects. If a packet gets lost during the shutdown sequence than oh well.
-Mike
Multiple incoming connects from the same ip with have different ports. The other side is identified by the ip:port pair, not just the ip.
-Mike
One problem you might be having is that UDP is not connection oriented...there is no 'handshaking' involved. If you want a handshake, use TCP. Here's the first two links when looked up in [google]

http://www.skullbox.net/tcpudp.php

http://www-mae.engr.ucf.edu/~ambrose/tcpvsudp.html


Why are you using connectionless (UDP) when you really want connection oriented (TCP)? Why re-invent the wheel (unless that's what you're trying to do)?
Handshaking and connection-oriented handling are not the same thing - most UDP based systems have some kind of handshaking before initiating data transfer.

As far as handling multiple machines behind one IP, that's NAT for you. Try this link, or this handy guide written by someone vaguely familiar...

Richard "Superpig" Fine - saving pigs from untimely fates - Microsoft DirectX MVP 2006/2007/2008/2009
"Shaders are not meant to do everything. Of course you can try to use it for everything, but it's like playing football using cabbage." - MickeyMouse

Multiple clients behind the same IP will have different source ports, so you can still tell them apart.

Even multiple clients on the same machine will have different source ports, because two processes can't bind to the same port at the same time.

Losing a packet in the handshake process is handled by re-transmitting after a time-out. After a longer time-out, you give up and close the nascent connection; or if you get a RST or similar from the other end (which they should send you if you ACK something they're not interested in).
enum Bool { True, False, FileNotFound };

This topic is closed to new replies.

Advertisement