Client to server works. Why not otherway around?

Started by
8 comments, last by Kylotan 14 years, 12 months ago
Trying to get basic TCP communication working with SDL_Net. I can send messages from client to server great. It seems I also am able to send messages from server to client(atleast server doesn't print out any error messages) yet nothing comes to client side. Where did the message go? Do I need to create some new socket when client connects for writing? Could have swore you could use same socket for reading and writing but if I have misunderstood that one it certainly would explain it. Bit of my code:

int player::sendMessageNow() {
  int numsent;
  if(strcmp(nextMessage, "")!=0) {
    printf("Sent: %s\n", nextMessage);
    strcat(nextMessage, "\n");
    numsent=SDLNet_TCP_Send(mySocket, nextMessage, strlen(nextMessage)+1);
    if(numsent<strlen(nextMessage)+1) {
      printf("SDLNet_TCP_Send: %s\n", SDLNet_GetError());
    }
    clearMessage();

    return numsent;
  }
  
}


Code from server side that sends the message. mySocket is working allright(receiving isn't problem. Sending is).

int client::openConnection(char *server, int serverPort) {
  
  if(SDLNet_ResolveHost(&serverAddress, server, serverPort) !=0) {
    printf("Address resolving failed!");
    exit(1);
  }

  mySocket=SDLNet_TCP_Open(&serverAddress);

  if(!mySocket) {
    printf("SDLNet_TCP_Open: %s\n", SDLNet_GetError());
    exit(2);
  }
  mySet = SDLNet_AllocSocketSet(1);
  SDLNet_TCP_AddSocket(mySet, mySocket);
}


client side. Opens up connection to server and creates set used for checking wether there's activity in the network.

int client::receiveData() {
  int result;
  int bytesRcvd = 0;
  strcpy(readBuffer, "");
  if(SDLNet_CheckSockets(mySet, 0)>0) {
    printf("Activity in set!\n");
    if(SDLNet_SocketReady(mySocket)!=0) {  
      printf("Activity in mySocket!\n");
      do {   
	result=SDLNet_TCP_Recv(mySocket, readBuffer+bytesRcvd, 1);
	readBuffer[bytesRcvd+1]='\0';
	printf("%s\n", readBuffer);
	if(result==0) {
	  SDLNet_TCP_DelSocket(mySet,mySocket);
	  SDLNet_TCP_Close(mySocket);
	  return 0;
	}
	bytesRcvd+=result;
      } while(!strchr(readBuffer, '\n') && bytesRcvd<MAX_PACKET_SIZE);

    }  
    return result;
  }
  return -1;
}


And the client read message. Never gets past first if clause so there's not even any activity in the socket set. What's up with that? Edit: Oops! Seems client received data just fine. Too bad it only checked after X ticks and after that didn't bother to read data...Had > instead of < on if clause limiting number of receiveData calls(as unlimited it became CPU hog making graphic drawing and keyboard typing very, very, very laggy). [Edited by - tneva82 on April 20, 2009 6:58:56 AM]
Advertisement
Is your problem solved then? Or do you have further questions?
Quote:Original post by Kylotan
Is your problem solved then? Or do you have further questions?


Yeah this one is solved. Now further issue is that after receiving message it freezes(as if it would enter infinite loop). Seems to happen when trying to read network for next time. Not sure what's up with that though I have few ideas where to look.

BTW could that be result of memory issues? I'm used for that causing segfaults but could it cause freezing of program instead?

Edit: Is it possible that the

result=SDLNet_TCP_Recv(mySocket, readBuffer+bytesRcvd, 1);


line would enter into blocking mode despite having passed:

  if(SDLNet_CheckSockets(mySet, 0)>0) {    printf("Activity in set!\n");    if(SDLNet_SocketReady(mySocket)!=0) {


Ie it would wait there 'till there's activity rather than existing the while loop?

Edit: Guess it was. I changed read method to:

int player::readNetwork() {  int result=0;  int bytesRcvd = 0;  if(readBuffer==NULL) {    readBuffer=new char[MAX_PACKET_SIZE+1];  }  strcpy(readBuffer, "");  do {    if(SDLNet_CheckSockets(mySet, 0)>0) {      if(SDLNet_SocketReady(mySocket)!=0) {  		result=SDLNet_TCP_Recv(mySocket, readBuffer+bytesRcvd, 1);	readBuffer[bytesRcvd+1]='\0';	if(result==0) {	  SDLNet_TCP_DelSocket(mySet,mySocket);	  SDLNet_TCP_Close(mySocket);	  return -1;	}	bytesRcvd+=result;      }     }  else {      return 0;    }  } while(!strchr(readBuffer, '\n') && bytesRcvd<MAX_PACKET_SIZE);  return result;}


And it works. If somebody could confirm wether I figured reason correctly and I didn't just hide mistake badly I would appreciate it though. Just to be safe side that I have it working now. Networking has caused tons of headaches(especially before I added: readBuffer[bytesRcvd+1]='\0'; Before that line I got tons of extra trash causing rather...Random...workings when sending very long messages).

Edit: And I'll cheer here since I have to cheer somewhere :D Program is starting to approach the point where server and client finally discuss and I have something visible out of it :D Over 9k lines it has taken(mostly to get basic stuff needed done. GUI, graphic engine, network engine etc) but finally groundwork is starting to be done(well atleast done well enough) and I can start adding stuff that is visible!

Edit: Further thought on the error I think what happened was that after string containing first commands there still was '\0' character left. It therefore noticed activity, went to pick and then without further activity went to blockind mode. Whoops! Makes sense. '\0' is last character in char arrays but I read strings to '\n'. Therefore after I encounter '\n' and go out of read loop the '\0' is left unread and causes it to go wait for further activity.

Again if somebody sees error in this logic please do tell.

[Edited by - tneva82 on April 20, 2009 1:19:22 PM]
Urgh. Now ran into new problem. I'm communicating nicely along and then suddenly client stops receiving messages. Any ideas where I could be going wrong? I try to print out messages and get nothing as if there would be no messages. When printing out readBuffer during receiveData() loop I get lots of activity but readBuffer remains empty string. Huh? Server sends out data without issues(right message is coming) but client side doesn't seem to receive one bit of it. Keeps claiming 0 bits read from the socket after message has been sent from server. Very strange.

Anybody has guess where my code is failing? Seems it's not done afterall :(
Quote:Any ideas where I could be going wrong?


Yes: you have a bug in your system.

I would suggest setting up little test harnesses for each component of the system, and feeding it known data, making sure it responds appropriately to each piece of data you feed it. For example, you can wrap the socket in a small class (that has just send() and recv() functions), which allows you to provide a dummy socket that copies from some buffer you decide instead of really sending/receiving, and use that to test the upper layer of your code.

enum Bool { True, False, FileNotFound };
Quote:Original post by hplus0603
Yes: you have a bug in your system.


Thanks. I would never have figured THAT one out on my own ;-) Afterall all I have in my hands is code that doesn't work...

Bug found. Mistake was using newline to separate packet from another. What I SHOULD have done is use the '\0' character to say "this was whole message". Those stray '\0' which were left unread caused strings to end up looking like empty string.

Cutting \n from messages and making sure reading stops at \0 char fixed the issue. Onward on project.
It's usually best not to use delimiters for your packets and instead to prefix them with the size so you know how many bytes to expect. As you've been finding, the problem with using certain bytes as packet delimiters is that those same delimiters get used for other things (eg. end of line, end of string), and you often need to 'escape' them when they show up in legitimate data. There's nothing intrinsically wrong with using \n or \0 as long as you handle them properly - it's just easier to get wrong. Prefixing a message with the message size is simpler.
Quote:Original post by Kylotan
It's usually best not to use delimiters for your packets and instead to prefix them with the size so you know how many bytes to expect. As you've been finding, the problem with using certain bytes as packet delimiters is that those same delimiters get used for other things (eg. end of line, end of string), and you often need to 'escape' them when they show up in legitimate data. There's nothing intrinsically wrong with using \n or \0 as long as you handle them properly - it's just easier to get wrong. Prefixing a message with the message size is simpler.


Hum. So how would one send size of char array to end?

And out of curiosity what other purpose \0 would have? I can't figure why it would appear more than once in the string(at the end) so it as delimiter should be just fine. Afterall all I'm sending is plain old text with \0 at the end which comes automaticly.

Can't figure any other legimitate use for that one. Separating different commands? Nope. Not that one. I use other character for that one and use strtok to cut thing apart.

Edit: Wohoo! It works! Things are now wrapped up nicely and I can finally move around in 3d world with server providing movement data via network connection to client. Huzah! Next big thing: Determining height from polygons character stands on. Time to start reading stuff about collision detection...

[Edited by - tneva82 on April 22, 2009 1:17:24 PM]
Quote:Original post by tneva82
Hum. So how would one send size of char array to end?

Write the size, as an integer. Then write each element. Which part is the difficult part?

Quote:And out of curiosity what other purpose \0 would have?

There will probably come a point where you want to send binary information rather than encoding everything as plain text. Better to learn a useful method that works everywhere rather than a method that only works for a certain kind of data which has already posed you one problem so far.

This topic is closed to new replies.

Advertisement