在C中通过TCP套接字传递结构
我正在用 C 编写一个小型客户端服务器应用程序。
在客户端,我有一个类似的结构,
#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
并将变量填充为,
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;
并使用以下函数发送到服务器,
send(sock, (char *)&client_info, bytesRead, 0);
在服务器端,我有一个类似的结构(与客户端结构相同),
#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
并接收消息并在屏幕上打印,
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 在服务器屏幕上,
lcl_viewBox.bRT_flag:1
lcl_viewBox.nFrameNum:1936287860
lcl_viewBox.frameData: is 1st line
我不知道它在我的服务器端到底发生了什么。我从客户端发送 10 个 bRT_flag 并在服务器上接收 1 个。还从客户端发送 nFrameNum=1 并在服务器上接收为 nFrameNum:1936287860。 FrameData 也在客户端发送“这是第一行”,而在服务器上仅接收“这是第一行”。 有人会帮忙解决这个问题吗?
谢谢和问候,
斯里
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
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
不应该这样:
是:
并且您应该检查 send() 的返回值,特别是 recv() 的返回值 - 不能保证对 recv 的调用会一次性获取您的结构。
Shouldn't this:
be:
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.
像这样发送原始结构是一个非常糟糕的主意。
您必须处理字节序(字节顺序)、打包(即使使用#pragma pack,这仍然是一个问题),您遇到的另一个问题是“int”等类型的大小可能会有所不同平台。
我建议您使用 Google Protocol Buffers 之类的序列化库来帮助您解决此问题。如果您仍然想自己完成,则需要查找像
htonl
这样的函数来将整数类型转换为网络字节顺序,并开始使用固定大小的基元,例如uint32_t
。您还应该立即停止发送整个结构,而是编写辅助函数,例如 writeClientStruct(int sock, struct client_struct *) ,它将单独发送每个成员值,以避免平台之间的打包问题
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 likeuint32_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.
一种解释是您的客户端和服务器对“unsigned long”的大小有不同的解释。 (在不同的机器或不同的编译器选项上运行,其他是 32 位和其他 64 位)。
这可以解释症状:
对此的简单检查是检查 sizeof(struct) 或 sizeof(unsigned long) 以查看它们是否匹配。
请参阅 Mike Weller 的帖子了解如何正确解决此问题。
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:
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.