Advertisement

reliable UDP protocol

Started by March 18, 2006 03:46 AM
13 comments, last by Nit 18 years, 11 months ago
i've got a game which uses TCP but i cant do nat punch trough with TCP, so this means i need to use UDP for my game. So, i've started writing a reliable UDP protocol. It seems to work okay. I send a packet, and store its ID. I keep sending this packet each update till i get an ACK message from the other end. So the other end receives a packet, stores the ID and keeps sending ACK messages till it stops receiving the message using the ID from the other side (this uses a timeout). This all works fine and dandy. I want to set up a connection and disconnection part to the protocol though, so what i do: The client sends a connect message to the server, when the server gets this its also sends a connect message back. Then once both ends get each other's connect message, they both send a connect ack message. The problem then begins here, when one end gets the connect ack message, it stops sending all packets to make way for user packets. This then screws up as the other end may have not received the connect ack yet. So one end thinks its connected, the other doesnt know. So what i do is wait for a timeout before clearing the packets. This now leads to the situation where it may take a few seconds to connect due to wating for timeouts etc.. Is it best to open a seperate thread while a connection is being made? and the same when a connection is being closed? This hides the connection/disconnection part of the protocol from the user. Or is there a better way to implement the protocol?
Would using a ready-built library like RakNet or eNet maybe solve your problem in a satisfactory way?
Implementing it yourself would really help understanding, using a library would save you time.
Advertisement
cool, time is vital for my current project. Not for my next one though. Thx for the link
> So one end thinks its connected, the other doesnt know.

Maybe you haven't setup your state machine right. Look for "RFC908" on the web. It's a reliable protocol proposition that is relatively simple and the state machine is well-documented. Can give you some ideas / hints as to how to setup and debug your states.

Here is another reliable UDP implementation. Pretty simple and tight-coded:

http://airhook.ofb.net ( Clicky )

-cb
hrmm im wondering, when you accept a TCP connection, does the connection process negotiate another port to talk over, leaving the port only for listening?
Yes, accepting returns a new socket descriptor under TCP. This is still the same port as the original listener socket though. TCP sockets bridge the connection gap (a connected protocol). UDP doesn't - if you fire UDP traffic at a certain port, it's up to you to sort it out.

This is a pain in the ass if you're allowing a flexible-protocol system, meaning you need a socket pool interface even for UDP, and a means of client identification (usually from remote address) for TCP.
Winterdyne Solutions Ltd is recruiting - this thread for details!
Advertisement
Instead of continuously sending the message from the sending end, and continuously sending ACKs for that message on the receiving end, a better solution is to just send the message once from the sending end, and on the receiving end send a NAK to request retransmission of any missing messages. For example, if you receive message #1, and then #4, you'd start spitting out NAK's for messages 2 and 3 until you get them. And the sending end would just send the message again whenever it receives a NAK
Quote:
when you accept a TCP connection, does the connection process negotiate another port to talk over


No. TCP stays on the same port. It returns a new socket, that's specific to the connection in question, but it stays at the same port on the server.

What's special about TCP, though, is that it identifies a session as the tuple (local IP, local port, remote IP, remote port). The client will start the connection on a unique port; if the socket is not bound before calling connect(), connect() will allocate and bind an unused port on the client before talking to the server.

You can do the same thing on UDP: treat each tuple of (local IP, local port, remote IP, remote port) as a connection, and route it to a specific connection handler, using recvfrom(). No socket pools needed for that specific reason.
enum Bool { True, False, FileNotFound };
Quote:
Original post by RDragon1
Instead of continuously sending the message from the sending end, and continuously sending ACKs for that message on the receiving end, a better solution is to just send the message once from the sending end, and on the receiving end send a NAK to request retransmission of any missing messages. For example, if you receive message #1, and then #4, you'd start spitting out NAK's for messages 2 and 3 until you get them. And the sending end would just send the message again whenever it receives a NAK


If you do this you might want to periodically send an ACK to just to give the sending side some information so it can clean up its resend queue.

-=[ Megahertz ]=-
-=[Megahertz]=-
I'm looking at the state diagram here:
http://www.faqs.org/rfcs/rfc908.html
around 1/4 the way down

trying to work out how the initial connection part works.

i've got the server in the listen state, and a client in the SYN-SENT state.
so my client is spamming the server with a SYNC packet.

The server receives this, and goes in to the SYN-RCVD and starts spamming a SYN,ACK message.

Now this is where i get lost in this diagram. so sync-sent goes to open state on receiving of the SYN,ACK from the server, OR it goes to SYN-RCVD if it receives a SYN (why would this last bit happen? NAT punch through maybe?)

so does SYN-RCVD simply go to OPEN after a timeout?
also what if the client is in the open state while the server is sync-send, and the client sends packets to the server? i guess it could just go in to the open state after a timeout or receiving of a packet if the packet is not a SYN packet?

does this sound correct?
also what if the server goes in to open, and the client hasnt received the SYN,ACK to put it in the open state? we'd end up with a half open connection...

This topic is closed to new replies.

Advertisement