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

发布于 2024-11-06 02:17:08 字数 1819 浏览 0 评论 0原文

我正在用 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

暖风昔人 2024-11-13 02:17:08

不应该这样:

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

是:

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

并且您应该检查 send() 的返回值,特别是 recv() 的返回值 - 不能保证对 recv 的调用会一次性获取您的结构。

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.

夜巴黎 2024-11-13 02:17:08

像这样发送原始结构是一个非常糟糕的主意。

您必须处理字节序(字节顺序)、打包(即使使用#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 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.

醉生梦死 2024-11-13 02:17:08

一种解释是您的客户端和服务器对“unsigned long”的大小有不同的解释。 (在不同的机器或不同的编译器选项上运行,其他是 32 位和其他 64 位)。

这可以解释症状:

  • bRT_flag 移动 32 位到 nFrameNum
  • nFrameNum 包含来自frameData的前32位(1936287860 -> 0x73696874 -> "siht" -> with endian swap "this")

对此的简单检查是检查 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:

  • 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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文