前言
衡量Web页面性能的时候有一个重要指标,叫做’FP’,first paint页面初次绘制的时长,
这个时间越短,证明页面加载速度,计算,绘制等有很高的效率,想要优化web页面,首先要对网络有充分的理解.首先要对协议,不管是http还是tcp/ip协议都要有足够了解
一个数据包的旅程
数据要在网络中传输,首先要遵守一个规则,就像你开车上路要遵守交通规则一样,而这个规则,我们称之为协议,我们现在只关注osi模型中的较上层的协议,非常底层的协议和工作原理大家感兴趣可以自己了解
互联网上不同的在线设备都有一个唯一的地址,地址是一个数字,你可以想象成一个家庭住址,你只要知道了一个家庭的具体位置,就可以发送包裹了这样才能给别人寄快递嘛
ip地址(网络层)
计算机地址就称为ip地址(这是一个逻辑地址,物理地址是mac由网卡厂家提供,物理地址一般在数据链路层发挥作用,想到了提一嘴)
访问任何一个网站,实际就是你这台计算机向另一台计算机请求资源和信息,如果你想要把一个数据包从主机A发送给主机B,那么在传输之前,在网络层,会给这个数据包加上一个ip头的数据结构,ip头包含一些信息:目标地址,源地址,ip协议版本,生存时间等,这样才能正确寻址,而且目标计算机也能找到你
流程如下:上层数据包到达网络层->添加一个ip头传给继续传给下层->下层一系列操作(纠错)传输->接收下层传过来的数据包->网络曾解析ip头->传给目标计算机上层
udp,tcp(传输层)
ip是比较底层的协议,他只负责将数据包传输给指定计算机,不知道将其传给哪个应用程序(端口),是交给lol还是永杰无间?因此基于ip协议上开发了能和应用打交道的协议udp和tcp
udp
用户数据包协议,重要的一个信息就是端口号,端口号其实就是一个数字,打个比方:ip负责将你的快递传到你的小区(就把小区当作你的计算机吧),但他不会理会你的具体地址,几栋几楼啊之类的,派送员就是个工作在传输层的协议,将你的快递送到你本人手上,udp和ip一样,处理数据包一样是在数据包前面加一个udp头,包含目的端口号,源端口号等信息,
流程:
上层数据包到达传输层->按udp协议添加udp头->传输层数据包到达网络层->添加一个ip头传给继续传给下层->下层一系列操作(纠错)传输->接收下层传过来的数据包->网络层解析ip头->传输层解析udp头->传给目标计算机指定端口
udp在传输的时候会有各种因素导致数据包出错和丢失,虽然udp本身有校验数据正确的算法,但是他没有重传机制 ,而是直接丢弃现在的包,udp发送之后也不会管数据是否到达目的地,他主要优点就是传输速度特别快,反正一股脑的把数据发出去就完事,不用管你收没收到,应用在游戏领域很广泛,比如我玩lol,打团的时候不可能因为你的某个数据包出错了整个游戏等待你那个数据包重传吧?
TCP
对于浏览器请求,或者邮件这类要求数据务必可靠的应用,那就只能使用可靠的TCP了
TCP特点就是
1.对于数据包的出错丢失,提供重传机制,
2.TCP引入了数据包排序机制,将文件分割成数据包传输过来之后,通过排序保证把乱序的数据包重新整合成一个有序的文件
和udp头一样,tcp头除了包含端口信息之外还包含了用于排序的序列号,来重排数据包
可能有人会问了:为什么TCP协议可靠啊?
首先,连接的时候:3次握手来完成准备工作
- 首先客户端发送给服务端一个SYN报文(什么是SYN等会说),报文中指明了客户端的初始化序列号ISN.此时客户端处于syn_sent(同步发送)状态 SYN报文中首部同步位SYN=1,初始化序号seq=x(x是算法随机生成的,一般跟时间有关),消耗掉一个序号1
- 服务器接收到客户端的SYN报文后,会以自己的SYN报文作为应答,我们也称之为确认报文ACK报文,并且也指定了自己的初始化序列号ISN(s),并且把客户端的ISN+1作为ACK的值,表示自己接收到了客户端的SYN,此时服务器处于SYN_RCVD状态,确认报文段中SYN=1,ACK=1,确认号ack=x+1,初始序号seq = y
- 客户端接收到服务端的确认报文后,同样发送一个确认报文ACK,同样的,把服务端发来的ISN+1作为ack的值,表示收到,然后客户端开启连接状态,服务器收到这个报文后也为开启状态.ACK =1 ,确认号ack=y+1,seq=x+1(刚开始是x嘛,现在序号+1没毛病吧)
什么是SYN报文:当两台计算机在TCP连接上进行会话时,连接一定会首先被初始化。完成这项任务的包叫作SYN。一个SYN包简单的表明另一台计算机已经做好了会话的准 备。只有发出服务请求的计算机才发送SYN包.SYN 同步序号的英文的所学
来了来了,经典问题来了
为什么三次握手?疫情阶段我两次不行嘛?
首先得搞清楚,tcp必须是可靠的(理论上),那就表示接收方和发送方必须能正常通信,
就好像大家面试的时候
你:歪歪歪?面试官能听到吗?
面试官:我能听到?同学你能听到嘛?
你:可以的,…
这就是一个完整流程,也是3次对吧?如果2次呢?
你:歪歪歪?面试官能听到吗?
面试官:我能听到?同学你能听到嘛?
假如你耳机有问题面试官不知道你能不能听到他说话啊
这就芭比Q了,到时候你一直讲,面试官一直听,但是他说什么你听不到,你就在那瞎讲…
所以3次握手就是保证双方能正常的通信
半/全连接队列
服务器第一次收到客户端的SYN之后,此时双方还没有完全建立其连接,服务器会把此种状态下请求连接放在一个半连接队列里,如果完成了三次握手,就取出这次请求放在全连接队列里,半连接队列满了就可能造成丢包现象(所以也不是完全可靠)
半连接状态下,如果没有收到客户端继续发来的请求,就会重传确认报文,还没收到就继续重传,每隔一段时间(时间是指数递增的)重传,重传超过指定次数,连接就会释放
为什么ISN是不固定的呢?
这种问题其实我们只要举反例就行.如果他是固定的,网络攻击者猜出来了怎么办?猜出来之后他截获你的数据包重新排序那么你的信息不就全丢了?还有就是如果是固定的,那么你两个间隔时间很短的连接请求,第一个连接的SYN报文延迟了他在服务端收到第二个SYN之后才收到第一个SYN,这时候排序怎么办?听连接1的还是连接2的?所以ISN不固定,一般是没4ms加1,跟时间有关
三次握手中可以携带数据吗?
还是我之前的那个面试的例子…
首先肯定是设备调试吧,不可能一上来就巴啦一大堆你的信息,管你设备好坏啊
所以第一次和第二次的握手不能携带数据
第三次可以携带,因为第三次的时候设备已经确认好没毛病了,当然可以发送数据了
如果第一次和第二次可以携带数据,设备有问题呢?那对面没收到没回应你,你一直重传la浪费资源吗? 或者说可以携带数据,我想攻击你我伪造一堆假的ip地址疯狂向你发垃圾数据,反正可以携带嘛,我管你连接建没建立好,发就完事了,那就会出大乱子了
以上是一些经典的问题,然后呢,tcp传输时,会在本地缓存刚发出去的报文,等待服务端发来接收报文,如果服务端没有发来,或者说发来的报文有错误,就把刚刚缓存的报文重发,如果确认无误,删除缓存,发送下一个报文,缓存重复操作.这就是其可靠的基本原理了(当然还有很多,滑动窗口,流量控制,校验和等等.我就不说了)
4次挥手
建立连接需要3次握手,释放连接需要4次挥手,这是由于TCP的半关闭造成的,半关闭就是tcp提供了连接的一端在结束它的发送后还能接收令一端的数据,(就是我不发送数据了,但我还能收到你的数据)
- 第一次挥手 客户端发送fin报文,请求释放连接, FIN=1 序号seq=u ,之后就不再发送数据了,进入终止等待状态
- 第二次挥手,服务端接收到了FIN之后,发送ACK确认报文,且把序号值加1(实际还是走的握手流程) 然后服务端进入关闭等待状态 ACK=1,ack = u+1 seq = v
- 第三次挥手 服务端也想断开连接了 和第一次挥手一样发送fin报文 FIN=1,ACK = 1 seq = w, ack = u+1
- 第四次挥手,客户端发送确认报文 ACK = 1,seq = u+1,ack = w+1,然后客户端进入等待状态,等待2个报文最大存活时间后,彻底释放
为什么挥手需要4次呢?
前面说了tcp的半关闭性质,服务端收到客户端的关闭请求后,只是说客户端没有数据要发送了,此时客户端还是能听到服务端的消息,服务端表示:’‘好的,你没有要说的了,等我把我要说的话说完’’ 然后才会说’‘好了,我也没话说了’’,然后呢?客户端点头,服务端点头,拜拜
为什么还需要等待2个报文最大存活时间呢才关闭呢?
这种问题方向上只要往网络拥塞和网络安全上想准没问题
如果客户端发送的ACK确认报文出错了堵车被拥塞了呢?
那么服务端就没有收到那个ACK确认报文,此时会重传一个FIN报文
如果客户端关闭了,那么客户端收不到这个FIN报文,那么服务端就在那当舔狗一样一直发消息没得回应就造成了资源浪费
好了,现在让我们回顾一下TCP简单流程:
三次握手->传输数据(涉及重传等机制)->四次挥手
看到这里就明白了为什么udp和tcp速度差异大
tcp每次都要确认数据无误,而udp像个渣男只发信号不负责
最后分享一个推上看到的有意思的图片(我不是老色p)