一、从一个请求来看网络分层原理
1.1 复杂的网络
以下为一次请求过程中可能遇到的问题,预示着网络的复杂性。
1.2 如何简化复杂度
为了简化网络的复杂度,网络通信的不同方面被分解为多层次结构,每一层只与紧挨着的上层或者下层进行交互,将网络分层,这样就可以修改,甚至替换某一层的软件,只要层与层之间的接口保持不变,就不会影响到其他层。
1.2.1 OSI( Open System Interconnection Reference Model): 开放系统互联参考模型
1.2.2 TCP/IP 协议族
1.2.3 两种协议的对应关系
应用层:应用程序负责的部分
传输层:TCP、UDP、SCTP 等
网络层:IPv4、IPv6等
数据链路层:以太网、无限LAN(WIFI)
物理层:光纤、双绞线电缆、无线设备
1.3 一个请求的分层解析流程
请求各层之间都是调用对应层的接口(这个接口可以类比java中的接口,它可以有各种实现方式)。
在请求过程中域名是无法直接被计算机识别的,必须先转换成ip,此时先检测本地是否配置了host,如果没有配置的话会发起一个dns请求。
DNS使用UDP作为传输层,DNS服务器IP配置在你的操作系统中,可以直接获取。
数据链路层在接收到网络层调用后,会通过IP使用ARP协议获取当前IP对应的MAC地址。
最终通过物理层将数据传入路由器,路由器进行逆向解析(MAC地址->IP),如果路由器判断此信息不是给自己的会将信息继续传给下游电信运营商。
运营商判断是DNS请求还是HTTP请求,如果是DNS请求会调用DNS服务器换取IP并返回。
获取IP后DNS请求完成,此时再次发送一次HTTP请求,HTTP在传输层使用的是TCP协议,其他层同理。
运营商判断如果非DNS请求,那么电信会通过运营商直接的协议进行消息的发送,最终找到ip对应的服务器。
接收端服务器的物理层接受到此次请求,通过对应的协议进行数据的层层解析获取对应的信息,最终将数据传给本地服务器(nginx、tomcat等),服务器将响应报文通过HTTP方式将数据返回。
一次请求的流转如下图:
二、HTTP协议
超文本传输协议(HyperText Transfer Protocol,HTTP): 一种无状态的,以请求/应答方式运行的协议,它使用可扩展的语义和自描述消息格式,与 基于网络的超文本信息系统灵活的互动
2.1 HTTP报文格式
请求报文和响应报文的结构基本相同。
起始行:描述请求或响应的基本信息。
头部字段集合:key-value结构,报文的详细信息。
消息体:真实传输的内容,可以是文本或二进制等。
2.1.1 HTTP请求报文
一个HTTP请求报文由请求行(request line)、请求头部(header)、空行和请求数据4个部分组成,下图给出了请求报文的一般格式。
2.1.1.1 请求行
请求行由请求方法字段、URL字段和HTTP协议版本字段3个字段组成,它们用空格分隔。例如,GET /index.html HTTP/1.1。
HTTP协议的请求方法有GET、POST、HEAD、PUT、DELETE、OPTIONS、TRACE、CONNECT。
2.1.1.2 请求头部
请求头部由关键字/值对组成,每行一对,关键字和值用英文冒号“:”分隔。请求头部通知服务器有关于客户端请求的信息,典型的请求头有:
User-Agent:产生请求的浏览器类型。 Accept:客户端可识别的内容类型列表。 Host:请求的主机名,允许多个域名同处一个IP地址,即虚拟主机。
2.1.1.3 空行
最后一个请求头之后是一个空行,发送回车符和换行符,通知服务器以下不再有请求头。
2.1.1.4 请求数据
请求数据不在GET方法中使用,而是在POST方法中使用。POST方法适用于需要客户填写表单的场合。与请求数据相关的最常使用的请求头是Content-Type(这个主体的对象类型)和Content-Length(主体的长度)。
2.1.1.5 头部字段注意事项
字段名不区分大小写,字段名里不允许出现空格,可以使用连字符“-”,但不能使用下划线“_”(有的服务器不会解析带“_”的头字段)。字段名后面必须紧接着“:”,不能有空格,而“:”后的字段值前可以有多个空格; 字段的顺序是没有意义的,可以任意排列不影响语义; 字段原则上不能重复,除非这个字段本身的语义允许,例如 Set-Cookie。
2.1.2 HTTP响应报文
HTTP响应也由三个部分组成,分别是:状态行、消息报头、响应正文。
2.1.2.1 状态行格式如下
HTTP-Version Status-Code Reason-Phrase CRLF
其中,HTTP-Version表示服务器HTTP协议的版本;Status-Code表示服务器发回的响应状态代码;Reason-Phrase表示状态代码的文本描述。状态代码由三位数字组成,第一个数字定义了响应的类别,且有五种可能取值。
1xx:指示信息–表示请求已接收,继续处理。
2xx:成功–表示请求已被成功接收、理解、接受。
3xx:重定向–要完成请求必须进行更进一步的操作。
4xx:客户端错误–请求有语法错误或请求无法实现。
5xx:服务器端错误–服务器未能实现合法的请求。
常见状态代码、状态描述的说明如下:
200 OK:客户端请求成功。
400 Bad Request:客户端请求有语法错误,不能被服务器所理解。
401 Unauthorized:请求未经授权,这个状态代码必须和WWW-Authenticate报头域一起使用。
403 Forbidden:服务器收到请求,但是拒绝提供服务。
404 Not Found:请求资源不存在,举个例子:输入了错误的URL。
500 Internal Server Error:服务器发生不可预期的错误。
503 Server Unavailable:服务器当前不能处理客户端的请求,一段时间后可能恢复正常,举个例子:HTTP/1.1 200 OK(CRLF)。
百度百科 状态码参考网址
2.1.2.1 响应头
Access-Control-Allow-Credentials:true
Access-Control-Allow-Origin:*
Access-Control-Expose-Headers:Date,X-API-Request-Id
Content-Encoding:gzip
Content-Type:application/json;charset=UTF-8
Date:Sun, 10 Mar 2024 12:00:17 GMT
2.1.2.2 响应实体内容
服务器发给浏览器,要让浏览器显示的内容(html,js,css,图片,数据等信息)。
三、HTTP请求完整过程
3.1 请求过程描述
首先浏览器先解析URL中的域名。
通过域名获取对应的ip地址,上边已经说过ip是通过DNS服务器获取,我们可以在谷歌浏览器中查看到域名对应ip的解析。
获取到IP地址后,浏览器就可以发起与服务器的三次握手
建立连接后,就开始组装http请求,发送请求。
接收端收到请求后,开始处理请求解析请求头中的数据,并生成对应的响应数据,给发送端返回响应数据。
浏览器收到响应后,会通过响应头类型,解析对应的数据报文。
补充:上边2中从浏览器中获取域名的步骤。
浏览器中输入:chrome://net-export/
打开对应文件搜索你想找的域名即可。
四、TCP协议
4.1 TCP协议描述
面向连接的,可靠的,基于字节流的传输层通信协议
4.2 TCP协议特点
基于连接的:数据传输之前需要建立连接
全双工的:双向传输
客户端和服务端可以互相双向写数据
字节流:不限制数据大小,打包成报文段,保证有序接收,重复报文自动丢弃
发送方:每次传输不限制数据大小,不是一次性将所有的数据都传输,会将数据切分成多个片段,并进行排序,通过网络介质传输给接收方。
接收方:不同的数据包会通过网络不同的路线传入接受方,因此接收方收到的数据有可能是乱序的,因此需要对数据包进行重排序。
流量缓冲:解决双方处理能力的不匹配
可靠的传输服务:保证可达,丢包时通过重发机制实现可靠性
拥塞控制:防止网络出现恶性拥塞
当网络环境比较差的时候,会控制报文大小减小传输速率。
4.3 TCP连接管理
4.3.1 TCP连接四元组
四元组分别为:源地址、 源端口、 目的地址、 目的端口
4.3.2 TCP头部格式
序列号:在建⽴连接时由计算机⽣成的随机数作为其初始值,通过 SYN 包传给接收端主机,每发送⼀次数据,就累加⼀次该数据字节数的⼤⼩。⽤来解决⽹络包乱序问题。
确认应答号:指下⼀次期望收到的数据的序列号,发送端收到这个确认应答以后可以认为在这个序号以前的数据都已经被正常接收。⽤来解决不丢包的问题。
控制位:
ACK:该位为 1 时,确认应答的字段变为有效,TCP 规定除了最初建⽴连接时的 SYN 包之外该位必须设置为 1 。
RST:该位为 1 时,表示 TCP 连接中出现异常必须强制断开连接。
SYN:该位为 1 时,表示希望建⽴连接,并在其序列号的字段进⾏序列号初始值的设定。
FIN:该位为 1 时,表示今后不会再有数据发送,希望断开连接。当通信结束希望断开连接时,通信双⽅的 主机之间就可以相互交换FIN位为 的 TCP 段。
URG:当URG=1时,表明紧急指针字段有效。它告诉系统此报文段中有紧急数据,应该尽快传送,而不按照原来的排队序列来传送。
PSH:推送(PuSH),当两个应用进程进行交互式的通信时,有时一端的应用进程希望在键入一个命令之后就能立即收到对方的响应。在这样的情况下,就可以使用推送操作,此时,发送方将PSH置为1,并创建一个报文发送出去,接收端接受到该报文,发现PSH为1,就尽快交付接受应用进程,而不用等到整个缓存都满了之后再向上交付。
紧急数据指针:当发送端需要发送一些紧急数据时,可以设置紧急指针来指示接收端,在接收到该指针之后尽快处理这些数据。紧急指针的值是一个相对于当前序列号的偏移量,用于指示紧急数据在整个数据流中的位置。
窗口大小:当前服务器缓存可接受的数据报文大小。
4.4 TCP 三次握手
说明:
服务端启动后会监听特定端口,处于监听状态,等待客户端的请求。
客户端发起请求,变更成发送状态,此时会在请求中携带同步序列号 x。
服务端接受到请求后,保存客户端对应的信息,并发送确认收到应答消息,此消息的应答码需要在x的基础上加1,此时服务端处于等待客户端确认状态。
客户端收到服务端确认后,状态变更为已连接,客户端也需要给服务端回复确认收到,此时应答码为服务端确认码y+1。
服务端收到客户端确认消息后,状态变更为已连接。
连接建立成功,此为三次握手。
握手过程中会消耗序号,建立链接后不会消耗。
以下是三次握手的示例过程:
4.5 TCP 四次挥手
说明:
客户端和服务端都可以主动发起关闭连接。
图中为客户端发起关闭连接,首先客户端发起 FIN 关闭连接请求。
服务端收到关闭请求后,先回复收到关闭请求的确认消息给客户端,此时客户端处于等待关闭2状态,等待服务端完成收尾工作,服务端完成收尾(剩余未完成传输数据同步),执行关闭连接方法,并给客户端发送FIN 关闭链接请求。
客户端收到关闭请求后,给服务端回复确认关闭应答消息,服务端关闭,客户端处于等待状态,此时需要等待两个最大请求时长(防止服务端由于网络原因未收到应答消息,服务端会重试发送FIN消息)。
等待时间到期后关闭连接。
4.5 TCP 可靠性传输
4.5.1 停止等待协议
描述:没传送一个报文,服务端都回复一个确认消息,效率低下。
4.5.1 重传机制
4.5.1.1 ack丢失
描述:如果出现丢包如何处理
4.5.1.2 报文丢失
4.5.2 滑动窗口协议与累计确认(延时ack)
说明:
服务端收到后只收到,1,2,4。 3丢失,此时服务端确认只确认到2。
客户端收到确认后,从3开始在滑动下一个窗口,进行数据传输。
参考文献
OSI参考模型: https://baike.baidu.com/item/OSI%E5%8F%82%E8%80%83%E6%A8%A1%E5%9E%8B/708028?fr=aladdin
HTTP状态码: https://baike.baidu.com/item/HTTP%E7%8A%B6%E6%80%81%E7%A0%81?fromModule=lemma_search-box
TCP协议: https://baike.baidu.com/item/TCP/33012?fr=ge_ala
TCP与UDP的可靠性传输: https://zhuanlan.zhihu.com/p/636141175
服务器托管,北京服务器托管,服务器租用 http://www.fwqtg.net
背景 在GreatSQL主从复制环境中,有时候可能会出现一些误操作,将本应该写入到主库的数据写入到了从库,导致主从数据不一致,影响数据同步。是否可以将写入从库的数据同步写入主库呢? 测试环境 角色 IP地址 数据库开放端口 版本 主库 192.168.137.…