简体   繁体   中英

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:

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. Can someone explain?

It is creating the binary representation for the 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 :

#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 :

struct in_addr {
    unsigned long s_addr; 
};

Now, usually, when we utilisize this s_addr, we write :

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() 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.

Now we clearly know that the unsigned long s_addr contains the binary form of the ip in network byte order .

You don't need to shift the ip youreslf, instead just use inet_aton() and inet_ntoa() for manipulating ip adresses.

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. 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 '. 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. Eg 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. 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. This is then repeated for the rest of the segments.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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