sin_family的网络字节顺序

时间:2017-10-30 11:32:42

标签: python c networking endianness

我正在从Ubuntu盒子上的python发送UDP消息到vxworks机器上的C程序。 vxworks机器上的Endianness与Network Byte Order不匹配,所以我不得不使用ntohs,ntohl等交换字节顺序。

我正在读取UDP连接,然后尝试确定“系列”,所以我知道我是否应解码IPV4或IPV6。我想做这样的事......但它不起作用。

struct sockaddr data = {};
char udp_ip[INET6_ADDRSTRLEN] = {0};
// ... (recvfrom ...)
if (AF_INET == data.sa_family)
{
    struct sockaddr_in*s = (struct sockaddr_in *)&data;
    const char *addr = inet_ntop(AF_INET, &s->sin_addr, udp_ip, sizeof(udp_ip));
    udp_port = ntohs(s->sin_port);
    ...
}
if (AF_INET6 == data.sa_family)
{
    struct sockaddr_in6 *s = (struct sockaddr_in *)&data;
    const char *addr = inet_ntop(AF_INET6, &s->sin6_addr, udp_ip, sizeof(udp_ip));
    udp_port = ntohs(s->sin6_port);
    ...
}

我习惯看到端口,并且交换了类似的字段,但我发现该系列是一个多字节字段。我发现代码不起作用,因为我的sa_family值超出了范围。在我的这台机器的标题中,最大的AF_ *值是40.我看到的值超过500.我看起来sa_family上的字节被交换了,我也需要交换它们的字节顺序。类似的东西:

const sa_family_t family = ntohs(data.sa_family);

然后我会在if检查中使用该family变量。 问题:这是否合理?我以前从未见过ntoh *对这个家庭做过的事。我很惊讶它是多字节(sizeof(data.sa_family)== 2)。

我不认为我的python代码是相关的,但为了完整性..

udp_sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
udp_sock.bind(('', 0))
data = self.create_data()
udp_sock.sendto(data, (ip, port))     

发送的数据有点无关紧要,因为在我解析数据之前我已经陷入困境,如果数据像“FOO”一样简单就会出现问题。

我检查过的其他文章:what kind of fields in network packets should be converted to network byte order以及Network byte order and endianness issues

我也读过这篇文章,这似乎与我所看到的相矛盾。 struct sockaddr_in member byte order for bind()

同样地,相反地,(但未示出),当从我的vxworks(非网络字节顺序机器)发回消息回到我的另一台机器时,我必须在设置消息时按下(AF_INET)或它没有'工作。我只是感到困惑,因为我在SO上看到了相互矛盾的建议所以我认为我必须做其他根本错误的事情。 问题:如果您不需要转换家庭的建议(htons / ntohs),我做错了什么?

1 个答案:

答案 0 :(得分:0)

家庭不需要转换。它本身不会传输。见:

https://en.wikipedia.org/wiki/IPv4

https://en.wikipedia.org/wiki/IPv6

如果版本值为4,则其IP版本== 4 ... IPV4。如果它的版本== 6 ..那么IPV6。

真正的问题是我正在进行交叉编译,而且我的目标头文件版本错误。我有一个结构是这样的:

struct sockaddr {
    u_short sa_family;              /* address family */
    char    sa_data[14];            /* up to 14 bytes of direct address */
};

在真实系统上,结构包含另一个字段:

/*
 * Structure used by kernel to store most
 * addresses.
 */
struct sockaddr {
    unsigned char   sa_len;      /* total length */
    sa_family_t     sa_family;   /* address family */
    char            sa_data[14]; /* actually longer; address value */
};
#define SOCK_MAXADDRLEN 255     /* longest possible addresses */

额外的角色和结尾是我问题的根源。我看到一个像528这样的值。当字节被组合并被视为两个字节的无符号时,它是长度为“10”和“2”的组合。