1
\$\begingroup\$

I am programming a fighting game that uses a UDP client/server architecture for multiplayer. The server can handle multiple clients, two of which (or one being the server) are playing and the rest are watching and chatting. I would prefer to use UDP for everything, including: player input from client, player state from server, and chat going both ways.

My concern is keeping the order of the player inputs in sync from the client to the server. Since moves involve a specific sequence of inputs (e.g., Left,Left-down,Down,Light Punch), if the server processes them out of order then the game is ruined. What is a good approach for dealing with packet loss and packets arriving out of order in this case?

I have considered having a linked list of outgoing packets in the client and server. With each step the list is traversed and unsent packets are sent, and if an ack packet(one I program the receiver to send back) was received for a particular packet (which I can identify simply with an integral value) then the outgoing packet is removed from the list. However, this does not guarantee order of delivery. Perhaps the server could keep a queue of inputs and evaluate another integral value in the packet for each input, organizing them into the correct order.

I'm not entirely sure, if someone could point me in the right direction I would be very grateful. I have working client and server chat code but before I starting seriously designing the network architecture I wanted to see what others have to say.

\$\endgroup\$
4
\$\begingroup\$

One reason you might prefer UDP over TCP is to save bandwidth. The drawbacks are obvious: if data gets lost on the way neither the sender nor the recipient will notice. In addition, the order of packages may change if they take different routes in the network, which would result in clients seeing wrong "combos" (e.g. Left-Down-Punch instead of Down-Left-Punch). In certain cases a client might also receive a single package multiple times (Down-Down-Left-Punch).

In scenarios where these drawbacks are acceptable and large amounts of data are sent, (e.g. video/audio streaming) UDP is a valid choice. Here errors in the data transfer will only cause minor and short-lived artifacts in your media stream. It seems to me, however, that in your case a connectionless protocol like UDP ist not reasonable. What you are trying to do is deliberately not use the automated control mechanisms TCP brings along and then reimplement them yourself because you actually need them. Therefore I wonder what you are trying to achieve. Why not stick with TCP that takes care of everything: Monitored data transfer that ensures your data packets are delivered in the right order, with automatic resend requests in the event of data loss.

\$\endgroup\$
  • \$\begingroup\$ +1, also note that even some of the biggest MMOes use TCP! \$\endgroup\$ – wondra Aug 1 '14 at 7:07
  • \$\begingroup\$ Thanks for your suggestion. I do realize the advantages of TCP, however I have seen in one too many places a programmer emphasizing not to use TCP for a game, for example gamasutra.com/view/feature/131781/… It wouldn't be hard to switch to TCP at this point, but I'm not comfortable doing it for a fighting game which needs very high-speed updates. I think it's possible to do this with UDP (using something like Raknet would make it much easier). \$\endgroup\$ – Blue Wizard Aug 1 '14 at 8:21
  • 1
    \$\begingroup\$ If you want to go this route maybe check out this tutorial: gafferongames.com/networking-for-game-programmers/udp-vs-tcp - it also contains a section "Reliability and Flow Control" \$\endgroup\$ – xoric Aug 1 '14 at 8:47
  • \$\begingroup\$ @unixunited As long as you don't need the performance and speed improvement of UDP and that TCP works fine, stick with it. TCP isn't great at handling a lot of packets, but a fighting game is not a lot, so TCP should be just fine. \$\endgroup\$ – Alexandre Desbiens Aug 1 '14 at 11:56
  • \$\begingroup\$ I'm not sure how familiar you guys are with the fighting game community, but even a standard amount of latency is completely unacceptable. TCP may work for one on one matches, but for updating the other clients viewing the match it would probably require UDP. I may end up just testing with both. \$\endgroup\$ – Blue Wizard Aug 2 '14 at 2:57
1
\$\begingroup\$

If I understand what you're trying to achieve, you want your two active clients to send key strokes to your server, and you want your server to process them in the right order.

If you have to encode a key code and possibly some timestamp to know exactly when the touch was pressed (timing may be important for combos), I guess it should fit in 4 bytes/key (4 bits for key number + 28 bits for whatever timestamp you're using).

Since a UDP trame can safely contains 512 bytes of payload (according to https://stackoverflow.com/questions/1098897/what-is-the-largest-safe-udp-packet-size-on-the-internet), it won't have any impact on your communication speed if you send 1 byte or 512 at a time.

So, the solution I would try to implement is:

On the client:

  • Implement your own packet number; No need to be fancy here: just use a 4 bytes unsigned integer that you increment for each packet sent
  • When you send a new keystroke, what you actually send is: The packet number, [4 bytes], the keycode/timestamp you want to send [4 bytes] and the 126 previous keycode/timestamps [4*126 bytes].

On the server:

Whenever a packet is received:

  • If its packet number is lower than the last processed packet number for the same client, you drop it
  • If its packet number is greater than the last processed packet number for the same client, you process as many keycode/timestamps as needed (i.e., if you're receiving packet 8 and previous processed packet was 6, you process the two more recent key/time information; if the packet 7 arrives later, you drop it since its payload has already been processed).

As long as you don't lost 127 packets in a row, it should work; using timestamps should help you to conserve the continuity. (also, you may be able to use less than 4 bytes for each keycode/timestamp pair, and so have more redundancy).

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.