本文紧接上文,聚焦于网络线程连接并请求主机直至获得响应报文这个过程,主要研究一个数据包的网络之旅
整个过程如下图所示:
参考资料:户根勤《网络是怎么连接的》
浏览器生成消息
1.生成HTTP请求消息
浏览器的第一步工作就是要对URL进行解析,并生成发送WEB服务器的请求信息
(1)URL解析
- URL各个部分的含义:
- 对URL进行解析从而定位到Web服务器下对应的目录:
我们常见的url中很多都是没有文件名的,例如https://www.baidu.com,这种情况往往是对文件名进行了省略,web服务器有默认指向的文件如index.html等,例如https://www.baidu.com/index.html
(2)HTTP请求消息生成
对URL进行解析后,浏览器确定了Web服务器和文件名,然后根据这些信息生成HTTP请求消息
- HTTP请求基本结构:
- 请求方法:
- 请求报文:
HTTP状态码:
- 响应报文:
2.DNS域名解析
通过浏览器解析URL并生成HTTP消息后,还需要查询服务器域名对应的IP地址,才能找到消息发送对象的地址位置
DNS服务器就是专门用来保存WEB服务器域名与IP对应关系的服务器
(1)IP地址知识
- IP地址结构
子网掩码表示IP地址中网络号与主机号的分界,子网掩码为1的部分为网络号,子网掩码为0的部分为主机号
当主机号部分的比特全为0时表示整个子网(而不是某台设备)全为1表示向子网所以设备发送
- IP地址表示方法
(2)域名层级关系
在域名中,越靠右的位置表示其层级越高
- 根 DNS 服务器
- 顶级域 DNS 服务器(cn)
- 权威 DNS 服务器(google.cn)
- 而
www
是主机名 随意填写 域名解析的时候填写主机记录和记录值
(3)域名解析工作流程
- 本地DNS服务器(离客户端最近的DNS服务器)运行的是递归查询:对客户端负责到底,不断去询问查找可以解析域名的服务器
- 其他DNS服务器运行的是迭代查询:奉行踢皮球原则,不主动询问其他服务器,而是把知道域名对应关系的服务器信息告诉给本地域名服务器
(4)域名解析内部原理
域名解析请求DNS服务器,与浏览器请求远程web服务器有类似的地方,后面含义再详细讲Socker库和协议栈
用电信号传输TCP/IP数据
协议分层模型:
TCP/IP数据包封装:
不同的协议层对数据包有不同的称谓,在传输层叫做段(segment),在网络层叫做数据报(datagram),在链路层叫做帧(frame)
通信操作中使用的控制信息分为两类:
- 头部中记录的信息(即加载数据包前的控制信息)
- 套接字(协议栈中的内存空间)中记录的信息
1.委托协议栈发送消息
通过DNS获取IP后,就可以把HTTP的传输工作交给操作系统中的协议栈
委托的结果是:协议栈之间连接了一条数据通道,数据包能沿着这条通道流动(套接字则可以视为管道的出入口,套接字的实体就是通信控制信息)
(1)套接字结构
在协议栈内部有一块用于存放控制信息的内存空间,这里记录了用于控制通信操作的控制信息,我们可以认为这些控制信息就是套接字的实体
套接字中记录了用于控制通信操作的各种控制信息,协议栈则需要根据这些信息判断下一步的行动,这就是套接字的作用(协议栈是根据套接字中记录的控制信息来工作的)
套接字内容查看:
(2)TCP/IP 软件分层结构
(3)Socket库
浏览器通过调用Socket库,委托协议栈来工作
向操作系统内部的协议栈发出委托时,需要按照指定的顺序来调用Socket 库中的程序组件:
- 创建套接字(创建套接字阶段)
- 将管道连接到服务器端的套接字上(连接阶段)
- 收发数据(通信阶段)
- 断开管道并删除套接字(断开阶段)
(4)TCP与UDP协议
TCP和UDP协议,接收应用层的委托指向收发数据的操作
- TCP和UDP协议的运用:
- TCP/UDP比较:
咳咳,正经详细的比较如下:
- TCP/UDP编程模型
(5)IP协议
在互联网上传数据时,数据刽被切分成一块块的网络包,而将网络包发送给对方的操作就是由 IP 负责的
此外 IP 中还包括 ICMP
协议和 ARP
协议:
ICMP
用于告知网络包传送过程中产生的错误以及各种控制信息ARP
用于根据 IP 地址查询相应的以太网 MAC 地址
IP 下面的网卡驱动程序负责控制网卡硬件,而最下面的网卡则负责完成实际的收发操作,也就是对网线中的信号执行发送和接收的操作
2.TCP可靠传输
参考资料:TCP三次握手
(1)TCP包头格式
源端口号:发送网络包的程序的端口号
目标端口号: 网络包的接收方程序的端口号
序号:发送方告知接收方,该网络包发送的数据相当于所有发送数据的第几个字节
ACK 号(确认号):接收方告知发送方,接收方已经收到了所有数据的第几个字节
数据偏移量(首部长度): 表示数据部分的起始位置,也可以认为表示头部的长度
保留:该字段为保留,现在未使用
控制位(状态位):该字段中的每个比特分别表示以下通信控制含义
- URG:表示紧急指针字段有效
- ACK:表示接收数据序号字段有效,一般表示数据已被接收方收到
- PSH:表示通过flush 操作发送的数据
- RST:强制断开连接,用于异常中断的情况
- SYN:发送方和接收方相互确认序号,表示连接操作
- FIN:表示断开连接
窗口大小:接收方告知发送方窗口大小(窗口大小即缓存大小,标识当前处理能力,用于流量控制,拥塞控制)
校验和:用来检查是否出现错误
紧急指针:表示应紧急处理的数据位置
可选字段:除了上面的固定头部字段之外,还可以添加可选字段,但除了连接操作之外,很少使用可选字段
(2)TCP三次握手
TCP三次握手其实就是建立一个TCP连接,客户端和服务器之间需要3个数据包,握手的主要作用就是为了确认双方的接收和发送能力是否正常,初始序列号,交换窗口大小以及 MSS 等信息
SYN:发送方和接收方相互确认序号,表示连接操作; ACK:表示接收数据序号字段有效,一般表示数据已被接收方收到
- 初始状态下,客户端和服务端都处在CLOSED状态,先是服务端主动监听某个端口,处于LISTEN状态
- 第一次握手:客户端发送SYN报文,并进入SYN-SENT状态,等待服务器确认
- 第二次握手:服务器收到SYN报文后,需要向客户端发送ACK确认收到的报文;同时服务端也向客户端发送一个SYN报文(也就是说服务端向客户端发送了SYN+ACK报文),然后服务端进入SYN_RCVD状态
- 第三次握手:客户端收到SYN+ACK报文后,向服务端发送ACK确认收到的报文,客户端进入ESTABLISHED状态; 服务端收到客户端的ACK包后也会进入ESTABLISHED状态,完成三次握手
三次握手的本质是——客户端和服务器通过两对SYN-ACK报文互相确认能力正不正常
每次SYN发送一个随机数n(seq=n),则ACK需要返回n+1(ack=n+1)
(3)TCP连接状态查看
在Linux系统可以通过netstat -napt
命令查看TCP连接状态
(4)TCP分割数据
MTU
:一个网络包的最大长度,以太网中一般为1500
字节。MSS
:除去 IP 和 TCP 头部之后,一个网络包所能容纳的 TCP 数据的最大长度
HTTP请求消息比较长,超过MSS长度,TCP就会把HTTP消息的数据拆解成一块块的数据发送,数据会被以 MSS
的长度为单位进行拆分,拆分出来的每一块数据都会被放进单独的网络包中
(5)TCP报文生成
TCP 协议里面的两个端口,一个是浏览器监听的端口(通常是随机生成的),一个是 Web 服务器监听的端口(HTTP 默认端口号是 80
, HTTPS 默认端口号是 443
)
TCP报文即为TCP头部+HTTP头部+数据,组装好后交给下面的网络层(IP)处理
(6)TCP四次挥手
当我们的应用不再需要数据通信,就会发起断开TCP连接,建立一个连接需要三次握手,而终止一个连接需要经过四次挥手
SYN:发送方和接收方相互确认序号,表示连接操作; ACK:表示接收数据序号字段有效,一般表示数据已被接收方收到; FIN:表示断开连接
- 第一次挥手:客户端发起FIN包,客户端进入FIN_WAIT_1状态(虽然FIN包不携带数据,也需要消耗一个序号u)
- 第二次挥手:服务端收到FIN包,发出确认包ACK(ack=u+1),并带上自己的序号seq=v,服务端进入CLOSE_WAIT状态(这个时候客户端仍需要接收服务器发送的数据);客户端接收到服务端发送的ACK后,进入FIN_WAIT_2状态
- 第三次挥手:服务端数据发送完毕后,向客户端发送FIN包(seq=w,ack=u+1),半连接状态下服务器可能又发送一些数据,服务端此时进入LAST_ACK状态
- 第四次挥手:客户端收到服务端的FIN包后,发出确认包ACK(ACK=1, ack=w+1),此时客户端进入TIME_WAIT状态;服务端收到客户端确认包后进入CLOSED状态,而客户端需要等待2MSL后才进入CLOSED状态
四次挥手的本质是——客户端和服务器通过两对FIN-ACK报文通知对方自己要关闭了
三次握手中,在第二次握手时,接收端将一个ACK包和一个SYN包合并一起发送,所以减少了一次包的发送
四次挥手中,在主动关闭方(客户端)发送FIN包后,接收方(服务端)可能还要发送数据,不能立即关闭数据通道,所以服务端要先确认ACK,然后等到自己把数据发无可发后再发送FIN包
3.IP远程定位
TCP 模块在执行连接、收发、断开等各阶段操作时,都需要委托 IP 模块将数据封装成网络包发送给通信对象
(1)IP包头格式
参考资料:IP报头格式
- 版本号(Version):标明了IP 协议的版本号,目前的协议版本号为4,下一代IP 协议的版本号为6
- 首部长度:指 IP 包头部长度,占4 位
- 区分类型(服务类型):包括一个3 位的优先权字段(COS,Class of Service),4 位TOS 字段和1 位未用位。4 位TOS 分别代表最小时延、最大吞吐量、最高可靠性和最小费用
- 总长度:是整个IP 数据报长度,包括数据部分
- 标识:唯一的标识主机发送的每一份数据报,通常每发送一份报文它的值就会加1
- Flag:3bite 它是用来标志数据包是否分段,其中包含DF(do not fragment)和MF(more fragment),当DF的值为1时,则MF的值必为0,DF为1,则说明数据包有分段。同样可以知道当MF为1时,则DF为0,这表示的是数据包没有分段。当然也有可能MF和DF都为0的
- Frag offset:段偏移 15bite 用于描述此分段在数据包中的位置
- 生存时间:Time To Live(TTL),设置了数据包可以经过的 路由器数目。一旦经过一个路由器,TTL 值就会减1,当该字段值为0 时,数据包将被丢弃
- 协议:指示应当把这个数据包发往更高层的协议,TCP 协议的协议号为 6,UDP 协议的协议号为17
- 报头校验和:计算IP 头部的校验和,检查报文头部的完整性
- 源IP 地址:标识数据包的源端设备(即客户端输出的IP地址)
- 目的IP 地址:标识数据包的目的端设备(即通过DNS域名解析得到的WEB服务器IP)
- IP选项:一般格式为1个字节的代码,1个字节的长度,1个字节的指针,指针的值从1开始计数,指向IP选项的内容,一般其值为4(跳过了前面的代码&长度&指针的三个字节),长度包括前面3个字节在内的整个IP选项,最大值为40
(2)IP地址选择
客户端有多个网卡时,在填写源地址IP时就要根据路由表规则来判定应该使用哪一块网卡来发送包
在lInux系统,我们使用route -n
,在windows系统则用 route print
查看路由表
利用子网掩码与路由表判断源地址:
假设目的IP 地址(web服务器)是192.168.10.200,与各条目的子网掩码做与运算,计算出IP和条目的网络目标IP(destination)匹配,则选择该条目的网卡作为IP包头的源地址
第三条目的目标地址和子网掩码都是 0.0.0.0
,这表示默认网关,如果其他所有条目都无法匹配,就会自动匹配这一行。并且后续就把包发给路由器(Gateway即路由器的IP)
(3)IP报文生成
IP报文即为IP头部+TCP头部+HTTP头部+数据,组装好后IP模块还要进一步处理
4.MAC传输
生成了 IP 头部之后,接下来网络包还需要在 IP 头部的前面加上 MAC 头部
(1)MAC包头格式
MAC 头部是以太网使用的头部,它包含了接收方和发送方的MAC 地址等信息
- 接收方MAC 地址:网络包接收方的MAC 地址,在局域网中使用这一地址来传输网络包
- 发送方MAC 地址:网络包发送方的MAC 地址,接收方通过它来判断是谁发送了这个包
- 以太类型:使用的协议类型,下面是一些常见的类型,一般在TCP/IP 通信中只使用0800 和0806这两种
- 0000-05DC:IEEE 802.3
- 0800 :IP 协议
- 0806 :ARP 协议
- 86DD IPv6
(2)MAC地址确认
发送方:
发送方的MAC地址获取比较简单,MAC地址在网卡生产时写入ROM中的,只需将其读取出来放到MAC头部即可
接收方:
发送IP网络包需要告诉以太网对方的MAC地址,IP 模块根据路由表Gateway 栏的内容判断应该把包发送给谁,然后在利用ARP
协议通过广播的方法帮我们找到路由器(目标设备与发送方在同一子网中)的 MAC 地址
后续操作系统会将ARP的查询结果缓存在ARP缓存的内存空间内,可以通过arp -a
命令进行查看
(3)MAC报文生成
MAC报文即为MAC头部+IP头部+TCP头部+HTTP头部+数据,至此网络包终于完整了,可以从本设备的大门(网卡)走出去开始真正的网络之旅
5.网卡出口
(1)网卡处理IP网络包
IP生成的网络包只是放在内存中的一串二进制数字信息,所以在其开始网络旅程之前还要经过网卡将数字信息转换为电信号
网卡驱动从 IP 模块获取到包之后,会将其复制到网卡内的缓存区中,接着会其开头加上报头和起始帧分界符,在末尾加上用于检测错误的帧校验序列
- 起始帧分界符是一个用来表示包起始位置的标记
- 末尾的
FCS
(帧校验序列)用来检查包传输过程是否有损坏
最后网卡将网络包转换为电信号,通过网线发送出去
(2)以太网
以太网是一种为多台计算机能够彼此自由和廉价地相互通信而设计的通信技术,它可以让信号通过网线流过整个网络,最终到达所有的设备
以太网的三个性质:
- 包发送到MAC 头部的接收方MAC 地址代表的目的地
- 用发送方MAC地址识别发送方
- 用以太类型识别包的内容
(3)网络包传输
经过网卡处理后的网络包会发往最近的网络转换设备,当到达最近的转发设备之后,转发设备会根据头部中的信息判断接下来应该发往哪里
这个过程需要用到一张表,这张表里面记录了每一个地址对应的发送方向,也就是按照头部里记录的目的地址在表里进行查询,并根据查到的信息判断接下来应该发往哪个方向
网络中有路由器和集线器两种不同的转发设备,它们在传输网络包时有着各自的分工
(1)路由器根据目标地址判断下一个路由器的位置(基于IP规则)
(2)集线器在子网中将网络包传输到下一个路由(以太网规则)
从网线到网络设备
参考资料:集线器,交换机,路由器的区别
网络数据包的网络之旅:
各设备处理数据包的方式:
集线器:构建局域网的设备,它会将信号复制并发向连接同一个集线器(即同一局域网)的全部端口(广播)
交换机:构建局域网的设备,运行在MAC层,它会将信号发向指定MAC的端口
路由器:将局域网连接上互联网的设备,运行在IP层,路由器可以分析网络包的目标地址IP,如果该IP在自己负责的网络内则接收,如果不在的话就发向其他网络(本质上是一个网络网关)
1.集线器传输
集线器(Hub)是指将多条以太网双绞线或光纤集合连接在同一段物理介质下的设备
(1)网卡与集线器的双绞线连接
网线周围的电磁波会产生噪声混淆信号导致信号的波形发生失真,所以用双绞线移植噪声
(2)集线器将信号发往所有线路
当电信号(网络包经过网卡转换后的形态)到达集线器后,集线器将信号发送给所有连接在它上面的线路,会被广播到整个网络中
集线器将包发到所有的设备,然后由设备根据接收方MAC 地址来判断应该接收哪些包
2.交换机包转发
交换机意为“开关”,是一种用于电(光)信号转发的网络设备。它可以为接入交换机的任意两个网络节点提供独享的电信号通路
交换机工作在MAC层,也称为二层网络设备
(1)交换机包接收操作
- 电信号进入交换器模块后,电信号转换为数字信号
- 通过包末尾的FCS校验错误,无误后信号放入缓冲区
- 交换机的端口不具有MAC地址,所以会将接收到所有的包存放再缓冲区中
(2)交换机MAC地址查找
- 包存入的缓冲区后,就需要查询MAC地址表找到包的接收发MAC地址对应的端口,从而准确发送到连接该端口的设备
- 如果地址表找不到指定的MAC地址(可能是该地址没有向交换机发送过包,或者这个设备一段时间没有工作导致地址从地址表删除了),就将包复制并发向其他所有的端口(和集线器同样的转发方法),然后只有相应的接收者才接收包,其他设备会忽略这个包
- 如果接受方MAC地址是一个广播地址,交换机也会将包复制并发向其他所有的端口
3.路由器包转发
经过交换机后,网络包终于走出了子网,再经过路由器这个关口正式进入互联网
路由器,是连接因特网中各局域网、广域网的设备
(1)交换机与路由器
- 因为路由器是基于 IP 设计的,俗称三层网络设备,路由器的各个端口都具有 MAC 地址和 IP 地址
- 而交换机是基于以太网设计的,俗称二层网络设备,交换机的端口不具有 MAC 地址
(2)路由器基本原理
路由器的端口具有MAC地址,因此它可以成为以太网的发送方和接收方;同时还具有IP地址,从这个意义上说,它和计算机的网卡是一样的
当转发包时,首先路由器端口会接收发给自己的以太网包,然后路由表查询转发目标,再由相应的端口作为发送方将以太网包发送出去
(3)路由器包接收操作
- 电信号到达网线接口部分,路由器模块会将电信号转成数字信号
- 通过包末尾的FCS进行错误校验
- 检查MAC头部接收方MAC地址,如果是发给自己的就放到接收缓冲区中,否则就丢弃这个包
- 路由器的端口都具有 MAC 地址,只接收与自身地址匹配的包,遇到不匹配的包则直接丢弃
(4)路由表查询确认输出端口
完成包接收操作后,路由器就会去掉MAC头部(MAC头部的作用就是将包送达路由器,接收方 MAC 地址就是路由器端口的 MAC 地址)
然后查询路由表判断转发目标,如图10.10.1.101
的计算机要向地址为 192.168.1.100
的服务器发送一个包,这里的路由匹配与之前讲的IP地址的选择一样,即用目标IP与各条目的子网掩码做与运算,直到找到计算出IP和条目的网络目标IP(destination)匹配,则该条目的记录作为转发目标
实在找不到匹配路由时,就会选择默认路由,路由表中子网掩码为 0.0.0.0
的记录表示「默认路由」
(5)路由器包发送操作
路由器包发送操作需要根据路由表的网关列来判断:
- 如果网关是一个 IP 地址,则这个IP 地址就是我们要转发到的目标地址,还未抵达终点,还需继续需要路由器转发。
- 如果网关为空,则 IP 头部中的接收方 IP 地址就是要转发到的目标地址,也是就终于找到 IP 包头里的目标地址了,说明已抵达终点。
知道对方的 IP 地址之后,接下来需要通过
ARP
协议根据 IP 地址查询 MAC 地址,并将查询的结果作为接收方 MAC 地址发送方 MAC 地址字段,填写输出端口的 MAC 地址
网络包完成后,接下来会将其转换成电信号并通过端口发送出去(与计算机的网卡的操作是一致的)
经过多个路由器的大接力,层层转发最终到达目的地
在网络包传输的过程中,源 IP 和目标 IP 始终不变,一直变化的是 MAC 地址,因为需要 MAC 地址在以太网内进行两个设备之间的包传输
通过接入网进入互联网内部*
(对于这部分我只做简单介绍,详细资料可参考接入网进入互联网内部——探索接入网和网络运营商 )
网络包出了局域网后通过接入网进入互联网。和局域网一样,互联网也是通过路由器来转发包的,因此我们可以将互联网视为局域网络的放大版
1.ADSL接入网
连接用户与互联网的接入网,所谓接入网,就是指连接互联网与家庭、公司网络的通信线路
2.光纤接入网
另外一种接入网技术光纤接入网(FTTH),通过光纤分路来降低传输成本
用户发送的网络包会通过ADSL 和FTTH 等接入网到达运营商的BAS,通过ADSL 接入网和BAS 之后,网络包就到达了互联网内部
3.接入网中使用的PPP和隧道
ADSL和FTTH接入网中,都需要先输入用户名和密码,而BAS就是登录操作的窗口,而BAS使用PPPoE(以太网点对点协议,是将PPP 消息装入以太网包进行传输的方式)来实现这个功能
(1)PPPE协议
拨号上网中的PPP:
ASDL中的PPP:
FTTH中的PPP:
(2)隧道
BAS 除了作为用户认证的窗口之外,还可以使用隧道方式来传输网络
包,通过隧道网络包被发向运营商
4.网络运营商内部
网络包通过接入网之后,到达运营商POP(Point of Presense,接入点)的路由器
NOC是运营商的核心设备,从POP 传来的网络包都会集中到这里,
并从这里被转发到离目的地更近的POP,或者是转发到其他的运营商
5.跨越运营商的网络包
无论最终目的地是否属于同一家运营商,都可以从路由表中查到,因此只要一次接一次按照路由表中的目标地址来转发包,最终一定可以到达Web服务器所在的POP
运营商之间的路由信息交换:
通过连接到中心设备IX的方式来减少线路数量:
进入服务端
通过互联网,我们可以到达旅途终点的大门前,我们的目标服务器就在这个局域网中
1.服务端所在地
一般都是(b)这种结构,经过接入网还要通过防火墙的审查
2.服务端处理数据包
请求终于到达了Web 服务器,短短几秒的“漫长旅程”迎来终点
最后服务端一层一层剥开数据包获得HTTP请求,也派出了他的使节(响应消息)赶往客户端……
ents.com/Autovy/Image/master/img/202110131159356.jpg)