1

I want to send structures in a Windows socket. I use TCP protocol.

For example I have this structure :

typedef struct  headerLobby
{
    unsigned      nbGames;
}    head; 

I send my structure :

char buff[DEFAULT_BUFFER_LENGTH]; //DEFAULT_BUFFER_LENGTH = 512
headerLobby header;

header.nbGames = 1;
memcpy(buff, &header,  sizeof(headerLobby));
send(ClientSocket, buff, sizeof(headerLobby, 0);

I receive the data :

headerLobby header;

char recvbuf[DEFAULT_BUFFER_LENGTH];
memset(recvbuf, 0, DEFAULT_BUFFER_LENGTH);
int iResult = recv(ConnectSocket, recvbuf, DEFAULT_BUFFER_LENGTH, 0);

memcpy(&header,recvbuf,  sizeof(headerLobby));

But when I print header.nbrGames I haven't the good value.

The client and the server are both in windows 8 64bits and the processor intel x64. I don't understand what's wrong in my code.

Bob
  • 589
  • 1
  • 11
  • 25

4 Answers4

1

Can you dump the hex data you are trying to send and you are recving. Do a packet capture on the sending/recv side using wireshark/similar tools and see the packet data you are seeing on the wire is what you are expecting.

Few best practices,

  1. always keep your structure to an aligned size. Use padding at the end of struct if necessary. If you don't do that, the compiler will automatically keep the struct size aligned and it will result the data you are sending on the wire may not match what you are trying to send.

  2. Before sending anything on the wire, keep the data in network byte order. You can use htonl to convert. It might not be causing the problem here, because the arch is same and you are dealing with the data etc. But it might cause problem in portable code.

joe
  • 1,136
  • 9
  • 17
  • if you are going to site using htonl to address endian issues ,be sure to also mention the possibility of issues caused by differences in ***[atomic element size](http://en.wikipedia.org/wiki/Endianness)*** from one machine to the next. (see about 2/3 down the linked page) – ryyker Nov 09 '13 at 03:15
  • @joe - I see that htonl exist on unix and windows, so why it might cause problem in portable code ? – Bob Nov 09 '13 at 12:11
  • @Bob I was not saying htonl might cause problem. I was saying, if you don't do an htonl before sending the bytes, it might cause a problem. But in your case, the network order conversion might not be the one causing the problem as you say the source and destination uses same arch, same OS etc. Sorry for the confusion. btw, did you get it working? – joe Nov 09 '13 at 20:45
0
  (...)
  header.nbGames = 1;
  memcpy(buff, &header, sizeof(struct headerLobby));
  send(ClientSocket, buff, sizeof(struct headerLobby), 0);

  memset(recvbuf, 0, 20);
  int iResult = recv(ConnectSocket, recvbuf, 20, 0);
  memcpy(&recvheader, recvbuf, sizeof(struct headerLobby));

  printf("%d\n", recvheader.nbGames);
  (...)

$ ./out

1

So, it works. Your code is correct. Or you obviously edited it to paste it here, removing the problematic part. Hint: always create a minimal test case which proves or disproves the problem you have.

hdante
  • 7,685
  • 3
  • 31
  • 36
  • It's exactly that. My problem wasn't the memcpy to the first structure but when I had another. When I sent two structures, I sent the pointeur to the second structure instead of the first.. – Bob Nov 09 '13 at 12:15
0

I found my error. The example code works but my error was that I wanted to send several structures. When I sent structures I didn't send the pointeur to the first structure.

For example :

char buff[DEFAULT_BUFFER_LENGTH]; //DEFAULT_BUFFER_LENGTH = 512
headerLobby header;
GameInfo info; //other struct

header.nbGames = 1;
info.nbPlayers = 3;
memcpy(buff, &header,  sizeof(headerLobby));
buf += sizeof(headerLobby);
memcpy(buf, &info, sizeof(gameInfo));
send(ClientSocket, buff, sizeof(headerLobby, 0); //I lost the pointeur to the first struct
Bob
  • 589
  • 1
  • 11
  • 25
-1

Although it can be done safely, sending struct data by sockets (or using any binary method for that matter) is risky for several reasons.

sizes of intrinsic types may be different from machine to machine.
padding on sending machine may be different on the receiving machine.
endian rules on sending machine may be different than on receiving machine.

generally not a good idea from the start to send struct data this way, with a caveat:

If you serialize your data into a buffer first ( credit to this post ) these issues are addressed.

Community
  • 1
  • 1
ryyker
  • 22,849
  • 3
  • 43
  • 87