简体   繁体   English

为什么在Socket Programming-C中将位移位8?

[英]Why shift bits by 8 in Socket Programming - C?

I am studying the FreeBSH Developers Handbook and there I am seeing this code for Socket programming: 我正在研究《 FreeBSH开发人员手册》,在那儿我看到了用于Socket编程的代码:

struct sockaddr_in sa;
sa.sin_addr.s_addr = htonl((((((192 << 8) | 43) << 8) | 244) << 8) | 18);

Why is the bitwise shift and or is used here? 为什么在这里使用“或”按位移位?

I know what bitwise shift and xor is, I made a very small test program: 我知道按位移位和是什么,我做了一个很小的测试程序:

int c = 5;
printb(c);

int d = 5<<2;
printb(d);

int e = d | c;
printb(e);

which prints: 打印:

00000000000000000000000000000101
00000000000000000000000000010100
00000000000000000000000000010101

however I do not understand why for sa.sin_addr.s_addr I need to shift the ip and or it with the following value. 但是我不明白为什么对于sa.sin_addr.s_addr我需要移动ip和/或使用以下值。 Can someone explain? 有人可以解释吗?

It is creating the binary representation for the IP 192.43.244.18. 它正在创建IP 192.43.244.18的二进制表示形式。

Let's analyse each operation one by one. 让我们逐一分析每个操作。

Start from the binary representation of those constants: 从这些常量的二进制表示形式开始:

192 = 11000000
 43 = 00101011
244 = 11110100
 18 = 00010010

Innermost operation: 最内在的操作:

(192 << 8) =

= 11000000 << 8 =

= 1100000000000000

Next one: 下一个:

(192 << 8) | 43 =

= 1100000000000000 |
          00101011 =

  1100000000101011

Next one: 下一个:

((192 << 8) | 43) << 8) =

= 1100000000101011 << 8 =

= 110000000010101100000000

Next one: 下一个:

(((192 << 8) | 43) << 8) | 244 =

= 110000000010101100000000 | 244 =

= 110000000010101100000000 |
                  11110100 =

= 110000000010101111110100

Next one: 下一个:

(((192 << 8) | 43) << 8) | 244) << 8 =

= 110000000010101111110100 << 8 =

= 11000000001010111111010000000000

And finally: 最后:

(((((192 << 8) | 43) << 8) | 244) << 8) | 18 =

= 11000000001010111111010000000000 | 18 =

= 11000000001010111111010000000000 |
                          00010010 =

= 11000000001010111111010000010010

Let's start by looking at the actual structure of sock_addr_in : 让我们从查看sock_addr_in的实际结构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];  
};

And the struct of in_addr : in_addr的结构:

struct in_addr {
    unsigned long s_addr; 
};

Now, usually, when we utilisize this s_addr, we write : 现在,通常,当我们利用此s_addr时,我们这样写:

inet_aton("89.161.169.137", &myaddr.sin_addr.s_addr); //dummy ip

OK. 好。 How about we check up the inet_aton man ? 我们去检查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()将Internet主机地址cp从IPv4的数字和点表示法转换为二进制形式(以网络字节顺序),并将其存储在inp指向的结构中。 inet_aton() returns nonzero if the address is valid, zero if not. 如果地址有效,则inet_aton()返回非零,否则返回零。

Now we clearly know that the unsigned long s_addr contains the binary form of the ip in network byte order . 现在我们清楚地知道, unsigned long s_addr包含以网络字节顺序排列的ip的二进制形式。

You don't need to shift the ip youreslf, instead just use inet_aton() and inet_ntoa() for manipulating ip adresses. 您不需要移动ip youreslf,而只需使用inet_aton()和inet_ntoa()来处理ip地址。

First, lets begin with the binary operations. 首先,让我们从二进制操作开始。 The shift ' a << b ' as you have correctly assumed moves the bits in a by an amount of b in the left direction. 您正确假设的移位' a << << b '将a中的位沿左方向移动b量。 Shifting by 1 can be seen as a multiplication by 2. (This is actually how optimization can happen, as a shift operation is faster than multiplication, but most modern compilers take that into account.) The or-statement is ' a|b '. 移位1可以看作是2的乘法。(实际上这是优化的方式,因为移位操作比乘法快,但是大多数现代编译器都考虑到了这一点。)or语句为' a | b ' 。 In or, if one of the two elements is 1, the result is 1. This is a standard method used in bitwise operations and actually all the bits inside a and b are or-ed. 在或中,如果两个元素之一为1,则结果为1。这是在按位运算中使用的标准方法,实际上ab所有位都是或运算的。 Eg a = 0010 1011, b = 1111 0000, a|b = 1111 1011. 例如a = 0010 1011,b = 1111 0000,a | b = 1111 1011。

Now back to the problem. 现在回到问题所在。 In your case sa.sin_addr.s_addr is 0 at the beginning, so when it's or-ed with 192, it adds the bit representation of 192 to the variable. 在您的情况下, sa.sin_addr.s_addr开头为0,因此在与192进行或运算时,会将192的位表示形式添加到变量中。 Then it is shifted by 8 bits, in order to free space for the next element in the ip address - each can have values between 0-255, which is exactly 8 bits. 然后将其移位8位,以便为IP地址中的下一个元素释放空间-每个元素的值都可以在0-255之间,也就是8位。 This is then repeated for the rest of the segments. 然后针对其余的片段重复此操作。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM