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

news2024/7/6 19:38:04

目录

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

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]; // 不使用
}

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

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

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

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

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

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

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

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

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

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

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

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

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

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

// 字节序转换:
unsigned short htons(unsigned short); // 主机字节序转换为网络字节序
unsigned short ntohs(unsigned short); // 网络字节序转换为主机字节序
unsigned long htonl(unsigned short); // 主机字节序转换为网络字节序
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 地址

// 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;
}

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

// 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;
}

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

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

// 网络地址的初始化
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部分代码案例

// 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;

}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/973065.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Svelte状态管理——svelte/store模块的使用

目录 前言 一、项目中使用示例 1. 创建全局状态 2. 在组件中使用全局状态 3. 便捷使用技巧$ 二、api介绍 1. writable 2. readable 3. derived 前言 在 Svelte 中&#xff0c;可以使用其自带的svelte/store模块来管理全局的应用程序状态&#xff0c;该模块导出用于创…

大出所料,9月1号前上线的小游戏却收到了补充备案材料的通知

引言 前阵子工信部发布了《工业和信息化部关于开展移动互联网应用程序备案工作的通知》&#xff0c;为此&#xff0c;微信公众平台ICP代备案管理系统提供新增备案、变更备案、注销备案等服务&#xff0c;协助开发者更好更方便地完成微信小程序备案&#xff0c;届时所有9月1号后…

HTML 标签讲解

HTML 标签讲解 HTML 语言结构根元素元数据元素主体根元素大纲元素文本内容语义化内联文本图像与多媒体编辑标识table表格内容表单内容table表单 HTML 语言结构 Markup &#xff08;标记、标签&#xff09;用来容纳和描述内容 严格意义上&#xff0c;标签是指开始标签&#xf…

PMC在制造企业中发挥哪些价值?

导 读 ( 文/ 2127 ) PMC(生产计划与物料控制)是制造企业运行的核心&#xff0c;PMC的好坏可以直接影响客户的需求交付、生产进行的顺利与否、库存资金的占用、企业效率的提升等&#xff0c;在制造企业中起着关键的作用。它负责将生产计划转化为实际的生产活动&#xff0c;并确保…

Mavan进阶之多模块(聚合)

文章目录 Maven 多模块&#xff08;聚合&#xff09;非父子关系的多模块项目 Maven 多模块&#xff08;聚合&#xff09; Maven 继承和聚合是 2 个独立的概念。工程与工程之间可能毫无关系&#xff0c;也可能是继承关系&#xff0c;也可能是聚合关系&#xff0c;也可能既是继承…

QT数据库,实现数据库增删改查

QT关于数据库的相关概念 QT将数据库分为三个层次&#xff1a; 数据库驱动层&#xff1a;QSqlDriver、QSqlDriverCreator、QSqlDriverCreatorBase、QSqlDriverPlugin sql接口层&#xff1a;QSqlDatabase、QSqlQuery、QSqlRecord、QSqlError 用户接口层&#xff1a;提供一些模…

算法训练 第一周

一、合并两个有序数组 本题给出了两个整数数组nums1和nums2&#xff0c;这两个数组均是非递减排列&#xff0c;要求我们将这两个数组合并成一个非递减排列的数组。题目中还要求我们把合并完的数组存储在nums1中&#xff0c;并且为了存储两个数组中全部的数据&#xff0c;nums1中…

创建具有管理员权限的快捷方式

参考 https://zhidao.baidu.com/question/86334639.html

【AI】机器学习——绪论

文章目录 1.1 机器学习概念1.1.1 定义统计机器学习与数据挖掘区别机器学习前提 1.1.2 术语1.1.3 特点以数据为研究对象目标方法——基于数据构建模型SML三要素SML步骤 1.2 分类1.2.1 参数化/非参数化方法1.2.2 按算法分类1.2.3 按模型分类概率模型非概率模型逻辑斯蒂回归 1.2.4…

CRM 自动化如何改善销售和客户服务?

许多 B2B 和 B2C 公司都使用 CRM 系统来组织业务流程&#xff0c;使复杂的任务更容易完成。企业可以使用 CRM 自动化来自动化工作流程&#xff0c;让团队有更多的时间来执行高价值的任务&#xff0c;而不是陷于一堆琐碎事情中。 什么是CRM自动化&#xff1f; CRM 自动化是指 C…

SD卡中了蠕虫病毒怎么办?清除病毒以及数据恢复方法

蠕虫病毒是近年来非常流行的病毒之一&#xff0c;它主要通过U盘、网络等途径进行传播。如果你的SD卡不幸感染了蠕虫病毒&#xff0c;可能会导致数据丢失。那么&#xff0c;如何进行数据恢复呢&#xff1f;同时&#xff0c;当SD卡中感染了蠕虫病毒时&#xff0c;我们应该采取什么…

Java“牵手”阿里巴巴商品详情数据,阿里巴巴商品详情API接口,阿里巴巴国际站API接口申请指南

阿里巴巴平台商品详情接口是开放平台提供的一种API接口&#xff0c;通过调用API接口&#xff0c;开发者可以获取阿里巴巴商品的标题、价格、库存、月销量、总销量、库存、详情描述、图片等详细信息 。 获取商品详情接口API是一种用于获取电商平台上商品详情数据的接口&#xf…

第8篇:ESP32连接超声波HC-SR04测距点亮LED无源喇叭播放声音

第1篇:Arduino与ESP32开发板的安装方法 第2篇:ESP32 helloworld第一个程序示范点亮板载LED 第3篇:vscode搭建esp32 arduino开发环境 第4篇:vscodeplatformio搭建esp32 arduino开发环境 第5篇:doit_esp32_devkit_v1使用pmw呼吸灯实验 第6篇:ESP32连接无源喇叭播放音乐《涛声…

【java基础复习】如何理解java中基本数据类型里的自动类型提升和强制类型转换?

自动类型提升强制类型转换注意事项 ❗感谢 &#x1f496; Java是一种强类型语言&#xff0c;这意味着在编写代码时&#xff0c;需要明确指定每个变量的数据类型。我们知道&#xff0c;java中有八大基本数据类型。分别是&#xff1a; 数据类型大小&#xff08;字节数&#xff0…

2024年java面试--多线程(4)

系列文章目录 2024年java面试&#xff08;一&#xff09;–spring篇2024年java面试&#xff08;二&#xff09;–spring篇2024年java面试&#xff08;三&#xff09;–spring篇2024年java面试&#xff08;四&#xff09;–spring篇2024年java面试–集合篇2024年java面试–redi…

BCSP-玄子Share-Java框基础_双系统Redis安装与基础语法

四、Redis 4.1 Redis 简介 Redis 是开源、高性能的key-value数据库&#xff0c;属于 NoSQL 数据库 NoSQL 数据库与关系型数据库 关系型数据库&#xff1a;采用关系模型来组织数据&#xff0c;主要用于存储格式化的数据结构NoSQL 数据库&#xff1a;泛指非关系型数据库&…

力扣|找出和所对应的两数的下标

从零开始刷力扣&#xff08;bushi 题目放在这&#xff1a; 给定一个整数数组 nums 和一个整数目标值 target&#xff0c;请你在该数组中找出和为目标值target的两个整数&#xff0c;并返回它们的数组下标。 你可以假设每种输入只会对应一个答案。但是&#xff0c;数组中同一…

数电发票开票接口

全电发票&#xff0c;也叫数电发票&#xff0c;全称为全面数字化的电子发票。数电发票是依托可信身份体系和电子发票服务平台&#xff1b;以去介质、去版式、标签化、要素化、授信制、赋码制为基本特征&#xff1b;覆盖全领域、全环节、全要素的全新发票。与纸质发票具有同等法…

tkinter控件样式

文章目录 以按钮为例共有参数动态属性 tkinter系列&#xff1a; GUI初步&#x1f48e;布局&#x1f48e;绑定变量&#x1f48e;绑定事件&#x1f48e;消息框&#x1f48e;文件对话框&#x1f48e;控件样式扫雷小游戏&#x1f48e;强行表白神器 以按钮为例 tkinter对控件的诸…

05-Redis

1、Redis为什么快&#xff1f; 1、纯内存操作 2、单线程可以省去多线程时CPU上下文会切换的时间 3、渐进式ReHash、缓存时间戳 数组需要扩容的时候&#xff0c;他会维护两张hash表&#xff0c;比如第一张的数组长度为6&#xff0c;另一张的数组长度为12&#xff0c;在set和g…