簡體   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