"TCP/IP Network Programming" Reading Notes--Address Family and Data Sequence

Table of contents

1--IP address and port number

2--Representation of address information

3--Network byte order and address conversion

4--Initialization and allocation of network addresses

5--Windows partial code case


1--IP address and port number

There are two types of IP addresses:

        ① IPv4 means  -byte address family;

        ② IPv6 means  16  -byte address family;

The 4-byte IP address of IPv4 standard is divided into network address and host address , generally divided into A, B, C, D and E types:

        ① Class A: network ID (1 byte), host ID (3 bytes); first byte range: 0~127;

        ② Type B: network ID (2 bytes), host ID (2 bytes); first byte range: 128~191;

        ③ Type C: network ID (3 bytes), host ID (1 byte); first byte range: 192~223;

        ④ Type D: Network ID (4 bytes));

        ⑤ Class E: reserved;

The port number:

        Port numbers are used to distinguish Sockets (different applications) , and one port number cannot be assigned to different Sockets;

        The port number is composed of 16 bits, and the range of assignable port numbers is 0-65535 , of which 0-1023 is a well -known port for allocation to specific applications;

        TCP Socket and UDP Socket will not share the port number, so duplication is allowed;

2--Representation of address information

The structure sockaddr_in representing the IPv4 address :

struct sockaddr_in{
    sa_family_t sin_family; // 地址族
    uint16_t sin_port; // 16位 TCP/UDP 端口号
    struct in_addr sin_addr; // 32位IP地址
    char sin_zero[8]; // 不使用
}

The member sin_family represents the address family . Commonly used address families are as follows:

        ① AF_INET indicates the address family used in the IPv4 network protocol;

        ② AF_INET6 indicates the address family used in the IPv6 network protocol;

        ③ AF_LOCAL indicates the UNIX address family used in local communication

// 一般用法:
SOCKADDR_IN servAddr;
servAddr.sin_family = AF_INET;

        The second parameter of the bind() function expects to obtain the sockaddr structure type, which is defined as follows:

struct sockaddr{
    sa_family_t sin_family; // 地址族
    char sa_data[14]; // 地址信息(包含IP地址和端口号,其它部分填充为0)
}

        Generally, the sockadd_in structure needs to be converted into a sockaddr structure variable, which will be input into the bind() function:

        bind(serv_sock, (struct sockaddr*) &serv_addr , sizeof(serv_addr)); where serv_addr is the sockadd_in structure variable;

3--Network byte order and address conversion

There are two ways for the CPU to save data to memory:

        ①Big -endian : the high-order byte is stored in the low-order address;

        ②Little endian : the high-order byte is stored in the high-order address;

        When transmitting data through the network, it is agreed to adopt a unified network byte order, that is, unified as big-endian ; first convert the data array into network byte order (big-endian), and then transmit it. After the receiver receives the data Parse the network byte order into a data method that conforms to its own CPU;

// 字节序转换:
unsigned short htons(unsigned short); // 主机字节序转换为网络字节序
unsigned short ntohs(unsigned short); // 网络字节序转换为主机字节序
unsigned long htonl(unsigned short); // 主机字节序转换为网络字节序
unsigned long ntohl(unsigned short); // 网络字节序转换为主机字节序

        h means host ( host ) byte order, n means network ( network ) byte order; s means short (short type occupies 2 bytes in linux), l means long (long type in linux occupies 4 bytes);

4--Initialization and allocation of network addresses

        The inet_addr() function converts the IP address in string form into 32-bit integer data , and completes the network byte order conversion while converting the type ;

        The inet_addr() function can also detect invalid IP addresses ;

// inet_addr.c
// gcc inet_addr.c -o inet_addr
// ./inet_addr

#include <stdio.h>
#include <arpa/inet.h>

int main(int argc, char *argv[]){
    char *arrd1 = "1.2.3.4"; 
    char *arrd2 = "1.2.3.256";

    unsigned long conv_addr = inet_addr(arrd1);
    if(conv_addr == INADDR_NONE){
        printf("Error occured \n");
    }
    else{
        printf("Network ordered integer addr: %#lx \n", conv_addr);
    }

    conv_addr = inet_addr(arrd2);
    if(conv_addr == INADDR_NONE){
        printf("Error occured \n");
    }
    else{
        printf("Network ordered integer addr: %#lx \n", conv_addr);
    }

    return 0;
}

        The inet_aton() function has the same function as inet_addr(), but it will , so it is used more frequently;

// inet_aton.c
// gcc inet_aton.c -o inet_aton
// ./inet_aton

#include <stdio.h>
#include <stdlib.h>
#include <arpa/inet.h>

void error_handling(char *message){
    fputs(message, stderr);
    fputc('\n', stderr);
    exit(1);
}

int main(int argc, char *argv[]){
    char *addr = "127.232.124.79";
    struct sockaddr_in addr_inet;

    if(!inet_aton(addr, &addr_inet.sin_addr)){
        error_handling("Conversion error");
    }
    else{
        printf("Network ordered integer addr: %#x \n", addr_inet.sin_addr.s_addr);
    }
    return 0;
}

        The inet_ntoa() function is the opposite of the function of the above two functions, it converts the network byte order integer IP address into a string form;

        After calling the inet_ntoa() function, you need to store the corresponding string information, otherwise it will be overwritten next time it is called;

// 网络地址的初始化
struct sockaddr_in addr;
char* serv_ip = "211.217.168.13"; // 声明 IP 地址字符串
char* serv_port = "9190"; // 声明端口号字符串
memset(&addr, 0, sizeof(addr)); // 结构体变量 addr 的所有成员初始化为 0
addr.sin_family = AF_INET; // 指定地址族
addr.sin_addr.s_addr = inet_addr(serv_ip); // 基于字符串的 IP 地址初始化
addr.sin_port = htons(atoi(serv_port)); // 基于字符串的端口号初始化

5--Windows partial code case

// gcc endian_conv_win.c -o endian_conv_win -lwsock32
// endian_conv_win

#include <stdio.h>
#include <winsock.h>

void ErrorHandling(char* message){
    fputs(message, stderr);
    fputc('\n', stderr);
    exit(1);
}

int main(int argc, char *argv[]){
    WSADATA wsaData;
    unsigned short host_port = 0x1234;
    unsigned short net_port;
    unsigned long host_addr = 0x12345678;
    unsigned long net_addr;

    if(WSAStartup(MAKEWORD(2, 2), &wsaData) != 0){
        ErrorHandling("WSAStartup() error!");
    }

    net_port = htons(host_port);
    net_addr = htonl(host_addr);

    printf("Host ordered port: %#x \n", host_port);
    printf("Network ordered port: %#x \n", net_port);
    printf("Host ordered address: %#lx \n", host_addr);
    printf("Network ordered address: %#lx \n", net_addr);
    WSACleanup();
    return 0;
}

// gcc inet_adrconv_win.c -o inet_adrconv_win -lwsock32
// inet_adrconv_win

#include <stdio.h>
#include <string.h>
#include <winsock2.h>

void ErrorHandling(char* message){
    fputs(message, stderr);
    fputc('\n', stderr);
    exit(1);
}

int main(int argc, char *argv[]){
    WSADATA wsaData;
    if(WSAStartup(MAKEWORD(2, 2), &wsaData) != 0){
        ErrorHandling("WSAStartup() error!");
    }

    // inet_addr 函数调用示例
    {
        char *addr = "127.212.124.78";
        unsigned long conv_addr = inet_addr(addr);
        if(conv_addr == INADDR_NONE){
            printf("Error occured! \n");
        }
        else{
            printf("Network ordered integer addr: %xlx \n", conv_addr);
        }
    }

    // inet_ntoa 函数调用示例
    {
        struct sockaddr_in addr;
        char *strPtr;
        char strArr[20];

        addr.sin_addr.s_addr = htonl(0x1020304);
        strPtr = inet_ntoa(addr.sin_addr);
        strcpy(strArr, strPtr);
        printf("Dotted-Decimal notation3 %s \n", strArr);
    }

    WSACleanup();
    return 0;

}

Guess you like

Origin blog.csdn.net/weixin_43863869/article/details/132671109