我在编写网络软件时面临一些问题。当我尝试发送或接收包含8字节数据类型的结构时,下一个发送或接收的结构以某种方式受到影响。我有几点想法,但首先我想在进入调试之前确认一件事。 我在64位x-86系统上使用32位Ubuntu 11.04(愚蠢的我)。这与字节对齐问题有关吗?
我正在开发一个与Open Flow交换机通信的控制器。 openflow协议根据构建的交换机定义一组规范。问题是当我尝试与交换机通信时,一切正常,直到我发送或接收包含64位日期类型(uint64_t)的结构。用于发送和接收功能的特定结构是
estruct ofp_header {
uint8_t version; /* OFP_VERSION. */
uint8_t type; /* One of the OFPT_ constants. */
uint16_t length; /* Length including this ofp_header. */
uint32_t xid; /* Transaction id associated with this packet.
Replies use the same id as was in the request
to facilitate pairing. */};
assert(sizeof(struct ofp_header) == 8);
/* Switch features. */
struct ofp_switch_features {
struct ofp_header header;
uint64_t datapath_id; /* Datapath unique ID. The lower 48-bits are for a MAC address, while the upper 16-bits are implementer-defined. */
uint32_t n_buffers; /* Max packets buffered at once. */
uint8_t n_tables; /* Number of tables supported by datapath. */
uint8_t pad[3]; /* Align to 64-bits. */
/* Features. */ /* Bitmap of support "ofp_capabilities". */
uint32_t capabilities; /* Bitmap of supported "ofp_action_type"s. */
uint32_t actions;
/* Port info.*/
struct ofp_phy_port ports[0]; /* Port definitions. The number of ports is inferred from the length field in the header. */
};
assert(sizeof(struct ofp_switch_features) == 32);
问题是当我使用任何其他数据类型小于64位的结构进行通信时,一切都很顺利。当我收到功能回复时,它显示正确的值但在此之后,如果我收到任何其他结构,它显示垃圾值。即使我再次收到功能回复,我也会得到垃圾值。简而言之,如果在任何代码点我收到功能请求或规范中定义的任何其他结构,其数据类型为64位,则下一个结构将接收垃圾值。用于发送和接收功能请求的代码如下
////// features request and reply ////////////
ofp_header features_req;
features_req.version=OFP_VERSION;
features_req.type=OFPT_FEATURES_REQUEST;
features_req.length= htons(sizeof features_req);
features_req.xid = htonl(rcv_hello.xid);
if (send(connected, &features_req, sizeof(features_req), 0)==-1) {
printf("Error in sending message\n");
exit(-1);
}
printf("features req sent!\n");
ofp_switch_features features_rep={0};
if (recv(connected, &features_rep, sizeof(features_rep), 0)==-1) {
printf("Error in receiving message\n");
exit(-1);
}
printf("message type : %d\n",features_rep.header.type);
printf("version : %d\n",features_rep.header.version);
printf("message length: %d\n",ntohs(features_rep.header.length));
printf("xid : %d\n",ntohl(features_rep.header.xid));
printf("buffers: %d\n",ntohl(features_rep.n_buffers));
printf("tables: %d\n",features_rep.n_tables);
答案 0 :(得分:6)
htons
等确保以网络顺序发送整数。为各种机器的端部节省麻烦这将确保您不会有任何麻烦。
答案 1 :(得分:1)
我得到了Daniweb.com的帮助,所有的功劳都归功于一个带有NEZACHEM缺口的人。 His answer was,我引用:
该问题与64位类型无关。 您阅读的值不是垃圾,而是非常有价值的端口定义:
struct ofp_phy_port ports[0]; /* Port definitions. The number of ports is inferred from the length field in the header. */
这意味着,一旦你
recv(connected, &features_rep, sizeof(features_rep), 0)
你需要检查features_rep.header.length, 弄清楚p_phy_port的结构有多少, 为他们分配内存并读取这些数据。
我做到了,多亏了他,我的问题得到了解决,一切顺利:) 感谢所有回复的人。 干杯:)
答案 2 :(得分:0)
答案 3 :(得分:0)
这是想要的东西
features_req.version=OFP_VERSION;
features_req.type=OFPT_FEATURES_REQUEST;
features_req.length= htons(sizeof features_req);
features_req.xid = htonl(rcv_hello.xid);
char data[8];
data[0] = features_req.version;
data[1] = features_req.type;
memcpy(data + 2, &features_req.length, 2);
memcpy(data + 4, &features_req.xid, 4);
if (send(connected, data, 8) ....
在接收端
char data[8];
if (recv(conncted, data, 8) ...
features_req.version = data[0];
features_req.type = data[1];
memcpy(&features_req.length, data + 2, 2);
memcpy(&features_req.xid, data + 4, 4);
features_req.length = ntohs(features_req.length);
features_req.xid= ntohl(features_req.xid);
答案 4 :(得分:0)
1如果你坚持发送结构,你应该确保它们是字节对齐的。
为此,请使用pragma pack
,如下所示:
#pragma pack(1)
struct mystruct{
uint8_t myint8;
uint16_t myint16;
};
#pragma pack()
这样做可以确保此结构仅使用3个字节。
2为了将64位值从主机顺序转换为网络顺序,这篇文章读取了解释:Is there any "standard" htonl-like function for 64 bits integers in C++?(不,它只以c ++开头,也以C结尾)