簡體   English   中英

通過一個套接字發送和接收兩個結構

[英]Send & recv two structures by one socket

我有一個結構:

struct one
{
    char name[10];
    int age;
};

struct two
{
    int X;
    int Y;
};

現在我想發送此結構,例如第一個“一個”,第二個“兩個”並從套接字接收。

但是,如果我不知道我發送的是哪種結構(stuct'one'或'two'),該如何接收呢?

您可以在發送的數據中添加標識符:

enum StructID {
    STRUCT_ONE,
    STRUCT_TWO,
};

在發送數據之前先發送。

Uint16     id;
struct one dataOne;

id = STRUCT_ONE;
send(&id, sizeof(id));
send(&dataOne, sizeof(dataOne));

在接收端:

char buffer[256];
unsigned nbRecv;

nbRecv = recv(buffer, sizeof(buffer));
if (nbRecv > sizeof(Uint16))
{
    char * p = buffer;

    Uint16 *pId = (Uint16*)p;
    p += sizeof(*pId);

    if (*pId == STRUCT_ONE)
    {
        struct one * pOne = (struct one *)p;
        p += sizeof(*pOne);

        if (nbRecv >= sizeof(*pId) + sizeof(*pOne))
        {
           // deal with pOne.
        }
        else
        {
           // Deal with too little data; pOne is incomplete....
        }
    }
    else if (*pId == STRUCT_TWO)
    {
        struct two * pTwo = (struct two *)p;
        p += sizeof(*pTwo);

        if (nbRecv >= sizeof(*pId) + sizeof(*pTwo))
        {
           // deal with pOne.
        }
        else
        {
           // Deal with too little data; pTwo is incomplete....
        }
    }
    else
    {
        // Error, unknown data.
    }
}
else
{
    // Deal with too little data....
}

本質上,您正在定義協議,標識符只是一個非常簡單的“標頭”,用於識別數據。 像這樣的許多協議也發送要遵循的數據大小,因此您可以在下一個標識符/標頭之前分辨出有多少數據。

除整數外,另一種常見方法是發送4個ASCII字符,因為當您查看原始數據(Wireshark,hexdump,調試器中的字節等)時,它們很容易讀取。 對於您的示例,我建議:

const char STRUCT_ONE_FOURCC[4] = { 'O', 'N', 'E', ' ' };
const char STRUCT_ONE_FOURCC[4] = { 'T', 'W', 'O', ' ' };

(請注意,它們不是字符串,因為它們不是以NULL結尾的。它們是固定大小的字符數組。)

注意:在上面的代碼中,我沒有進行大多數錯誤檢查和字節序交換(到/從網絡字節順序開始)。

也可以看看:

您需要執行序列化,並添加一個標識符。 一個(不是這樣)簡單的解決方案是:

template<int index>
struct serializable {
  static const int identifier = index;
}

struct A :
  public serializable<1>
{
  int a, b;
  char * serialize() { char *buffer = new char[sizeof (A) + sizeof (int)]; memcpy(buffer, this, sizeof(A)); }
  static A deserialize(const char *in) { return A{&in[sizeof(int)], &in[sizeof(int) * 2]}; }
}

您應該定義一個將在通信中使用的協議,不要發送結構,因為不同系統中的數據類型和內存對齊方式不同。 您可以改用xml,序列化您的結構並發送xml字符串。 還要檢查正在通過TCP實現通信協議的其他庫。 您可以檢查例如Apache Axis。 對於手動序列化,可以使用boost :: serialization並將結構轉換為xml字符串。

暫無
暫無

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

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