为什么在 Socket Programming - C 中将位移动 8?
Why shift bits by 8 in Socket Programming - C?
我正在学习 FreeBSH 开发人员手册,我在那里看到了这段用于套接字编程的代码:
struct sockaddr_in sa;
sa.sin_addr.s_addr = htonl((((((192 << 8) | 43) << 8) | 244) << 8) | 18);
这里为什么要用移位和或?
我知道位移和异或是什么,我做了一个非常小的测试程序:
int c = 5;
printb(c);
int d = 5<<2;
printb(d);
int e = d | c;
printb(e);
打印:
00000000000000000000000000000101
00000000000000000000000000010100
00000000000000000000000000010101
但是我不明白为什么 sa.sin_addr.s_addr 我需要用以下值移动 ip 和/或它。有人可以解释一下吗?
让我们先看看sock_addr_in
的实际结构:
#include <netinet/in.h>
struct sockaddr_in {
short sin_family;
unsigned short sin_port;
struct in_addr sin_addr;
char sin_zero[8];
};
in_addr
的结构:
struct in_addr {
unsigned long s_addr;
};
现在,通常,当我们使用这个 s_addr 时,我们写:
inet_aton("89.161.169.137", &myaddr.sin_addr.s_addr); //dummy ip
好的。我们检查一下 inet_aton 人怎么样?
inet_aton()
converts the Internet host address cp from the IPv4
numbers-and-dots notation into binary form (in network byte order) and
stores it in the structure that inp points to. inet_aton() returns
nonzero if the address is valid, zero if not.
现在我们清楚地知道unsigned long s_addr
包含了ip的二进制形式网络字节序.
您不需要改变自己的 ip,只需使用 inet_aton() 和 inet_ntoa() 来操作 ip 地址。
它正在为 IP 192.43.244.18 创建二进制表示。
下面我们来一一分析每个操作。
从这些常量的二进制表示开始:
192 = 11000000
43 = 00101011
244 = 11110100
18 = 00010010
最内层操作:
(192 << 8) =
= 11000000 << 8 =
= 1100000000000000
下一个:
(192 << 8) | 43 =
= 1100000000000000 |
00101011 =
1100000000101011
下一个:
((192 << 8) | 43) << 8) =
= 1100000000101011 << 8 =
= 110000000010101100000000
下一个:
(((192 << 8) | 43) << 8) | 244 =
= 110000000010101100000000 | 244 =
= 110000000010101100000000 |
11110100 =
= 110000000010101111110100
下一个:
(((192 << 8) | 43) << 8) | 244) << 8 =
= 110000000010101111110100 << 8 =
= 11000000001010111111010000000000
最后:
(((((192 << 8) | 43) << 8) | 244) << 8) | 18 =
= 11000000001010111111010000000000 | 18 =
= 11000000001010111111010000000000 |
00010010 =
= 11000000001010111111010000010010
首先,让我们从二元运算开始。
正如您正确假设的那样,移位 'a << b' 将 a 中的位向左移动了 b 的量。移位 1 可以看作是乘以 2。(这实际上是优化发生的方式,因为移位操作比乘法快,但大多数现代编译器都考虑到了这一点。)
or 语句是“a|b”。 or中,如果两个元素之一为1,则结果为1。这是位运算中使用的标准方法,实际上a和b中的所有位 是或运算。例如。 a = 0010 1011, b = 1111 0000, a|b = 1111 1011.
现在回到问题。在你的情况下 sa.sin_addr.s_addr 开头是 0,所以当它与 192 进行或运算时,它会将 192 的位表示添加到变量中。然后将它移动 8 位,以便为 ip 地址中的下一个元素释放 space - 每个元素的值都可以在 0-255 之间,正好是 8 位。然后对其余部分重复此操作。
我正在学习 FreeBSH 开发人员手册,我在那里看到了这段用于套接字编程的代码:
struct sockaddr_in sa;
sa.sin_addr.s_addr = htonl((((((192 << 8) | 43) << 8) | 244) << 8) | 18);
这里为什么要用移位和或?
我知道位移和异或是什么,我做了一个非常小的测试程序:
int c = 5;
printb(c);
int d = 5<<2;
printb(d);
int e = d | c;
printb(e);
打印:
00000000000000000000000000000101
00000000000000000000000000010100
00000000000000000000000000010101
但是我不明白为什么 sa.sin_addr.s_addr 我需要用以下值移动 ip 和/或它。有人可以解释一下吗?
让我们先看看sock_addr_in
的实际结构:
#include <netinet/in.h>
struct sockaddr_in {
short sin_family;
unsigned short sin_port;
struct in_addr sin_addr;
char sin_zero[8];
};
in_addr
的结构:
struct in_addr {
unsigned long s_addr;
};
现在,通常,当我们使用这个 s_addr 时,我们写:
inet_aton("89.161.169.137", &myaddr.sin_addr.s_addr); //dummy ip
好的。我们检查一下 inet_aton 人怎么样?
inet_aton()
converts the Internet host address cp from the IPv4 numbers-and-dots notation into binary form (in network byte order) and stores it in the structure that inp points to. inet_aton() returns nonzero if the address is valid, zero if not.
现在我们清楚地知道unsigned long s_addr
包含了ip的二进制形式网络字节序.
您不需要改变自己的 ip,只需使用 inet_aton() 和 inet_ntoa() 来操作 ip 地址。
它正在为 IP 192.43.244.18 创建二进制表示。
下面我们来一一分析每个操作。
从这些常量的二进制表示开始:
192 = 11000000
43 = 00101011
244 = 11110100
18 = 00010010
最内层操作:
(192 << 8) =
= 11000000 << 8 =
= 1100000000000000
下一个:
(192 << 8) | 43 =
= 1100000000000000 |
00101011 =
1100000000101011
下一个:
((192 << 8) | 43) << 8) =
= 1100000000101011 << 8 =
= 110000000010101100000000
下一个:
(((192 << 8) | 43) << 8) | 244 =
= 110000000010101100000000 | 244 =
= 110000000010101100000000 |
11110100 =
= 110000000010101111110100
下一个:
(((192 << 8) | 43) << 8) | 244) << 8 =
= 110000000010101111110100 << 8 =
= 11000000001010111111010000000000
最后:
(((((192 << 8) | 43) << 8) | 244) << 8) | 18 =
= 11000000001010111111010000000000 | 18 =
= 11000000001010111111010000000000 |
00010010 =
= 11000000001010111111010000010010
首先,让我们从二元运算开始。 正如您正确假设的那样,移位 'a << b' 将 a 中的位向左移动了 b 的量。移位 1 可以看作是乘以 2。(这实际上是优化发生的方式,因为移位操作比乘法快,但大多数现代编译器都考虑到了这一点。) or 语句是“a|b”。 or中,如果两个元素之一为1,则结果为1。这是位运算中使用的标准方法,实际上a和b中的所有位 是或运算。例如。 a = 0010 1011, b = 1111 0000, a|b = 1111 1011.
现在回到问题。在你的情况下 sa.sin_addr.s_addr 开头是 0,所以当它与 192 进行或运算时,它会将 192 的位表示添加到变量中。然后将它移动 8 位,以便为 ip 地址中的下一个元素释放 space - 每个元素的值都可以在 0-255 之间,正好是 8 位。然后对其余部分重复此操作。