繁体   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