Problem with SDL net

Started by
2 comments, last by hplus0603 13 years, 3 months ago
Hello!

I tried to make a server for my backgammon, but I ran into some difficulties and need some help.

Here is the code for the server, which is not working as it should...

[source]


while (!quit3)
{/* ----------------------------------- FIRST MOVE ----------------------------------------*/
while(true)
if(SDLNet_TCP_Recv(peerOne.socket, buffer, 512) > 0)
if(buffer[0] == 's')
{
Move move;
move.RecvMove(peerOne.socket);
printf("\nRECIEVED DATA :");
move.DisplayData();
peerOne.MoveList.push_back(move);
}
else if(buffer[0]=='e')
break;
for(vector<Move>::iterator itermove = peerOne.MoveList.begin();itermove!=peerOne.MoveList.end();itermove++)
{
itermove->SendMove(iter->socket);
printf("\nSENT DATA :");
itermove->DisplayData();
}
buffer[0] = 'e';
len = strlen(buffer)+1;
if (SDLNet_TCP_Send(iter->socket, (void*) buffer, len) < len) {
fprintf(stderr, "SDLNet_TCP_Send: %s\n", SDLNet_GetError());
}
SDL_Delay(100);/* ----------------------------------- SECOND MOVE ----------------------------------------*/
while(true)
if(SDLNet_TCP_Recv(iter->socket, buffer, 512) > 0)
{
printf("%c",*buffer);
Move move;
move.RecvMove(iter->socket);
printf("\nRECIEVED DATA :");
move.DisplayData();
iter->MoveList.push_back(move);
}
else if(buffer[0]=='e')
break;
for(vector<Move>::iterator itermove = iter->MoveList.begin();itermove!=iter->MoveList.end();itermove++)
{
itermove->SendMove(peerOne.socket);
printf("\nSENT DATA :");
itermove->DisplayData();
}
buffer[0] = 'e';
len = strlen(buffer)+1;
if (SDLNet_TCP_Send(peerOne.socket, (void*) buffer, len) < len) {
fprintf(stderr, "SDLNet_TCP_Send: %s\n", SDLNet_GetError());
}


vector<Move>::iterator iterMove = peerOne.MoveList.begin();
while(iterMove!=peerOne.MoveList.end())
peerOne.MoveList.pop_back();

iterMove = iter->MoveList.begin();
while(iterMove!=iter->MoveList.end())
iter->MoveList.erase(iterMove);
}

[/source]

where iter is the second player and peerOne is the first...

and the client side:

This code is executed after making your move.

[source]


char buffer[512];
int len;
SDL_Delay (1000);
for(vector<Move>::iterator iter = MoveList.begin();iter!= MoveList.end();iter++)
iter->SendMove(server);
SDL_Delay(50);
*buffer = 0;
buffer[0] = 'e';
printf("%c",buffer[0]);
len = strlen(buffer)+1;
if (SDLNet_TCP_Send(server, (void*) buffer, len) < len) {
fprintf(stderr, "SDLNet_TCP_Send: %s\n", SDLNet_GetError());
}
vector<Move>::iterator iter = MoveList.begin();
while(iter!= MoveList.end())
MoveList.pop_back();

[/source]

where Move is defined as follows:

[source]


struct Move
{
int DiceX,DiceY,OldX,OldY;

Move(){
DiceX=DiceY=OldX=OldY=-100;
};

void RecvMove(TCPsocket recv)
{
while(DiceX == -100 || DiceY == -100 || OldX == -100 || OldY == -100)
{
char buffer[512];
if (SDLNet_TCP_Recv(recv, buffer, 512) > 0) {
if(buffer[0] == 'q')
while(true)
{
if (SDLNet_TCP_Recv(recv, buffer, 512) > 0)
{
DiceX = (int)*buffer;
break;
}
}
if(buffer[0] == 'w')
while(true)
{
if (SDLNet_TCP_Recv(recv, buffer, 512) > 0)
{
DiceY = (int)*buffer;
break;
}
}

if(buffer[0] == 't')
while(true)
{
if (SDLNet_TCP_Recv(recv, buffer, 512) > 0)
{
OldX = (int)*buffer;
break;
}
}

if(buffer[0] == 'r')
while(true)
{
if (SDLNet_TCP_Recv(recv, buffer, 512) > 0)
{
OldY = (int)*buffer;
break;
}
}
}
}
};

bool SendMove(TCPsocket server)
{
char buffer[512];
int len;
buffer[0] = 's';
len = strlen(buffer)+1;
if (SDLNet_TCP_Send(server, (void*) buffer, len) < len) {
fprintf(stderr, "SDLNet_TCP_Send: %s\n", SDLNet_GetError());
}
SDL_Delay(50);
buffer[0] = 'q';
len = strlen(buffer)+1;
if (SDLNet_TCP_Send(server, (void*) buffer, len) < len) {
fprintf(stderr, "SDLNet_TCP_Send: %s\n", SDLNet_GetError());
}

SDL_Delay(50);
*buffer =(char) DiceX;
len = strlen(buffer)+1;
if (SDLNet_TCP_Send(server, (void*) buffer, len) < len) {
fprintf(stderr, "SDLNet_TCP_Send: %s\n", SDLNet_GetError());
}

SDL_Delay(50);
buffer[0] = 'w';
len = strlen(buffer)+1;
if (SDLNet_TCP_Send(server, (void*) buffer, len) < len) {
fprintf(stderr, "SDLNet_TCP_Send: %s\n", SDLNet_GetError());
}


SDL_Delay(50);
*buffer =(char) DiceY;
len = strlen(buffer)+1;
if (SDLNet_TCP_Send(server, (void*) buffer, len) < len) {
fprintf(stderr, "SDLNet_TCP_Send: %s\n", SDLNet_GetError());
}

SDL_Delay(50);
buffer[0] = 't';
len = strlen(buffer)+1;
if (SDLNet_TCP_Send(server, (void*) buffer, len) < len) {
fprintf(stderr, "SDLNet_TCP_Send: %s\n", SDLNet_GetError());
}

SDL_Delay(50);
*buffer = (char) OldX;
len = strlen(buffer)+1;
if (SDLNet_TCP_Send(server, (void*) buffer, len) < len) {
fprintf(stderr, "SDLNet_TCP_Send: %s\n", SDLNet_GetError());
}

SDL_Delay(50);
buffer[0] = 'r';
len = strlen(buffer)+1;
if (SDLNet_TCP_Send(server, (void*) buffer, len) < len) {
fprintf(stderr, "SDLNet_TCP_Send: %s\n", SDLNet_GetError());
}

SDL_Delay(50);
*buffer =(char) OldY;
len = strlen(buffer)+1;
if (SDLNet_TCP_Send(server, (void*) buffer, len) < len) {
fprintf(stderr, "SDLNet_TCP_Send: %s\n", SDLNet_GetError());
}

return 1;
};

void DisplayData(){
printf("\nDiceX %i DiceY %i OldX %i OldY %i\n",DiceX,DiceY,OldX,OldY);
};
};

[/source]




The problem is that the first move is OK the client made the move sends the data, the server recieves it and sends it to the other player. So far so good. When I make the second move the data is sent from client two, but it doesn't arrive at the server... The code for the second move is identical with the first, but the reciever and sender and switched. AND THE CODE DOESN'T work......... Please help me because I'm banging my head in the wall and I can't find a way to fix it.
Advertisement
You have several problems in this code.

First, each packet you send has to be preceded by a length. When you receive on the other end, you have to first make sure that you have enough data to decode the length, and then that you have enough data that the length describes. This is because TCP is a stream, much like a file -- send() and recv() calls may very well transmit only parts of what you request of it.

Second, this also means that you should have an outgoing data queue, and send as much as you can out of that each frame, keeping the rest buffered for later. When you want to send more data, put that data at the end of the queue.

Third, the main loop has to be a state machine that continually polls the network and user input, and then generates events based on what happens -- a full packet was decoded, or the player entered some input, or whatever.

Fourth, you are assuming that the other end will send zero-terminated strings. If someone were to connect to your game and send a very large string of random non-0 bytes, your could would crash or, worse, potentially allow a remote exploit of the machine.

If you want to teach yourself low-level network programming, then this is a fine path you've started on -- just realize that you have a long way to go!
If you want to make a networked game, I *highly* recommend that you use a higher-level library, like RakNet, Replica.net or similar.
enum Bool { True, False, FileNotFound };
First, thank you for your reply! Really I appreciate it!

Second, it's just a project of mine so that I can learn to program network games. My pathetic parody of a game is just for experience.

Last, does someone know a good general games programming (maybe even networking) tutorial/book/whatever?

You have several problems in this code.

First, each packet you send has to be preceded by a length. When you receive on the other end, you have to first make sure that you have enough data to decode the length, and then that you have enough data that the length describes. This is because TCP is a stream, much like a file -- send() and recv() calls may very well transmit only parts of what you request of it.

Second, this also means that you should have an outgoing data queue, and send as much as you can out of that each frame, keeping the rest buffered for later. When you want to send more data, put that data at the end of the queue.

Third, the main loop has to be a state machine that continually polls the network and user input, and then generates events based on what happens -- a full packet was decoded, or the player entered some input, or whatever.

Fourth, you are assuming that the other end will send zero-terminated strings. If someone were to connect to your game and send a very large string of random non-0 bytes, your could would crash or, worse, potentially allow a remote exploit of the machine.

If you want to teach yourself low-level network programming, then this is a fine path you've started on -- just realize that you have a long way to go!
If you want to make a networked game, I *highly* recommend that you use a higher-level library, like RakNet, Replica.net or similar.

Last, does someone know a good general games programming (maybe even networking) tutorial/book/whatever?


Did you read the [FAQ]? It's probably useful to go back now and again, because as you learn some things, other things in the FAQ may start making more sense!
enum Bool { True, False, FileNotFound };

This topic is closed to new replies.

Advertisement