簡體   English   中英

通過TCP套接字發送C結構

[英]Send C struct over TCP socket

我已經看到了很多與我的問題相關的答案,但是我真的不能在我的情況下使用它。

我正在Linux域下使用帶有C語言的套接字編程來構建網絡模塊。 我必須實現一個函數,該函數可以發送包含int,char,char *和其他一些結構(嵌套結構)的結構。

struct EnQuery
{
   char  type[6]; // insert, select , update , delete
   char * columns; //note here, it's an array of big, {name, age, sex, position, email}  not in string
   struct Values * values; //an array of values(another struct), {tom, 23, male, student, tom@compan.com}  is represented by the second struct values, not in string
   struct condition * enCondition; //  array of condition,  "name=tom and age>30" is represnted by the third struct condition
   short len;
   short rn; 
};

struct Values
{
    char * doc;
    char  key[2];
    char  s;
};

struct condition
{
     short k;              
     struct condition * children;
};

以上是我要發送的結構。 我聲明變量,並使用send()函數通過套接字發送。

我將如何通過套接字發送char *? 還是有辦法方便地調整char數組的長度?

PS我不能使用外部庫

我將如何通過套接字發送char *?

顯然,發送指針值不是一件有用的事,因為指針不會指向接收計算機上任何有效的東西。

因此,您不必發送指針,而必須發送它指向的數據。 一種典型的實現方法是首先發送指針指向的字節數:

uint32_t sLen = strlen(doc)+1;  // +1 because I want to send the NUL byte also
uint32_t bigEndianSLen = htonl(sLen);
if (send(sock, &bigEndianSLen, sizeof(bigEndianSLen), 0) != sizeof(bigEndianSLen)) perror("send(1)");

....然后發送字符串的字節:

if (send(sock, doc, sLen, 0) != sLen) perror("send(2)");

在接收端,您將執行相反的操作:首先接收字符串的長度:

uint32_t bigEndianSLen;
if (recv(sock, &bigEndianSLen, sizeof(bigEndianSLen), 0) != sizeof(bigEndianSLen)) perror("recv(1)");
uint32_t sLen = ntohl(bigEndianSLen);

...,然后接收字符串的數據:

char * doc = malloc(sLen+1);
if (recv(sock, doc, sLen, 0) != sLen) perror("recv(2)");
doc[sLen] = '\0';  // paranoia:  make sure the string is terminated no matter what

請注意,此示例代碼有點天真,因為它無法正確處理send()或recv()返回傳給它們的字節數以外的值的情況。 生產質量代碼將正確處理錯誤(例如,通過關閉連接),並且還將正確處理以下情況:send()或recv()發送/接收僅傳輸請求的某些字節(通過調用send()/稍后再次將recv()用作剩余的未發送/未接收字節)。

您需要做出選擇:使用“打包”功能在發送方對內存中的數據結構進行序列化,使用解壓縮功能通過線進行發送並反序列化(直接使用),或者直接對套接字動態地進行序列化/反序列化(更好)之后,作為第一個版本的優化)。

您可以從以下開放源代碼中獲得一些啟發,例如: https : //code.google.com/p/protobuf-c/

用“類型編號”定義一個枚舉。 使用您的示例:

Tchar
Tstring
Tshort
Tint
TEnQuery
TValues
Tcondition
Tpop

定義一些標志類型,這些標志位與類型相關:

Tarray -- array of base type
現在輸出類型編號。 緊隨其后的是實際數據。 例如,要輸出一個Values結構:
  Tvalues\n TString,文檔數據(inc EOS)\n Tchar |  Tarray,2,關鍵數據\n Tchar的價值\n TPOP 
任何聚合(例如struct)都會執行與Tpop配對的隱式“ Tpush”

現在,您有了一個字節流,可以使用某種狀態機來遞歸處理該字節流。 對於上述所有類型,您將需要遞歸函數進行導出/導入。 導入時,關鍵是類型編號是您要調度的對象

結構是(ANSI)C語言可用的數據類型。 我相信您正在尋找以下功能來執行結構中的數據發送。

  1. 插座()
  2. 讀()
  3. 寫()

請記住,這些是IPC (也稱為信號 ), TCP / IP和/或UDP通信的最低要求。

有關客戶端/服務器體系結構的簡單實現(盡管如今已經完全過時了),請參考; 客戶 / 服務器 您可能會更好地將研究重點放在對等通信上,因為每個對等點之間都擁有彼此的連接信息,因此可以提供一組更可靠的故障轉移 看這里:

點對點

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM