【问题标题】:C socket sending multiple fields message with binary protocolC套接字使用二进制协议发送多字段消息
【发布时间】:2013-01-08 00:28:16
【问题描述】:

如何构造具有给定消息规范的请求消息,然后发送到服务器思想 c 套接字?二进制协议用于客户端和服务器通信。以下方法是否正确?

给定消息规范:

字段格式长度值 ------------ ------ ------ -------- 请求 ID Uint16 2 20 requestNum Uint16 2 100 requestTitle String 10 数据串 /****************** 方法一 ****************/ typedef 无符号短 uint16; 类型定义结构{ uint16 请求 ID [2]; uint16 requestNum [2]; 无符号字符请求标题[10]; }requestMsg; … 请求消息 rqMsg; memcpy(rqMsg.requesID, "\x0\x14", 2); //20 memcpy(rqMsg.requesNum, "\x0\x64", 2); //100 memcpy(rqMsg.requesTitle, "title01", 10); … 发送(sockfd, &rqMsg, sizeof(rqMsg), 0); /******************方法2 ****************/ 无符号字符 rqMsg[14]; memset(rqMsg, 0, 14); memcpy(rqMsg, "\x0\x14", 2); memcpy(rqMsg+2, "\x0\x64", 2); memcpy(rqMsg+4, "title01", 10); … 发送(袜子,&rqMsg,sizeof(rqMsg),0);

【问题讨论】:

  • 只有第二种方法是正确的,大家可以自己想想memset这个调用的用处。
  • @KerrekSB 这并不完全正确。如果他的机器的字节序与协议的字节序匹配,并且如果他使用pragma pack(1) 作为结构,他可以获得正确的结果。 (好的,只要他从字段中删除数组大小)但不幸的是代码不是真正可移植的......

标签: c


【解决方案1】:

它们至少部分正确,但我更喜欢第一个,因为与手动索引相比,它允许快速和自然的数据操作和访问,并且留出更少的错误空间。作为奖励,您甚至可以整体复制和分配结构值,并且在 C 中它可以按预期工作。

但是对于任何传出数据,您应该确保使用“打包”结构。它不仅会减少传输到基于数组的实现图的数据量,而且还会确保所有涉及的程序中的字段对齐方式相同。对于我尝试过的大多数 C 编译器(包括 GCC),它可以使用 __attribute__((__packed__)) 属性来完成,但是有不同的编译器需要不同的属性甚至不同的关键字。

如果您的应用程序要在不同的架构上运行(ARM 客户端与 x86_64 服务器是一个主要示例),则可能还需要字节序控制。在进行任何计算或数据输出之前,我只是使用一些简单的宏来单独预处理每个字段:

#define BYTE_SWAP16(num)    ( ((num & 0xFF) << 8) | ((num >> 8) & 0xFF) )
#define BYTE_SWAP32(num)    ( ((num>>24)&0xff) | ((num<<8)&0xff0000) | ((num>>8)&0xff00) | ((num<<24)&0xff000000) )

但您可以使用不同的方法,例如 BCD 编码、单独的解码函数或其他方法。

还要注意 uint16_t 已经是一个 2 字节的值。您可能不需要其中两个来存储您的单个值。

【讨论】:

    【解决方案2】:

    恐怕你误解了一些东西:长度列似乎告诉你以字节为单位的长度,所以如果你收到一个 uint16,你会收到 2 个字节。

    您的第一种方法可能会通过data structure alignment 导致严重问题。如果我在你的鞋子里,我更喜欢第二种方法,并将我自己的字节填充到一个字节数组中。

    关于在此处填充字段的一般说明:我将 memcpy 用于 uint16 等“本机”字段是没有用的。它可能有效,但只是浪费运行时间。您可以填写结构的字段,只需为其分配一个值,例如rqMsg.requesID = 20;

    另一个问题是二进制协议的字节顺序或endianness

    作为一个完整的包,我将实现一个“serializeRequest”函数,获取结构的字段并根据协议将其转换为字节数组。

    【讨论】:

    • 您的所有回复都对我解决问题很有帮助。非常感谢!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-05-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-09-06
    相关资源
    最近更新 更多