• 嵌入式养成计划-28-网络编程----网络编程基础


    六十四、网络编程基础

    1. 网络基础

    1.1 网络编程的概念

    1. 网络编程就是进程间通信,只不过多个进程间不一定在同一台主机上。
    2. 由于不在同一个主机上,不在同一个进程上就需要注意协议

    1.2 联网协议和层

    • 联网协议:定义如何在一个网络上传输信息的一组规则

    1.2.1 网络采用分层的思想

    1. 在计算机网络体系中,采用层次化的思想,将通信协议中必要的功能进行分层。
    2. 每一层都接收由它下一层所提供的特定服务,并且负责为自己的上一层提供特定的服务。
    3. 上下层之间进行交互所遵循的约定叫做『接口』。
    4. 同一层之间进行交互所遵循的约定叫做『协议』。
    5. 『接口』 即相邻两层之间交换位置的连接点,是上层使用下层服务的入口。
    6. 『协议』 即通信双方所做的一些约定,比如怎么开始通信、信息的格式与顺序、怎么结束通信等。
    • 分层的好处:
    1. 各层之间独立,每一层不需要知道下一层如何实现,而仅仅只需要知道该层通过层间的接口所提供的的服务。
    2. 稳定,当任何一层发生变化时,只要层间接口关系保持不变,则这层以上或以下层不受影响。
    3. 易于实现和维护(知道是什么功能,就到指定层去查找)
    4. 促进标准化工作

    1.2.2 OSI体系结构(重点!!)

    • ISO(国际标准化组织)制定了一个国际标准OSI(开放式通讯系统互联参考模型),对通讯系统进行了标准化。
    • 定义了7层模型
      在这里插入图片描述
      在这里插入图片描述
      顺口溜:(虽然貌似有点不顺)
      屋里(物理)数据要跑路,沿着链路上高速。—>物理层,数据链路层
      跑到高速没网络,数据传输靠不住。—>网络层,传输层
      掏出手机要叫人,一开会话嘟嘟嘟。—>会话层
      老铁表示要玩完,应用技术才懂路。—>表示层、应用层

    1.2.3 TCP/IP协议介绍

    • OSI模型是一个理想化的模型已经很少使用,没有完整的实现,但是模型本身非常通用。
    • TCP/IP协议 是Internet事实上的工业标准
      在这里插入图片描述
      在这里插入图片描述
    (1) 网络接口与物理层 也叫做网络访问层
    • 功能:包括ip地址与物理地址的映射(MAC),以及将上一层的ip报文封装层帧,转换成二进制比特流传输
    • MAC:物理地址,48bit全球唯一,网卡编号,网络设备的身份标识(cmd —>ipconfig/all),由厂商出厂后确定。
    • 改变网络环境后,IP地址变,MAC地址不变
    • 由电气电子工程协会IEEE定义。

    部分协议举例:

    • ARP/RARP 地址解析协议/逆向地址解析协议
    • ARP(Address Resolution Protocol):通过ip地址获取其对应的mac地址。
    • RARP(Reverse Address Resolution Protocol):通过mac地址获取其对应的ip地址。
    • PPP(Point to Point Protocol)协议:拨号协议(GPRS/3G/4G)

    MTU:最大传输单元:1500bytes
    MSS:最大报文长度:1460bytes

    (2) 网络层
    • 负责在主机之间的通讯中选择数据包传输的路径,即选择路由。

    ① IP协议(Internet Protocol)

    • ip协议根据数据包的目的ip地址来决定如何投递数据包。
    • 如果数据包不能直接投递给目标主机,那么ip协议就为他寻找下一个合适的下一跳路由器。
    • 路由器就是工作在网络层

    ② ICMP协议(Internet Control Management Protocol)

    • 英特网控制管理协议,ping检测网络就是用这个协议
    • 用于在IP主机、路由器之间传递控制消息
    • ping 命令 使用的就是这个协议

    ③ IGMP协议(Internet Group Management Protocol)

    • 英特网分组管理协议,组播,广播。
    (3) 传输层(重点!)
    • 负责提供应用程序之间通讯服务,这种服务又称之为端到端。
    • 传输层与网络层不同,传输层只关心通讯的 起始端 和 目的端,并不在乎数据包的传输中转过程。
    • TCP :(transmission control Protocol 传输控制协议):提供面向连接的,一对一的可靠数据传输协议。
    • UDP :(user datagram Protocol 用户数据报协议):提供无连接的,不可靠的尽力的传输协议,但是效率更高
    (4) 应用层
    • 负责处理应用程序的逻辑

    HTTP/HTTPS
    超文本传输协议,万维网数据通信的基础
    http:明文发送, https加密传输

    邮件协议
    收: POP3(post office protocol)邮局协议第三个版本
    从服务器接收右键,接收完后服务器就没有这个邮件了;

    发: SMTP(简单邮件传输协议)

    IMAP: 交互式邮件存储协议,与POP3类似的邮件访问标准协议之一。
    收取邮件后,服务器上邮件依然存在,如果删除、标记服务器也会做相应操作。

    FTP(FILE Transfer Protocol)
    文件传输协议,是用于在网络上进行文件传输的一套标准协议,使用TCP传输

    TFTP
    简单文件传输协议,适用于在网络上进行文件传输的一套标准协议,使用UDP传输

    DNS
    Telnet/ssh :远程登录

    1.2.4 网络封包与拆包

    在这里插入图片描述
    MTU :

    • Maximum Transmission Unit 最大传输单元
      • 物理接口(数据链路层)提供给上层(网络层(IP层))最大一次传输数据的大小。
      • 规定了数据链路层所能传送最大数据长度
      • 以太网为例,缺省MTU=1500字节,这是以太网接口对IP层的约束
      • 如果IP层<=1500字节需要发送,只需要一个IP包就可以
      • 如果IP层>1500字节需要发送,需要分片才能发送(分片:帧)

    MSS:

    • Maximum Segment Size 最大报文长度
      • TCP提交给IP层最大分段大小,指TCP报文所允许传送数据部分最大长度。
      • 不包含TCP头,MSS式TCP来限制应用层最大发送字节数。
      • 如果MTU=1500,则MSS = 1500-20(IP header)-20(TCP header) =1460字节
      • 如果应用有2000字节要发,需要2 Segment
      • 第一个TCP Segment = 1460 第二个TCP Segment = 540

    1.3 TCP和UDP协议的异同点(重点!!!)

    • 相同点: 都属于传输层协议
    • 不同点:
    1. TCP
    1. 是提供面向连接的,可靠的稳定的数据传输协议。
    2. 数据在传输过程中,无误,无丢失,无失序,无重复到达的通信。
    	1.1 每一个数据包都会编上一个编号,该编号称之为序列号(seq),且每一个数据包都需要一个正确的应答包应答
    	1.2 应答包:应答数据包,且通知对方下一次从哪个包开始发送(应答号:ack)。
    3. 超时重传机制。
    3. 传输效率低,耗费资源多。
    4. 在数据链路层限制数据包大小(46~1500bytes),超出部分分帧发送。
    5. 数据的收发是不同步的,会粘包(不存在数据边界)
    	5.1 粘包:为了提高效率,将多个足够小,且发送间隔极短的数据包合成一个包发送,该现象称之为粘包现象,该算法称之为Nagle算法。
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    适用场景: 适用于对传输质量要求比较高,传输大量数据的通信,在需要可靠数据传输的场合,通常使用TCP协议。
    例如: 网上购物付钱的时候,装备购买,账户密码登录的时候
    在这里插入图片描述

    1. UDP
    1.是提供无连接的,不可靠的尽力的数据传输协议。
    2.数据在传输过程中有可能出现,错误,丢失,失序,重复到达的通信。
    3. 传输效率高
    4. 限制每次传输的大小(46~1500bytes),超出部分直接删除。
    5. 数据收发是同步的,不存在粘包现象(存在数据边界)
    
    • 1
    • 2
    • 3
    • 4
    • 5

    适用场景: 适用于对传输质量要求比较低,传输小尺寸数据的通信,给出应答比较困难的网络中使用。
    例如: 广播/组播 直播 语音视频电话,多人竞技类游戏。

    1.4 IP地址

    • IP地址是因特网中主机的标识,每个数据包都必须携带目的IP地址和源IP地址,路由器依靠此信息为数据包选择路由。
    • IP地址是路由器下发的。(自动,手动)

    1.4.1 IP地址的分类

    1. IPv4:占4个字节,采用32bit的无符号整数来存储IP地址。[0, 2^32-1],给你个2^32= 42.9亿
    	1.1 局域网:为了解决IP地址不够用的问题,让多台主机使用同一个广域网IP地址。
    	1.2 广域网:与外界通信的网络环境。
    	1.3 每一个IP地址都可以下发一个局域网。
    
    2. IPv6:占16个字节,采用128bit的无符号整数来存储IP地址。[0, 2^128-1]2.1 容量足够多,能够给地球上的每一粒沙子都分配一个IP地址。
    	2.2 IPv4往IPv6过渡的阶段还未完成。IPv4和IPv6尚不兼容。
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    桥接模式和net模式的区别?
    桥接模式:windows和ubuntu是兄弟关系,连接同一个路由器
    net模式:windows当做路由器,下发一个网络给ubuntu
    
    • 1
    • 2
    • 3

    在这里插入图片描述

    1.4.2 IP地址划分

    • 由于IP地址基数比较大,所以为了提高寻径效率,则将IP地址划分成二级IP地址;

      • 二级IP地址 = 网络号 + 主机号
      • 网络号: 确定计算机从属的物理网络地址(确定是哪个村子的)
      • 主机号: 确定网络号后,用主机号标识该网络号中的所有主机。(确定是哪个村子后,在村子中找到设备的编号)
        在这里插入图片描述

      注意:

      • ABC类为基本类,可以分配给主机使用,且只有ABC类可以分配给主机使用
      • D类:不表示网络,用于特殊用途:组播,多播组
      • E类:保留,或者实验室使用。

    1.4.3 点分十进制

    • 使用点分十进制是为了方便记忆。
    • 将32位IP地址的二进制数,以8bit为一组,用十进制表示,利用点分割
    IP地址范围网络号个数主机号个数
    A类地址0.0.0.0~127.255.255.2552^7(网络号)2^24(主机号)大型网络
    B类地址128.0.0.0~191.255.255.2552^142^16名地址网管中心
    C类地址192.0.0.0~223.255.255.2552^212^8校园网或企业网、家庭网
    D类地址224.0.0.0~239.255.255.255组播地址
    E类地址240.0.0.0~255.255.255.255保留

    在ABC类中的特殊IP地址:不能分配给主机使用。(掐头去尾)

    • 网络地址:代表该网络的。由有效网络号 + 全是0的主机号组成
      如:
      110.1.2.3 —> A类IP地址 —>网络号是前8bit —>110.0.0.0
      129.1.2.3 —> B类IP地址 —>网络号是前16bit —>129.1.0.0
      200.1.2.3 —> C类IP地址 —>网络号是前24bit —>200.1.2.0
    • 广播地址:向该IP地址发送,代表给当前网络下的所有主机发送数据。由有效网络号 + 全是1的主机号组成
      如:
      110.1.2.3 —> A类IP地址 —> 网络号是前8bit —> 110.255.255.255
      129.1.2.3 —> B类IP地址 —> 网络号是前16bit —> 129.1.255.255
      200.1.2.3 —> C类IP地址 —> 网络号是前24bit —> 200.1.2.255

    1.4.4 子网掩码(重点!)

    • 二级IP地址划分后,主机的基数还是比较大,所以引入了另外一个概念:子网掩码。利用子网掩码可以将主机号进行再次划分:
      • IP = 网络号 + 子网号 + 主机号
      • 三级划分比较灵活,可以选择划分,也可以选择不划分,可以选择划分出2部分,4部分,8部分…2^n(n=0,1,2…)
        在这里插入图片描述
    (1) 子网掩码的概念
    • 子网掩码 :用于将一个大的IP网络中的主机号划分为若干小的子网络(常用)。
      1. 指明一个IP地址的哪些位表示的是主机所在的子网
      2. 指明哪些位表示的是主机的位掩码。
      3. 子网掩码不能单独使用,必须结合IP地址一起使用

    将若干个小网络组合成一个大的局域网(称之为超网技术)。

    • 子网掩码的格式:
      1. 与IP地址一样长的32位无符号整数,是由一串连续的1,后面跟着一串连续的0组成。
      2. 默认子网掩码的格式:
        1的个数与IP地址中网络号的个数一致
        0的个数与IP地址中主机号的个数一致。
    (2) 默认子网掩码
    A类IP地址的默认子网掩码:11111111 00000000 00000000 00000000 ===> 255.0.0.0
    B类IP地址的默认子网掩码:11111111 11111111 00000000 00000000 ===> 255.255.0.0
    C类IP地址的默认子网掩码:11111111 11111111 11111111 00000000 ===> 255.255.255.0
    子网掩码是对主机号做再次划分,D类E类没有主机号,所以没有子网掩码。
    
    C类IP地址的默认子网掩码:11111111 11111111 11111111 00000000 ===> 255.255.255.0
                           11111111 11111111 11111111 10000000 ===> 255.255.255.128
                           11111111 11111111 11111111 11000000 ===> 255.255.255.192
                           11111111 11111111 11111111 11100000 ===> 255.255.255.224
                           
                           11111111 11111111 11111111 00000011 ===> 1不连续错误的!!!
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    (3) 格式用法:IP & 子网掩码=子网网段
    (1) 1个子网网段
    192.168.125.229 & 255.255.255.0
    11000000 10101000 01111101 11100101 ===> 192.168.125.229
    11111111 11111111 11111111 00000000 ===> 255.255.255.0
    ------------------------------------------------------------------------------
    11000000 10101000 01111101 00000000 ===> 192.168.125.0  子网网段
    即192.168.125.229属于192.168.125.0该子网网段。
    在00000000-11111111该范围内的主机号,&255.255.255.0这个子网掩码,得到的结果均为192.168.125.0  子网网段。
    即0~255这个范围内的主机号,均为192.168.125.0  子网网段。
    所以没有划分出新的子网,所有主机号都在192.168.125.0  子网网段内。
    
    该子网网段可以写作:192.168.125.0/24 (24代表该子网网段是通过有241的子网掩码得到)。
    这个子网网段内的主机号是多少个 2^8= 256个。
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    (2) 2个子网网段
    192.168.125.229 & 255.255.255.128
    11000000 10101000 01111101 1 1100101 ===> 192.168.125.229
    11111111 11111111 11111111 1 0000000 ===> 255.255.255.128
    ----------------------------------------------------
    11000000 10101000 01111101 1 0000000 ===> 192.168.125.128  子网网段
    范围:如下范围的主机号[128, 255]& 255.255.255.128得到的结果均为192.168.125.128/25  子网网段。
    11000000 10101000 01111101 1 0000000 ===> 192.168.125.128
    11000000 10101000 01111101 1 1111111 ===> 192.168.125.255
    
    192.168.125.127 & 255.255.255.128
    11000000 10101000 01111101 0 1111111 ===> 192.168.125.127
    11111111 11111111 11111111 1 0000000 ===> 255.255.255.128
    ----------------------------------------------------
    11000000 10101000 01111101 0 0000000 ===> 192.168.125.0  子网网段
    范围:如下范围的主机号[0, 127]& 255.255.255.128得到的结果均为192.168.125.0/25  子网网段。
    11000000 10101000 01111101 0 0000000 ===> 192.168.125.0
    11000000 10101000 01111101 0 1111111 ===> 192.168.125.127
    
    综上所述,
    通过255.255.255.128可以将192.168.125.0该网络划分出2个子网
    每个子网中有2^7个主机号。
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    在这里插入图片描述
    特殊的IP地址:

    • 每个子网网段中,都有自己的子网网段地址。有效网络号+有效子网号+全是0的主机号 。 掐头
    • 每个子网网段中,都有自己的子网广播地址。 去尾
    • 总结:每个子网网段都需要掐头去尾

    1.4.5 网关

    • 网关是一个网络通向其他网络的IP地址
    • 目前家用路由器一般使用192.168.1.1和192.168.0.1作为LAN接口的地址,这个两个也是最常用的网关地址。
      在这里插入图片描述

    1.4.6 域名系统

    • 由于使用IP地址来指定计算机不方便人们记忆,且输入时候容易出错,用字符标识网络种计算机名称方法。

    • 这种命名方法就像每个人的名字,这就是域名(Domian Name)

    • 域名服务器(Domain Name server): 用来处理IP地址和域名之间的转换。

    • 域名系统(Domain Name System,DNS): 域名翻译成IP地址的软件

    • 一个域名,可以绑定多个ip

    域名结构

    • 例如域名 www.baidu.com.cn 从右向左看
      cn为高级域名,也叫一级域名,它通常分配给主干节点,取值为国家名,cn代表中国
      com为网络名,属于二级域名,它通常表示组织或部门
      中国互联网二级域名共40个,edu表示教育部门,com表示商业部门,gov表示政府,军队mil等等
      baidu为机构名,在此为三级域名,表示百度
      www:万维网 world wide web,也叫环球信息网,是一种特殊的信息结构框架。

    1.4.7 端口号

    • 为了区分一台主机收到的数据包交给哪个进程处理,使用端口号来区分。程序启动后将端口号和进程绑定在一起。
    • 网络里面的通讯是由 IP地址+端口号 来决定
    • 端口号存储在 2个字节 无符号整数中 (unsigned short int)。[1, 65535]
    • 常见的端口号:
    1~1023  端口我们编程时候不要使用,是那些 系统/规定 应用程序占了
    	TCP 21端口:FTP文件传输服务
    	TCP 23端口:TELNET终端仿真服务
    	TCP 25端口:SMTP简单邮件传输服务
    	TCP 110端口:POP3邮局协议版本3
    	TCP 80端口:HTTP超文本传输服务
    	TCP 443端口:HTTPS加密超文本传输服务
    	UDP 53端口:DNS域名解析服务
    	UDP 69端口:TFTP文件传输服务
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 可以使用的:1024~49151,就是我们平时编写服务器使用的端口号
    • 临时端口号:49152~65535,这部分是客户端运行时候动态选择的

    TCP和UDP的端口号是相互独立的: 有时TCP和UDP用到了同一个端口,也是能用的

    2. 跨主机传输

    2.1 字节序(重点!)

    2.1.1 字节序的概念

    1. 字节序是不同类型CPU主机,内存存储 多字节整数 序列的方式。
      1. char 字符串 float double均没有字节序的说法
      2. short int long long long有字节序的说法
    2. 小端字节序:低字节存储在低地址上,高字节存储在高地址上。
    3. 大端字节序:低字节存储在高地址上,高字节存储在低地址上。

    首地址都是低地址,数据的读取都是从低地址往高地址读取,经过大小端转换后得出结果。
    在这里插入图片描述

    2.1.2 本地字节序与网络字节序

    本地字节数:主机字节序(Host Byte Order) HBO
    网络字节序(Network Byte Order) NBO,网络字节序规定使用大端字节序。
    在跨主机传输过程中,需要使用统一的字节序,即网络字节序,避免兼容性问题。

    2.1.3 字节序转换函数

    2.1.3.1 htons htonl 主机字节序–>网络字节序

    头文件:
           #include uint32_t htonl(uint32_t hostlong);
           uint16_t htons(uint16_t hostshort);
    参数:
        指定要转换成网络字节序的整型:分别是32bit和16bit;
    返回值:
        成功,返回转换后网络字节序的整型​
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    示例:

    #include 
    #include int main(int argc, const char *argv[])
    {
        unsigned int a = 0x87654321;
        printf("%#x\n", a);             //0x87654321
        printf("%#x\n", htonl(a));      //0x21436587printf("%#x\n", htons(a));      //0x2143                 
        
        return 0;
    }   
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    2.1.3.2 ntohs ntohl 网络字节序---->主机字节序

    头文件:
           #include 
    原型:
           uint32_t ntohl(uint32_t netlong);
           uint16_t ntohs(uint16_t netshort);
    参数:
        uint32_t hostlong:32位网络字节序整型;
        uint16_t hostshort:16位网络字节序整型;
    ​
    返回值:
        成功,返回转换成主机字节序的整型;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    2.1.4 结构体对齐

    • 编译器会对结构体进行对齐,加速CPU取值周期,由于数据对齐也是与操作系统相关,不同的主机如果使用不同的对齐方式,会导致数据无法解析。
    • 所以网络传输结构体的时候需要取消结构体对齐;

    例如:

    #include #pragma pack(1)         //设置默认对齐系数 :()中的参数只能填2^n (n=0,1,2,3,4,5......)  typedef struct
    {
        char a;     //1
        int b;      //4
        int d;      //4
    }_A;#pragma pack()      //重置默认对其系数,重新置为8typedef struct
    {
        char a;     //1
        int b;      //4
        int d;      //4
    } __attribute__((packed))  B;       //取消结构体对齐
    ​
    ​
    typedef struct
    {   
        char a;     //1
                    //3
        int b;      //4
        int d;      //4
    }_C;int main(int argc, const char *argv[])
    {   
        printf("%ld\n", sizeof(_A));    //9
        printf("%ld\n", sizeof(_B));    //9
        printf("%ld\n", sizeof(_C));    //12return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38

    2.1.5 类型长度

    • 因为涉及到跨平台,不同平台会有不同的字长
    • int long int不同操作系统这两个数据类型所占的字节数可能是不一样的
    • 解决方式:可以通过通用类型:uint8_t uint16_t uint32_t
    #include typedef struct
    {
        uint8_t a;      //1
        uint32_t b;      //4
        uint16_t d;      //2
    }_A;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    2.2 IP转换

    • 由于IP地址本质上是一个4个字节的无符号整数,所以在跨主机传输中也有字节序的概念。
    • 所以需要将IP地址转换成网络字节序。
    • “192.168.8.189” ---->本机字节序的整型 0xC0A808BD---->网络字节序0xBD08A8C0
    • “192.168.31.42”----> 0xC0A81F2A ---->0x2A1FA8C0

    2.2.1 点分十进制—>网络字节序

    2.2.1.1 inet_aton

    • 只能转换IPv4
    头文件:
           #include 
           #include 
           #include 
    原型:
           int inet_aton(const char *cp, struct in_addr *inp);
    参数:
        char *cp:源IP地址的点分十进制字符串,例如 “192.168.1.10;
        struct in_addr *inp:存储转换成网络字节序的IP;
               typedef uint32_t in_addr_t;
               struct in_addr {
                   in_addr_t s_addr;
               };
    返回值:
        成功,返回非0;
        失败,返回0;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    例子:

     #define IP  "192.168.1.10"      //0xC0A8010A
     int main(int argc, const char *argv[])
     {
         struct in_addr inp;
     
         if(inet_aton(IP, &inp) == 0)
         {
             printf("转换失败\n");
             return -1;
         }
     
         printf("%#X\n", inp.s_addr);    //0X0A01A8C0
                                                               
         return 0;
     }                                                          
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    2.2.1.2 inet_pton

    • 既可以转IPv4也能处理IPv6
    头文件:
           #include 
    原型:
           int inet_pton(int af, const char *src, void *dst);
    参数:
        int af:协议族
                AF_INET         IPV4
                AF_INET6        IPV6
         char *src:指定要转换成网络字节序的点分十进制字符串;
         void* dst
               typedef uint32_t in_addr_t;
               struct in_addr {
                   in_addr_t s_addr;
               };
    ​
                af == AF_INETa;
                struct in6_addr
                {
                }
    返回值:
        成功,返回1;
        失败,返回0或者-1,更新errno;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    例子:

    #define IP "192.168.1.3" //0xC0A80103 --> 0x301A8C0 struct in_addr inp;
    inet_pton(AF_INET, IP, &inp);
    printf("%#X\n", inp.s_addr);        //0x301A8C0 
    
    • 1
    • 2
    • 3
    • 4
    • 5

    2.2.1.3 inet_addr

    • 最常用

    • 只能转换IPv4

      头文件:
      	#include 
      	#include 
      	#include 
      原型:
      	uint32_t inet_addr(const char *cp);
      参数:
      	char *cp:源IP地址的点分十进制字符串,例如 “192.168.1.10;
      返回值:
      	成功,返回转换后的网络字节序IP地址;
      	typedef uint32_t in_addr_t;
      	​
      	失败,返回INADDR_NONE (usually -1);
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13

    例子:

    printf("%#X\n", inet_addr(IP));
    
    • 1

    2.2.2 网络字节序—>点分十进制

    2.2.2.1 inet_ntoa 常用

    • 只能转换IPv4;
    头文件:
           #include 
           #include 
           #include 
    原型:
           char *inet_ntoa(struct in_addr in);
    参数:
        struct in_addr in:指定要转换成点分十进制字符串的IP地址;
               typedef uint32_t in_addr_t;
               struct in_addr {
                   in_addr_t s_addr;
               };
    返回值:
        成功,返回点分十进制字符串的首地址;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    printf("%s\n", inet_ntoa(inp));
    
    • 1

    2.2.2.2 inet_ntop

    头文件:
           #include 
    原型:
           const char *inet_ntop(int af, const void *src, char *dst, socklen_t size);
    参数:
        int af:协议族
                AF_INET         IPV4
                AF_INET6        IPV6
        void* src:存储要转换成点分十进制字符串的IP首地址;
               typedef uint32_t in_addr_t;
               struct in_addr {
                   in_addr_t s_addr;
               };
    ​
                af == AF_INETa;
                struct in6_addr
                {
                }
        char *dst:存储转换后的结果,点分十进制的首地址;
        socklen_t size:缓冲区大小,其实就是指定多大的空间用于转换IP;
    返回值:
        成功,返回字符串的首地址,就是dst;
        失败,返回NULL,更新errno;    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    例子:

    char ip[20];
    if(inet_ntop(AF_INET, &inp, ip, sizeof(ip)) == NULL)
    {
    	perror("ient_ntop");
    	return -1;                                            
    }
    printf("%s\n", ip);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
  • 相关阅读:
    【毕业设计源码】基于JAVA的企业人事管理系统
    Shell脚本速查手册
    【Java面试】Redis存在线程安全问题吗?为什么?
    go调用 c++中数组指针相关
    如何通过财务体系建设,助推企业数智化转型?
    基于springboot小区团购管理系统
    【Nginx】Linux keepalived+nginx实现主从模式
    leetcode 1423. Maximum Points You Can Obtain from Cards(从牌中能得到的最大点数和)
    【Oracle】Oracle系列之十五--存储过程
    数据查询优化技术方案
  • 原文地址:https://blog.csdn.net/qq_52625576/article/details/132992281