繁体   English   中英

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

[英]Passing structure over TCP socket in C

我正在用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也在客户端我发送“这是第一行”,在服务器接收“只是第一行”。 有人会帮助摆脱这个问题吗?

感谢致敬,

斯里兰卡

不应该这样:

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

是:

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

你应该检查send()的返回值,特别是recv()的返回值 - 无法保证对recv的调用将一次性获取你的结构。

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

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

我建议像Google Protocol Buffers这样的序列化库来帮助你解决这个问题。 如果你仍然想自己做,你需要查找像htonl这样的函数将整数类型转换为网络字节顺序,并开始使用固定大小的原语,如uint32_t等。

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

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

这可以解释症状:

  • bRT_flag将32位移位到nFrameNum
  • nFrameNum包含来自frameData的第一个32位(1936287860 - > 0x73696874 - >“siht” - >带有endian swap“this”)

对此进行简单检查将检查sizeof(结构)或sizeof(unsigned long)以查看它们是否匹配。

请参阅Mike Weller的帖子,了解如何正确解决这个问题。

暂无
暂无

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

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