2
votes

First of all I'd like to apologise for my bad English :) Yesterday I finished writing my first multiplayer game (Pong) in C++ using Winsock and Allegro5. The game consists of one server for all players and clients.

Every frame (FPS = 60) clients send their mouse_y coordinates to the server which passes them to their opponents' clients respectively. When I play the game on my 2 computers connecting to the server, which runs on one of them, by local network it works perfectly, opponent's paddle is moving smoothly. But when I do the same connecting through my external IP address the opponent's paddle is lagging, which ruins the game, because it's client which checks if the ball hit opponent's paddle or not. Thus synchronisation is ruined, whenever I move one paddle to bounce the ball on the other computer it lags and doesn't make it in time resulting in scoring a point for opponent... But it's not the game which is lagging. My paddle and the ball are moving smoothly. The problem is only with opponent's paddle.

I'm new to network programming as I've only read Beej's Guide to Network Programming. I use TCP sockets to send() and recv() coordinates of paddles and select() function to poll sockets for data.

I don't have a single idea what could be the cause.

TL;DR: Opponent's paddle lags when I connect through external IP, but it doesn't when I connect through local IP.

2

2 Answers

2
votes

To extend what thomas said. I'm gonna give you a bit more practical answer.

  • Use UDP for games.


If you insist on using TCP then do these.

  • Lower the value of TCPAckFrequency.

  • Disable nagle's algorithm because your requests will be small in size. Do that by setting TCPNoDelay to 1.

  • Ease the movement between two points.

  • Send less data while packing the rest.

  • Cast the received packets into structs.

  • Do not use select. After 50 or so connections you will notice huge performance loss. Use epoll or IOCP for Windows/Linux respectively.

2
votes

Well, that's perfectly expected behaviour, imposed (among others) by the speed of light. Packets sent across the internet just take a while to arrive:

$ ping stackoverflow.com
PING stackoverflow.com (198.252.206.16) 56(84) bytes of data.
64 bytes from stackoverflow.com (198.252.206.16): icmp_req=1 ttl=53 time=85.1 ms

That tells me the RTT (round trip time) from my machine to stackoverflow.com is 85 milliseconds, which is fine for a website, but is enough to result in noticeable lag in a real-time game.

That's the bad news. The worse news is that this is a very hard problem to solve.

Professional real-time multiplayer games use several tricks to make the lag less noticeable. For instance, they keep track of the latency for every client, and try to "predict" where the player will be at the current point in time, even if those packets haven't arrived yet. But of course, if the packets arrive and the prediction turns out to be wrong, this would result in the player suddenly "jumping" to the right place. To work around that, they apply some smoothing between the predicted and last known location. If it's done well, this gives the illusion of real-time movement.

The other problem is that you cannot do your game logic solely on the client, because every client has a slightly different view of the world. It's OK to have the client do predictions, but the server should have the final say in whether the paddle hit the ball.