• 《TCP/IP网络编程》阅读笔记--地址族和数据序列


    目录

    1--IP地址和端口号

    2--地址信息的表示

    3--网络字节序与地址变换

    4--网络地址的初始化与分配

    5--Windows部分代码案例


    1--IP地址和端口号

    IP 地址分为两类:

            ① IPv4 表示 字节地址族;

            ② IPv6 表示 16 字节地址族;

    IPv4 标准的 4 字节 IP 地址分为网络地址主机地址,一般分为 A、B、C、D和 E 类型:

            ① A类:网络ID(1字节),主机ID(3字节);首字节范围:0~127;

            ② B类:网络ID(2字节),主机ID(2字节);首字节范围:128~191;

            ③ C类:网络ID(3字节),主机ID(1字节);首字节范围:192~223;

            ④ D类:网络ID(4字节));

            ⑤ E类:已被预约;

    端口号:

            端口号用于区分 Socket(不同的应用程序),不能将 1 个端口号分配给不同的 Socket;

            端口号由 16 位构成,可分配的端口号范围是 0-65535,其中 0-1023 是知名端口用于分配给特定的应用程序;

            TCP Socket 和 UDP Socket 不会共用端口号,因此允许重复;

    2--地址信息的表示

    表示 IPv4 地址的结构体 sockaddr_in

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

    成员 sin_family,表示地址族,常用的地址族如下:

            ① AF_INET 表示 IPv4 网络协议中使用的地址族;

            ② AF_INET6 表示 IPv6 网络协议中使用的地址族;

            ③ AF_LOCAL 表示本地通信中采用的 UNIX 的地址族

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

            bind() 函数第二个参数期望获得 sockaddr 结构体类型,其定义如下:

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

            一般需要将 sockadd_in 结构体强制转换为 sockaddr 结构体变量,将输入到 bind() 函数中:

            bind(serv_sock, (struct sockaddr*) &serv_addr, sizeof(serv_addr)); 其中 serv_addr 是sockadd_in结构体变量;

    3--网络字节序与地址变换

    CPU向内存保存数据的方式有两种:

            ① 大端序:高位字节存放到低位地址;

            ② 小端序:高位字节存放到高位地址;

            在通过网络传输数据时,约定采用统一的网络字节序方式,即统一为大端序;先把数据数组转化成网络字节序(大端序),再进行传输,接收方收到数据后将网络字节序解析为符合自己CPU的数据方式;

    1. // 字节序转换:
    2. unsigned short htons(unsigned short); // 主机字节序转换为网络字节序
    3. unsigned short ntohs(unsigned short); // 网络字节序转换为主机字节序
    4. unsigned long htonl(unsigned short); // 主机字节序转换为网络字节序
    5. unsigned long ntohl(unsigned short); // 网络字节序转换为主机字节序

            h 表示主机(host)字节序,n 表示网络(network)字节序;s 表示 short(linux 中 short 类型占用 2 字节),l 表示 long(linux 中 long 类型占用 4 字节);

    4--网络地址的初始化与分配

            inet_addr() 函数会将字符串形式的 IP 地址转换为 32 位整数型数据,并在转换类型的同时完成网络字节序的转换

            inet_addr() 函数还可以检测无效的 IP 地址

    1. // inet_addr.c
    2. // gcc inet_addr.c -o inet_addr
    3. // ./inet_addr
    4. #include
    5. #include
    6. int main(int argc, char *argv[]){
    7. char *arrd1 = "1.2.3.4";
    8. char *arrd2 = "1.2.3.256";
    9. unsigned long conv_addr = inet_addr(arrd1);
    10. if(conv_addr == INADDR_NONE){
    11. printf("Error occured \n");
    12. }
    13. else{
    14. printf("Network ordered integer addr: %#lx \n", conv_addr);
    15. }
    16. conv_addr = inet_addr(arrd2);
    17. if(conv_addr == INADDR_NONE){
    18. printf("Error occured \n");
    19. }
    20. else{
    21. printf("Network ordered integer addr: %#lx \n", conv_addr);
    22. }
    23. return 0;
    24. }

            inet_aton() 函数的功能与 inet_addr() 相同,但其在调用过程中会将转换后的 IP 地址信息代入到 sockaddr_in 结构体中,因此使用频率更高;

    1. // inet_aton.c
    2. // gcc inet_aton.c -o inet_aton
    3. // ./inet_aton
    4. #include
    5. #include
    6. #include
    7. void error_handling(char *message){
    8. fputs(message, stderr);
    9. fputc('\n', stderr);
    10. exit(1);
    11. }
    12. int main(int argc, char *argv[]){
    13. char *addr = "127.232.124.79";
    14. struct sockaddr_in addr_inet;
    15. if(!inet_aton(addr, &addr_inet.sin_addr)){
    16. error_handling("Conversion error");
    17. }
    18. else{
    19. printf("Network ordered integer addr: %#x \n", addr_inet.sin_addr.s_addr);
    20. }
    21. return 0;
    22. }

            inet_ntoa() 函数与上述两个函数的功能相反,其将网络字节序整数型 IP 地址转换为字符串形式;

            调用 inet_ntoa() 函数后,需要存储对应的字符串信息,否则下次被调用会被覆盖;

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

    5--Windows部分代码案例

    1. // gcc endian_conv_win.c -o endian_conv_win -lwsock32
    2. // endian_conv_win
    3. #include
    4. #include
    5. void ErrorHandling(char* message){
    6. fputs(message, stderr);
    7. fputc('\n', stderr);
    8. exit(1);
    9. }
    10. int main(int argc, char *argv[]){
    11. WSADATA wsaData;
    12. unsigned short host_port = 0x1234;
    13. unsigned short net_port;
    14. unsigned long host_addr = 0x12345678;
    15. unsigned long net_addr;
    16. if(WSAStartup(MAKEWORD(2, 2), &wsaData) != 0){
    17. ErrorHandling("WSAStartup() error!");
    18. }
    19. net_port = htons(host_port);
    20. net_addr = htonl(host_addr);
    21. printf("Host ordered port: %#x \n", host_port);
    22. printf("Network ordered port: %#x \n", net_port);
    23. printf("Host ordered address: %#lx \n", host_addr);
    24. printf("Network ordered address: %#lx \n", net_addr);
    25. WSACleanup();
    26. return 0;
    27. }

    1. // gcc inet_adrconv_win.c -o inet_adrconv_win -lwsock32
    2. // inet_adrconv_win
    3. #include
    4. #include
    5. #include
    6. void ErrorHandling(char* message){
    7. fputs(message, stderr);
    8. fputc('\n', stderr);
    9. exit(1);
    10. }
    11. int main(int argc, char *argv[]){
    12. WSADATA wsaData;
    13. if(WSAStartup(MAKEWORD(2, 2), &wsaData) != 0){
    14. ErrorHandling("WSAStartup() error!");
    15. }
    16. // inet_addr 函数调用示例
    17. {
    18. char *addr = "127.212.124.78";
    19. unsigned long conv_addr = inet_addr(addr);
    20. if(conv_addr == INADDR_NONE){
    21. printf("Error occured! \n");
    22. }
    23. else{
    24. printf("Network ordered integer addr: %xlx \n", conv_addr);
    25. }
    26. }
    27. // inet_ntoa 函数调用示例
    28. {
    29. struct sockaddr_in addr;
    30. char *strPtr;
    31. char strArr[20];
    32. addr.sin_addr.s_addr = htonl(0x1020304);
    33. strPtr = inet_ntoa(addr.sin_addr);
    34. strcpy(strArr, strPtr);
    35. printf("Dotted-Decimal notation3 %s \n", strArr);
    36. }
    37. WSACleanup();
    38. return 0;
    39. }

  • 相关阅读:
    计算机网络——数据链路层
    FL Studio21最新演示测试版本下载FL水果V21
    云端日历同步大师:iCloud让工作与生活井井有条
    阿里云张新涛:连接产业上下游,构建XR协作生态
    MySQL面试题大全(陆续更新)
    qt多线程编程,信号绑定成功,槽函数不响应问题排查处理及总结
    Matlab论文插图绘制模板第118期—进阶气泡图
    LangChain 开发LLM的框架
    一文了解Gin对Cookie的支持
    3D生成式AI模型、应用与工具大全
  • 原文地址:https://blog.csdn.net/weixin_43863869/article/details/132671109