简体   繁体   English

在C中通过TCP套接字传递结构

[英]Passing structure over TCP socket in C

I'm writing a small client server application in C. 我正在用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, 服务器屏幕上的O / p,

 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. 我从客户端发送10个bRT_flag,在服务器上接收1个。 Also sending nFrameNum=1 from client and receiving as nFrameNum:1936287860 at server. 还从客户端发送nFrameNum = 1并在服务器上以nFrameNum:1936287860接收。 frameData also at client side i'm sending "This is 1st line" and at server receiving only "is 1st line". frameData也在客户端我发送“这是第一行”,在服务器接收“只是第一行”。 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. 你应该检查send()的返回值,特别是recv()的返回值 - 无法保证对recv的调用将一次性获取你的结构。

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. 您必须处理字节顺序(字节顺序),打包(即使使用#pragma pack仍然可能存在问题),另一个问题是像'int'这样的类型的大小可能因平台而异。

I would recommend a serialization library like Google Protocol Buffers to help you with this. 我建议像Google Protocol Buffers这样的序列化库来帮助你解决这个问题。 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. 如果你仍然想自己做,你需要查找像htonl这样的函数将整数类型转换为网络字节顺序,并开始使用固定大小的原语,如uint32_t等。

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. 您还应该立即停止发送整个结构,而是编写帮助函数,如writeClientStruct(int sock,struct client_struct *),它将分别发送每个成员值以避免平台之间的打包问题。

One explanation would be that your client and server have different interpretation for the size of "unsigned long". 一种解释是您的客户端和服务器对“unsigned long”的大小有不同的解释。 (Running on different machines or different compiler options, other being 32-bit and other 64-bit). (在不同的机器或不同的编译器选项上运行,其他是32位和其他64位)。

That would explain the symptoms: 这可以解释症状:

  • bRT_flag shifted by 32-bits to nFrameNum bRT_flag将32位移位到nFrameNum
  • nFrameNum containing first 32-bits from frameData (1936287860 -> 0x73696874 -> "siht" -> with endian swap "this") nFrameNum包含来自frameData的第一个32位(1936287860 - > 0x73696874 - >“siht” - >带有endian swap“this”)

Trivial check for this would be to check sizeof(the struct) or sizeof(unsigned long) to see if they match. 对此进行简单检查将检查sizeof(结构)或sizeof(unsigned long)以查看它们是否匹配。

Please see Mike Weller's post for how to fix this properly. 请参阅Mike Weller的帖子,了解如何正确解决这个问题。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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