简体   繁体   中英

Passing structure over TCP socket in C

I'm writing a small client server application in C.

At the client side i have one structure like,

#pragma pack(1)   // this helps to avoid serialization while sending over network. 
typedef struct _viewBoxClient_Info
{
  unsigned long viewBoxID;
  int bRT_flag;
  int nFrameNum;
  char frameData[1000];   
}viewBoxClient_info_send ;
#pragma pack(0)   // turn packing off 

and filling the variable as,

struct _viewBoxClient_Info client_info;
client_info.bRT_flag= 10;/*0 for false, 1 for true*/
client_info.viewBoxID=10000;
memcpy(client_info.frameData,buf,sizeof(client_info.frameData)); //char buf[] data is "is 1st line"
client_info.nFrameNum=1;

and sending to server by using the following function,

send(sock, (char *)&client_info, bytesRead, 0);

At the server side,i have one structure like (same as client side structure),

#pragma pack(1)   // this helps to avoid serialization while sending over network.
typedef struct _lclviewBoxClient_Info
{
 unsigned long viewBoxID;
 int bRT_flag;
 int nFrameNum;
 char frameData[1000];
}viewBoxClient_info_receive ;
#pragma pack(0)   // turn packing off

and receiving the message and printing on screen as,

viewBoxClient_info_receive lcl_viewBox;
ssize_t bytesReceived = recv( *nfd, &lcl_viewBox, sizeof(struct _lclviewBoxClient_Info), 0);
printf("\nlcl_viewBox.bRT_flag:%d\n",lcl_viewBox.bRT_flag);
printf("lcl_viewBox.nFrameNum:%d\n",lcl_viewBox.nFrameNum);
printf("lcl_viewBox.frameData:%s\n",lcl_viewBox.frameData);

O/p at server screen,

 lcl_viewBox.bRT_flag:1
 lcl_viewBox.nFrameNum:1936287860
 lcl_viewBox.frameData: is 1st line

I do not know what exactly its happening at my server side. I'm sending 10 for bRT_flag from client and receiving 1 at server. Also sending nFrameNum=1 from client and receiving as nFrameNum:1936287860 at server. frameData also at client side i'm sending "This is 1st line" and at server receiving only "is 1st line". Will someone help in to get rid of this problem?

thanks and regards,

Sri

Shouldn't this:

send(sock, (char *)&client_info, bytesRead, 0);

be:

send(sock, (char *)&client_info, sizeof( client_info ), 0);

And you should check the return value of send() and particularly of recv() - there is no guarantee that a call to recv will fetch your structure in one go.

Sending raw structures like this is a very bad idea.

You have to deal with endianness (byte order), packing (which can still be a problem even with #pragma pack ) and another problem you have is that the sizes of types like 'int' can vary between platforms.

I would recommend a serialization library like Google Protocol Buffers to help you with this. If you still want to do it yourself, you need to look up functions like htonl to convert integer types to network byte-order, and start using fixed-size primitives like uint32_t etc.

You should also stop sending the entire struct at once and instead write helper functions like writeClientStruct(int sock, struct client_struct *) which will send each member value separately to avoid packing problems between platforms.

One explanation would be that your client and server have different interpretation for the size of "unsigned long". (Running on different machines or different compiler options, other being 32-bit and other 64-bit).

That would explain the symptoms:

  • bRT_flag shifted by 32-bits to nFrameNum
  • nFrameNum containing first 32-bits from frameData (1936287860 -> 0x73696874 -> "siht" -> with endian swap "this")

Trivial check for this would be to check sizeof(the struct) or sizeof(unsigned long) to see if they match.

Please see Mike Weller's post for how to fix this properly.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM