1. 网络编程基础

以下内容来自与B站up上传的视频,跟着学习敲的,图片引用了视频中的。

网络协议

TCP/IP:网络之间的通信,狭义的认识就是TCP/IP这两种协议,广义的认识,TCP/IP是IP协议的通信过程中,使用到的协议族的统称。

TCP/IP:是以传输控制协议(TCP)和国际协议(IP)为核心,包含了其它重要协议,相互合作,各司其职,共同保障网络通信的顺畅进行。

网络层:IP协议,IPv4地址,点分十进制,每台接入互联的设备都有一个独一无二的IP地址,

1.网络编程基础

1.网络通信

通信双方,必须满足两个条件,才能通信:

  • 物理媒介(物理层面)

    任何信息的传输都需要物理媒介

    eg:网线、光纤、空气

  • 协议(软件层面)

    从应用的角度,协议理解为通信的规则,是数据传输和解释的规则

    eg:假设,A B双方想要传输文件,可以约定双方规则

    复制代码
    第一次:传输文件名,接收方接收到文件名后,应答ok给传输方
    第二次:发送文件大小,接收方接收到文件大小后,应答ok给传输方
    第三次:发送文件数据,接收方接收到文件大小多个字节后,应答ok给传输方

2.网络协议层次模型

层次:把不同的功能封装成不同的模块

为什么要分层?

把庞大的问题划分为若干个较小的局部文件,计算机网络功能非常复杂,采用分层结构将诸多功能合理的划分在不同层次,对等层之间指定协议,以实现功能。

每一层都简历在它的下层之上,像它的上一层提供一定的服务,并且把怎么实现这个服务的细节对上层屏蔽。

常见的网络层次模型:OSI七层模型 和TCP/IP四层模型(应用更广泛)

2.1OSI七层模型

​ OSI七层模型是ISO国际化标准组织指定,它针对广域网通信(也就是不同网络之间通信)设计的,将网络通信的功能划分为七个层次。

2.1.1物理层

​ 通过光信号和电信号传输数据, 它负责管理计算机通信设备和网络媒体之间的互通,实现相邻节点之间比特(0/1)的传输。

​ 物理层确保原始的数据可以在各种物理传输媒体上传输

​ 典型设备:网线、光纤、集线器(hub,集线器连接的网络本质上就是一个广播域)、中继器

2.1.2数据链路层

​ 在同一局域网内实现可靠的点对点数据传输 ,负责数据包的封帧及MAC寻址

​ 互联设备之间传输和识别帧,对数据进行封装成数据帧并传递并进行错误的检测;

​ 典型设备:交换机(switch)

​ MAC地址:是数据链路层的核心标识符,用于在同一物理网络内唯一标识设备,MAC地址就是唯一硬件身份,由设备网卡出厂时固化,全球范围内唯一。

​ MAC地址由48位(6个字节)组成,通常是16进制表示,前24是制造商编号,后面24位由制造商自行分配

2.1.3 网络层

互联网由无数个子网络组成的,比如中国和意大利肯定不在同一个子网络上,没有办法通过直接查找MAC地址来进行通信,网络层引入了一套新的地址,使得能够区分不同的计算机是否属于同一个子网络,这套地址称为网络地址,也称为IP地址。

一般通信的主机不是直接链接的,但是在物理层面连通的(中见经过多个中间节点(路由器/交换机/中继器等));

网络层负责将数据传输到目标地址,这一层主要负责IP地址寻址和路由选择,把分组(又称为数据报)从源点转发到目标节点。

典型设备:路由器(router)

该层协议:IP因特网协议:定义了数据包的格式及路由规则。

2.1.4 传输层

每台主机上会运行多个进程,因此我们还需要确保数据到底是发送到网络设备的哪一个进程,那就需要传输层,提供端到端(进程到进程之间的通信,同一个主机上不同的网络应用通过端口号区分)的数据传输,单位是数据报文

这一层的目的确保数据可靠的,有序的传输,并且可以提供端到端的机制。

2.1.4.1 TCP协议

TCP:transport control protocol,传输控制协议,是一种面向连接、面向字节流 的传输层协议,它能够提供可靠通信, 数据无误、数据无丢失、数据无失序、数据无重复到达(建立三次握手、四次挥手、重发机制),数据单元(段)

面向连接:双方在通信之间必须要先建立连接(三次握手),确认连接之后才能开始进行通信。

面向字节流:指TCP对待传输数据的方式将其视为连续的、无结构的、无边界的字节序列,而非独立的报文(UDP),TCP眼中只有字节流,没有数据包,将数据流切分段,用序列号为每个字节定位。

复制代码
eg:发送了消息1"hello"    发送了消息2"world"
    TCP只保证数据按照你的字节顺序发送出去:h e l l o w o r l d
    接收方接收到的数据有可能是两条消息"hello" "world"
    接收方接收到的数据可能是两条消息"helloworld"
    接收方接收到的数据可能是两条消息"hellowo""rld"
    ...
TCP粘包
2.1.4.2 解决TCP粘包的问题
  1. 固定长度:每条消息都严格一样长(比如每条消息都是20个字节),接收方只要直到读取了20个字节就是一条消息。

    缺点:不灵活,浪费空间。

  2. 分隔符:在每条消息的结尾加上一个特殊的,不会在正常内容中出现的字符(eg: \r\n),接收方只要持续读取,当读到了分隔符的位置,就知道一条消息结束了。

  3. 长度前缀(最常用、最推荐):在每条实际消息之间,先添加一个固定长度的消息头,先发送4字节的长度,在发送实际的消息。

    复制代码
    eg:
        "hello"
        0x05 h e l l o
        "kkkk"
        0x04 k k k k
2.1.4.3 TCP首部

TCP如何来实现数据无误、数据无丢失、数据无失序、数据无重复到达,通过解析TCP头部信息探究。

截图1:07:26s

功能
源端口号(2字节) 表示发送方应用程序使用的端口号 (端口唯一标识网络应用)
目的端口号(2字节) 表示接收方应用程序使用的端口号
序列号(SEQ)(4字节) 用于标识发送数据的序列号,用于对数据进行排序和重组,每个TCP数据段都有一个唯一的序列号,标识当前数据包第一个字节在数据流中的位置
(TCP using cumulative ack) 确认号(4字节) 如果设置了ACK标志位,则该字段有效,用于确认接收到的数据,表示接收方期望下一个接收到的字节的序列号
(TCP using cumulative ACK) 数据偏移(4 bits) 该字段表示TCP首部长度,是一个4位的二进制数,指明TCP首部中包含多少个32位的字,一般固定位5。因此首部长度为20字节
保留(6 bits) 未使用,保留为0
URG标志(1 bit) 紧急指针(urgent pointer) 是否有效的标志,如果设置了URG标志,则表面紧急指针指定的数据会优先传递处理
ACK标志(1 bit) 确认标识位,用于确认接收到的TCP报文。如果设置了改标志,则在ACK字段中确认号有效;否则,确认号无效,可以忽略ACK字段
PSH标志(1 bit) 推送标识位,用于告诉接收方应该尽早将数据交给上层应用程序处理
RST标志(1 bit) 复位标识位,用于终止残留的连接,相当于发送一个规范的非法序列,不需要对方回应设计的
SYN标志(1 bit) 同步标识位,用于发起一个新的TCP连接。在三次握手过程中用来建立和确认双方通信的初始序列号(ISN)
FIN标志(1 bit) 结束标识位,用于释放一个TCP连接。当此标志置位后,表明发送方已经没有数据需要传输了,等待接收方的确认即可安全关闭连接
窗口大小(2字节) 用于控制数据流量和避免缓冲区溢出的标志。发送方和接收方通过该字段进行流量控制
校验和(2字节) 用于检测TCP首部和TCP数据是否出现错误或被改动,并确保数据是由正确的发送方发出的
紧急指针(2字节) 如果设置了URG标志,则改字段表面紧急数据在整个数据中的位置
可选项 可选字段,长度不定,在必要时包含一些附加信息,如时间戳、SACK等。可以使用NOP字段填充必须为32位的限制
2.1.4.4三次握手
复制代码
1)SYN:同步标志位,发起新的连接请求,SYN=1,标识进行一个连接请求
2)ACK:认为,ACK=1,确认有效
            ACK=0,确认无效
3)FIN:断开一个连接
4)seq:序号,标识从计算机A发送数据到计算机B的字节编号,当前数据包的第一个字节在数据流中的位置(字节序)
5)ack:ack=已经接收到的最后字节的编号(seq字节序 + 负载数据长度) + 1
       ack,确认号,确认已经收到之前的包,期望下次收到的包序号为 ack=已经接收到的最后字节的编号(seq字节序 + 负载数据长度) + 1

客户端 服务端

你好,我希望来建立连接

好的,我已经准备好了,可以开始建立连接

好的,马上来连接你

===> 双方建立连接成功

第一次握手:

复制代码
客户端主动希望与服务器建立连接,它将会发送一个特殊的TCP报文段
这个报文段的SYN=1 它会发送一个随机的初始序列号,seq=x 
这个报文段不携带应用层的数据 
客户端发送完SYN同步报文后,客户端进入SYN-SENT(同步已发送)状态,等待服务器的确认

第二次握手:

复制代码
服务器一直处于监听(LISTEN)状态,一旦监听状态下,有监听到来自客户端的SYN请求后,如果服务器同意连接的,回复客户端一个报文
SYN=1   ACK=1确认有效 seq=y ack=x+1(表示收到了序号为x的包,期望收到下一个为x+1的包)
这个报文同样不携带应用层数据
服务器发送完报文后,进入SYN-RCVD(同步已收到)状态

第三次握手:

复制代码
客户端收到服务器的报文后,再次向服务器发送一个确认报文
ACK=1 seq=x+1 ack=y+1(表示收到序号为y的包,期望下次收到为y+1的序号的包)
客户端发送完报文后,进入ESTABLISHED(连接已建立)状态    established
服务器收到这个报文后,进入到ESTABLISHED(连接已建立)状态
至此,三次握手完成,双向通信通道已经成功建立,双方都可以开始传输数据了
2.1.4.5 四次挥手

第一次挥手:

复制代码
客户端主动断开连接,希望关闭连接,它会发送一个报文段
FIN=1 seq=u
客户端发送完FIN报文后,进入FIN-WAIT-1(终止等待1)状态

第二次挥手:

复制代码
服务器收到客户端FIN报文后,直到客户端想要关闭连接了
服务器立即发送一个ACK确认报文,这个报文中ACK=1 ack=u+1 seq=v
服务器发送完ACK确认报文后,服务器进入到CLOSE-WAIT(关闭等待)状态,TCP处于半关闭状态(即客户端到服务器的通道已经关闭,客户端不能再发送数据,但是服务器还可以给客户端发送数据)

第三次挥手:

复制代码
服务器把所有的数据全部发送完后,服务器也会开始要完全关闭连接
也发送一个FIN报文,FIN=1 seq=w
服务器发送完FIN报文后,进入LAST-ACK(最后确认)状态,等待一个客户端的ACK报文

第四次挥手:

复制代码
客户端收到服务器的FIN报文后
它会像服务器发送一个ACK报文,ACK=1 ack=w+1
客户端发送完ACK后,进入TIME-WAIT状态
服务器接收到ACK后,进入CLOSED状态
2.1.4.6 UDP协议

UDP:user datagram protocol 用户数据报协议,面向无连接的,不可靠的协议,并且面向数据报的

面向无连接:在数据发送前,不需要建立连接

不可靠:数据传输的时候,不会有数据回复/重发(提高发送数据效率)

相对TCP而言,UDP没有那么复杂的机制来确保数据可靠,优点是效率高

"直播",实时应用

数据单元:数据报,独立报文

复制代码
eg:发送消息1”hello“ 发送消息2”world“
UDP将两个消息分别封装成独立的报文,因此接收方能够直接知道这是两条独立消息,UDP中不会存在粘包的问题
2.1.5 会话层

管理进程间的会话,建立建立,管理或者断开与应用程序之间的通信,组织和协调两个绘画之间的通信,并且对数据进行管理

数据单元:会话数据

eg:FTP下载终端后从哪个断点继续重传

2.1.6 表示层

把数据转换为能与接收者的系统格式兼容并适合传输的格式(eg:双方系统不一样的,双方通信编码不一样),主要是对发送/接收的数据进行加密解密,进行格式的转换,确保一个系统的应用程序发送的数据,能够被另外一个系统的应用程序识别。

数据单元:表示数据

2.1.7 应用层

提供为应用软件而设计的接口,以设置与另一个应用软件之间进行通信,应用层以报文为数据传输单位

eg:http http sftp SSH DNS等

http超文本传输协议 ftp文件传输协议 DNS域名解析协议 qq协议

2.2 TCP/IP四层模型

TCP/IP协议体系结构划分了四层,从高到低为:应用层、传输层、网络层和网络接口层,虽然只有四层,但是包含了OSI七层中所有的功能,也包括了局域网和广域网之间通信的全部功能,目前TCP/IP模型应用比较广泛,而OSI七层由于过于理想化,导致实际应用中较为复杂,所以没有称为主流的模型。

OSI七层模型 TCP/IP四层模型 对应网络协议 数据格式
应用层 应用层 HTTP、DNS、SMTP、FTP、TFTP、Telnet、SNMP、SSH等 报文
表示层
会话层
传输层 传输层 TCP、UDP
网络层 网络层 IP、ARP(IP->MAC)、RARP(MAC->IP)等 分组(数据报)
数据链路层 网络接口层 FDDI,Ethernet、Arpanet、PDN、SLIP、PPP
物理层 IEEE802、1A、IEEE802到IEEE802.11 比特

3.常见的网络相关设备

3.1集线器(hub)

  • 可以将多个节点连接起来,组成一个计算机网络,用于在物理层拓展以太网

  • 工作在物理层,只是带电信号的传输,仅处理电信号(比特流),无数据链路层的功能(不识别MAC地址)

  • 接收到某一个端口的电信号,将其放大整形后,广播到其他端口,集线器不进行碰撞检测,可能会产生消息碰撞。

3.2交换机(switch)

  • 可以提供大量的网络接口将多态网络设备连接成局域网

  • 可以将多个节点连接起来,组成一个计算机网络。

  • 工作在数据链路层

  • 通过MAC地址来识别网络中的设备,并根据MAC地址进行查询MAC地址表,实现数据的转发

    • 数据帧进入交换机端口,记录源MAC地址,记录到MAC地址表中(表中记录MAC地址及其连接的具体的端口)

    • 转发一个数据帧,交换机通过查表,查找该帧的目的MAC连接在哪个端口,能够查询到从端口转发,如果表中没有目的MAC地址,那么就会广播,由主机判断数据是否是发送给自己的

3.3路由器

复制代码
1)IP地址:IPV4(32bits=网络号/网段号+主机号)     IPV6
2)在同一个局域网内的主机,网络号相同,主机号必须不相同
3)通常我们会将一个子网中主机位全0的地址称为网络号或者网段号,它代表整个子网本身,不能分配给任何的主机
4)通常将一个子网中主机位全位1的地址称为广播地址,不能分配给任何主机
5)通常将主机号为1的设置为默认网关
    eg:子网内某台主机IP:192.168.31.10
    子网掩码:255.255.255.0(11111111.11111111.11111111.00000000)高位为1为网络号,地位连接0主机号
    理论上子网内可以最大又多少台主机
    192.168.31.0~192.168.31.255,最大可以有256台
    192.168.31.0 代表这个子网的网络号,不能发配给主机
    192.168.31.255 当前子网的广播地址,不能发配给主机
    最大只能有254台,如果还需要设置网关IP,还需要-1
    默认网关:192.168.31.1
    最多只能有253台
  • 可以把两个或多个计算机网络互相连接起来,形成更大的计算机网络,称为"互连网",全球最大的互连网是因特网。

  • 工作在网络层,隔离广播域 ,可以实现路由选择和数据包的转发和交换,收到一个数据包时,会解析数据包,查看IP地址,识别IP地址,不关心MAC地址

  • 路由器的每一个接口都连接着一个独立的广播域,通常就是一个独立的子网,而这个路由器的接口的IP地址,就是该子网内所有设备的"默认网关",一般将网段内的第一个可用的主机IP地址设置为默认网关

  • 路由表是路由器中存储的信息,用于决定数据包应该被转发到哪个下一跳或者接口,它包含目标网络地址和下一跳的信号,这里直接与网络层的路径查询有关

4.网络数据传输过程

feiQ为例,用户a给用户b发送数据,解析封装数据及拆包的过程:

复制代码
eg:家用路由器举例
    - WAN(广域网接口):连接外网,WAN口也会有一个网关地址,这个网关是由运营商分配给你的
    - LAN(局域网接口):连接子网内的不同的主机

5. IP地址

IP地址,常见的IP地址分类:

  • IPV4地址:32bits

  • IPV6地址:128bits

IPV4地址32bits分成了两个部分:网络号(网段号) + 主机号

**网络号:**用于标识某一个网络(属于哪个网络),用子网掩码的连续的高位1来标识网络号在IP地址中占多少bit

**主机号:**用来标识特定的网段下特定的主机(是属于哪个网络下的一台主机),子网掩码中连续的地位的0来标识主机号在IP地址中站多少bit

IPV4表示:采用点分式表示

eg:192.168.31.10

​ 172.5.0.1

5.1 IP地址划分

IP地址分为A B C D E共5类

​ A类分配给政府机构

​ B类分配给公司单位

​ C类分配给个人

​ D类分配给组播

​ E类用于各种实验

地址按照使用范围划分,可以划分为两种:一种叫公网地址,一种叫私网地址

公有IP与私有IP区别:

  • 公网IP:是全球互连网范围内唯一的,确保每个设备在通信中的身份识别不重复,可以被其他互连网设备访问和通信,eg:网站、服务器等

  • 私网IP:不是全球唯一的,仅在局域网内有效,私有IP地址在局域网内唯一,但同一个局域网内的IP互不相同,不同的局域网内可以有相同的IP地址,为了为企业和家庭提供IP分配的灵活性

  • 公网IP由运营商分配,只有公网IP才能上网,但是不可能给每一台主机分配一个公网IP,因为IPV4地址32bits,不够分,才需要私网IP,私网IP要上网,必须经过公网IP

特殊地址 用途
0.0.0.0 不能作为目的地址使用。它通常用于表示"本网络上的本主机"在尚未获得具体的IP地址时的状态,会使用0.0.0.0作为源地址发送。
255.255.255.255 这是一个特殊的广播地址,它用于在本地网络上发送广播消息,即向同一网络段内的所有设备发送消息。
127.0.0.0 ~ 127.255.255.255 特殊的回环地址范围,也称为本地回环地址或环回地址,它用于指代本机地址,即发送数据包的设备本身就是目的地(自己给自己发)。指代本机地址:127.0.0.1(最常用的回环地址)
169.251.X.X 微软保留地址,无ip时会分配到这个地址

5.2 IP地址分类

IP地址的范围 私有地址的范围
A 0网络号(7Bits)+主机号(24Bits) 0.0.0.0~127.255.255.255 10.0.0.0~10.255.255.255
B 10网络号(14Bits)+主机号(16Bits) 128.0.0.0~191.255.255.255 172.16.0.0~172.31.255.255
C 110网络号(21Bits)+主机号(8Bits) 192.0.0.0~223.255.255.255 192.168.0.0~192.168.255.255
D 1110多播组号(28Bits) 224.0.0.0~239.255.255.255
E 11110留待以后(27Bits) 240.0.0.1~255.255.255.254

IP地址由网络号 + 主机号共32bits构成,那到底网络号占多少位,主机号占多少位,取决于子网掩码?

5.3 子网掩码

子网掩码:用来指定一定ip地址中,哪些bits是网段号,哪些bits是主机号

netsmask 高位的连续的1为网段号,低位连续的0为主机号

eg:

复制代码
netmask: 255.255.255.0 ==> ip中高3字节为网络号,低1字节为主机号

eg:B类网络的子网掩码是255.255.252.0,则理论上每个子网的主机数最多可以是多少个?

复制代码
11111111 11111111 11111100 00000000
理论上IPV4地址中,主机号占10位
0000000000 ~ 1111111111
1024台
实际中减去网关、网络号、广播地址
实际中最多只能有1021台

同一网络下主机的子网掩码是相同的,同一子网下网络号也是相同的

设置网卡ip地址

bash 复制代码
ifconfig etho(网卡名字) 192.168.31.100(设置的IP) netmask 255.255.255.0(设置的子网掩码) up
up: 立即生效

有了MAC地址和ip地址还不能进行通信,还需要端口号(标识是设备上哪一个网络应用),提供端到端的服务

ip地址用来标识网络上一台主机,一个主机上可以有多个网络应用,通过端口号区分不同的网络应用

6. 端口号(传输层)

不管是TCP还是UDP,都有源端口和目的端口两个字段

TCP和UDP采用16bits的端口号来标识网络应用程序

网络传输层的角度:TCP应用和UDP应用

TCP端口和UDP端口是独立的

假设TCP应用的端口为20 与 UDP应用端口为20 不是同一个应用,相互独立的

应用程序的地址: 应用程序对外提供服务的地址:IP地址+端口号 eg:web服务器的地址为192.168.1.100:80

网络连接四元组:MAC地址 + IP地址 + 传输层协议(TCP/UDP) + 端口号

端口号并不是你想指定为什么就是可以指定的,IANA机构管理端口号

公认端口:

  • 端口号范围:0~1023,这部分端口已经被一些知名的应用程序使用的,所以在测试自己的程序时候尽量不去使用该范围内的端口

  • 特性:这些端口已经绑定了一些服务,eg:HTTP服务的默认端口为80,HTTPS服务默认端口为443,SMTP服义默认端口25......

7.网络字节序的问题

主机字节序(又称为CPU字节序):由CPU指令集决定,它就决定了数据在内存中的存储方式,常见的字节序由大端字节序和小端字节序。

网络字节序: 采用大端字节序作为标准。

如果主机主机字节序与网络字节序不一致的,有可能导致数据解析错误,因此TCP/IP协议规定,发送端需要发送数据之前,先将主机字节序转换为网络字节序,在接收数据时,接收端需要将网络字节序转换为主机字节序,这样转换过程确保了数据在传输过程中的一致性和正确性。

IP地址转换:

cpp 复制代码
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
​
//n: network 网络地址
//a: ip的点分式十进制字符串
​
int inet_aton(const char *cp, struct int_addr *inp);
@cp: 指向要转换的点分式的IP地址字符串  eg: "192.168.31.10"
@inp: 指向一个转换后的struct in_Addr 网络ip地址,用来保存转换后的网络IP
    /* Internet address. */
    struct in_addr {
        uint32_t    s_addr;     /*address in network byte order*/
    };
​
in_addr_t inet_addr(const char *cp);
@cp: 指向转换的点分式的十进制的IP地址 eg: "192.168.31.10"
返回值:
    返回一个IP的网络地址
​
in_addr_t inet_metwork(const char *cp);
@cp: 指向转换的点分式的十进制的IP地址 eg: "192.168.31.10"
返回值:
    返回一个IP的网络地址
​
char *inet_ntoa(struct in_Arrd in);
@in: 网络字节序的IP
返回值:返回转换后的点分式十进制字符串IP地址的首地址

端口号转换:

cpp 复制代码
//h: host 主机
//n: network 网络
//s: short
//l: long
​
#include <arpa/inet.h>
​
// 把一个32bits整数的主机字节序转换为网络字节序
uint32_t htonl(uint32_t hostlong);
@hostlong: 主机字节序中一个long类型的整数
返回值: 转换后的32bits网络字节序的整数
​
// 把一个16bits整数的主机字节序转换为网络字节序
uint16_t htons(uint16_t hostshort);
​
// 把一个32bits整数的网络字节序转换为主机字节序
uint16_t ntohl(uint32_t netlong);
​
// 把一个16bits整数的网络字节序转换为主机字节序
uint16_t ntohs(uint16_t netshort);
相关推荐
百***37482 小时前
PHP进阶-在Ubuntu上搭建LAMP环境教程
开发语言·ubuntu·php
what_20182 小时前
idea启动项目配置环境变量(nacos 命名空间)
java·开发语言
Fantasydg2 小时前
JSP学习
java·开发语言·学习
太空程序猿3 小时前
数据类型与变量
java·开发语言
Guheyunyi3 小时前
安全风险监测系统核心技术
运维·网络·人工智能·安全
weixin_307779133 小时前
Amazon VPC中Web应用无法连接数据库的安全组配置问题分析与修复
网络·数据库·安全·云计算·aws
rit84324993 小时前
MATLAB实现图像PCA降噪
开发语言·计算机视觉·matlab
*小雪3 小时前
uniapp写H5授权登录及分享,返回到目标页面
开发语言·javascript·uni-app
百***78454 小时前
Java实战:Spring Boot application.yml配置文件详解
java·网络·spring boot