三次握手
建立连接,就是通信双方,各自保存对端的信息~
谁发起,谁就是客户端
客户端和服务器各自给对方发送syn,再各自给对方返回一个ack一共,其实是4次交互~~
关键在于,中间的两次交互ACK和SYN可以合并成一个网络数据。
ACK:6个标志位第二位为1
SYN:6个标志位第五位为1
所谓的合并,就是让这一个TCP数据报,报头中,同时把两个bit都设为1。
三次握手的时候,相当于,双方各自让对方保存自己的信息得是两边都把对方的信息保存好,连接才算是建立完成。
三次握手的意义:
1.三次握手,相当于"投石问路"。
保存对方的信息,就是对方的ip和端口
在正式传输业务数据之前,先确认一下通信链路是否畅通
问题:TCP如何保证可靠传输?
先建立连接然后才传输业务数据,通过确认应答和超时重传然后,才能建立连接,是在传输业务之前,就要先进行握手好了,才能进行后续的传输
应用层,应用程序
传输层 网络层,操作系统内核
数据链路层,驱动程序
物理层,硬件设备
2.通过三次握手,来确认通信双方,发送能力和接受能力都是正常的
进行三次握手,本质上就是完成上述确认的过程保存对方的信息,就是对方的ip和端口
三次握手分为两次握手行不行
不行,服务器这边对于发送能力接受能力的认知是不完整的,需要第三次交互,把客户端掌握的完整情报,告知给服务器。
3.三次握手过程中,还需要协商一些必要的参数。
通信双方共同商量一下,有的参数,不是单方面就能确认的,需要双方共同来确定出来的。
TCP通信时使用的序号就是协商出来的。
通常情况下,第一次连接和第二次连接协商出来的序号是不同的。
如果一个数据,再通信过程中,迷路了,等到达服务器的时候已经断开了,那么这个服务器会直接丢弃掉这个数据(通过序列号即可判断)。
小结:
三次握手主要的意义三个方面
1.投石问路,确认通信路径是畅通的
2.验证通信双方的发送能力和接收能力
3.协商必要的参数,比如起始序号
两个重要的状态:
1)LISTEN:服务器进入的状态.端口绑定成功,服务器准备就绪,随时可以有客户端连上来
2)ESTABLISHED:连接建立完成,随时进行数据通信了,
四次挥手
四次挥手,则不一定.客户端和服务器都可以主动发起~~
啥叫“断开连接"通信双方,把之前保存的对方信息,给删了~^
四次挥手,中间两次能否合并?如能!!!
有时候能合并,有时候不能合并
常规情况下是不能合并特殊情况下能合并
但是TCP中还有一个机制,延时应答.(要回复ack,但不是马上,而是稍等一会.)。这样就完成了三次了
经典面试题,
有的时候,可能会在服务器这边见到大量的CLOSE_WAIT说明代码大概率有bug了,代码很可能忘记调用close了或者close的调用不够及时。
延迟应答
ack不会立即返回,而是稍等一会再返回,
延时的目的是提高传输的效率。
决定传输速度最关键的因素,窗口大小
在能够承受的前提下,尽可能的提高窗口大小
通过延时,给应用程序腾出更多的时间。
如果没有延时应答,即立即返回ack就会传输多少,占用多少,但是如果传输过程中,自带延时,进行消化就会消费了一部分,这样的话应用程序就不会有太大的压力,提高了效率。
此处延时时间,有两种方式
1)按照一定的时间来指定延时这俩策略是结合使用
2)按照收到的数据量
捎带应答
一问一答的形式
由于延时应答的存在,ack不一定立即返回.在ack稍等这一会的时候,正好,就要返回响应数据此时,就在响应数据中,tcp中的ack这一位设置上,把确认序号/窗口大小都设置上.
9.面相字节流
在字节流读写数据的场景中,会涉及到一个非常关键的问题,粘包问题。
1)使用分隔符定义任意字符都可以.只要字符在请求数据中是不存在的
2)约定包的长度
服务器调用read来读取请求由于字节流的特点,读的时候咋读都行,一次可以读一个字节,也可以一次读若干个字节...此时,服务器无法区分,从哪里到哪里是一个完整的单词~~
三次握手的时候,通信双方分别给对方一个起始序号(通常不同)
异常情况
1.其中某一个进程崩溃了.
进程崩溃也好,正常结束也好,操作系统,都能够回收释放对应的PCB,可以释放里面的文件描述符表。也就相当于调用close.
2.某个主机被关机(正常流程的关机)
可能挥完手,也可能没有
主动触发FIN了,之后的流程没走完,系统就已经关机了
A和B建立TCP连接,A这边关机了,A关机之前,告诉B,FIN~~
B这边收到了FIN,B返回ACK,代码进入下一阶段流程,准备发送FIN,
此时如果A已经关机了,意味着B接下里的FIN就会反复重传几次~~
此时B反复重传几次,没有ACK,还是会继续吧A给删掉了~A都已经关机了,之前保存的B的消息,自然也没了(内存)
3.某个主机电源掉电
A和B通信,A突然掉电了,
A无法做出任何反应,,就无了!
a)B是发送数据方
B接下来发的数据,都不会有ack了.
B就会触发超时重传.重传几次之后,发送复位报文(RST).RST也没有响应,B就会单方面删除保存的A的信息。
b)B 是接收方.
接收方,无法知道对方啥时候给我发数据~~当A沉默了之后,B也不知道A是暂时暂停一会,还是A挂了~~B在一定时间之内没收到A的数据之后,就会触发心跳包。
心跳包:1)有周期2)没有心跳就挂了~~
心跳包是没有载荷的数据包。
B给A发送心跳包,如果A正常,A就会回应ACK,如果没有A,B就没有收到ack。
发了多次以后,A没有反应后,B就会主动释放连接。
tcp虽然内置了心跳包,但是这个心跳包,周期比较长,指望通过这个心跳发现对端挂了,往往需要分钟级别这样的时间。
这样的心跳包可以自己写这样的就能自己规定反馈时间,提高效率。
4.网线断开
A和B之间建立TCP连接A和B之间的网线断开了.
比如,A是发送方,B是接收方
A的角度:就会触发超时重传,触发RST,单方面删除信息
B的角度:就会触发心跳包,对方无响应,单方面删除信息.
网络原理的分布
1.确认应答2.超时重传3.连接管理4.滑动窗口5.流量控制6.拥塞控制7.延时应答8.悄带应答9.粘包问题10.异常情况
如果时间UDP的可靠传输呢?(相对于UDP,TCP的优点)
通过应用程序的代码完成可靠传输的过程
1)引|入确认应答(ack)
2)引I入序号+确认序号
3)引|入超时重传~
PSH催促对方尽快给自己给回应。
URG是紧急标志位。当URG=1时,表示紧急指针有效,即此报文时紧急报文优先发送,不再按序发送。此时与后面的紧急指针配合,向后偏移至此报文处,发送此报文。
紧急外数据传输
正常的TCP传输的数据,可以认为是"业务数据除了业务数据之外,还有一些特殊的,用来控制TCP自身工作机制特殊的数据包
IP协议
网络层主要做的事情:1.路径规划(路由选择)2.地址管理。
IPv4的结构
最短是20字节~,IP报头最长就是60字节.
tpye of service
8位服务类型(TypeOfService):3位优先权字段(已经弃用),4位TOS字段,和1位保留字段(必须置为0).4位TOS分别表示:最小延时,最大吞吐量,最高可靠性,最小成本.这四者相互冲突,只能选择一个.对于ssh/telnet这样的应用程序,最小延时比较较重要;对于ftp这样的程序,最大吞吐量比较重要,
最小延时:传输过程中消耗的时间最短
最大吞吐量:单位时间内传输的数据尽可能多
最高可靠性:降低丢包的概率
最小成本:比较节省系统开销
64kb
如果携带的载荷,超出长度上限,IP就会自动拆分成多个数据包,每个数据包携带一部分发送到对方之后,再拼接好。
整个IP数据包的长度
报头+载荷
总长度,去掉IP首部长度,剩下的就是TCP数据包的总长度去掉TCP报头长度,剩下的就是载荷长度了。
,如果数据很长,超出了64kb的上限
就会把数据拆分成多个部分,使用多个IP数据包发送
udp也能配合ip使用,但是udp解析的时候也就最大能有64kb
他只能解析红色框内的数据,无法解析红色方框外的数据,所以就算用IP包装也没有意义,只是画蛇添足而已。
16标识:用来区分哪些数据包要进行合并~
3位标志:只有2个有效其中一个用来表示,该数据包是否是触发了拆包的效果(是否需要组包)13位片偏移:若干个要拼接的数据包的先后顺序。(防止后发先至,数据混乱)。
IP数据包要在网络上转发限制一个数据包在网络上转发的最大次数。
这个次数每次经过一个路由器的转发,就要-1减到0了这个数据包就要丢弃掉。
这里背后,有一个"六度空间”理论(来自于社会科学)
就是指数方式的递增,我认识的人->认识的人认识的人->.....套娃套6次那么数据就是很可怕的。
路由器转发IP数据包的时候,每个路由器,其实不了解整个网络的全貌,
如果他的认识的人没有你发送的ip地址那么他就会发送给最“神通广大”的路由器,他们根据路由表来判断他的走向。
最“神通广大的”路由器
这里就描述了载荷部分是哪种协议的数据包交给TCP还是UDP还是其他的协议~~
传输层=>应用层:端口号来区分
网络层=>传输层:报头中有这个8位协议字段,不同的取值就对应不同的传输层协议。
数据链路层=>网络层:报头里,类型字段,区分是IP数据包,还是其他的数据包.
校验和,只是针对IP首部进行校验载荷部分不关心
载荷部分,UDP/TCP,都有各自的校验和IP只需要管好自己即可
0-42亿9千万。
32位的整数表示为“点分十进制“方式
IP地址不够用的处理方式:
方案一:动态分配IP地址
某个设备,上网就分配,不上网就不分配
方案二:NAT机制.网络地址映射
首先,把IP地址,分成两个大类
1)私网IP(局域网内部使用)
私网IP是通用的下面三种。
10.*
172.16-172.31.
192.168.*
2)公网IP(广域网使用的)
此时约定,公网IP唯一
私网IP允许在不同的局域网中重复~~
当前虽然能上网的设备非常多
但是绝大部分都是在局域网中的
局域网1中的设备ip可以和局域网2中的设备ip重复的
如果引入上述私网IP,如何进行通信呢?
1)同一个局域网内部,设备之间通信由于一个局域网内部的设备之间的IP是不能重复的.此时这些设备都能正常相互交互~~
2)广域网设备和广域网设备之间通信要求广域网中的设备IP本身就是唯一的.也能正常交互~UDF
3)局域网1中的设备A尝试访问局域网2中的设备B
这种情况认为不允许进行访问!!
4)局域网中的设备主动访问广域网设备这个过程中,NAT机制就开始发挥作用了.(下节课再画这个.)
5)广域网设备主动访问局域网设备(这种情况也是不允许进行访问的!
CLOSE_WAIT:等待应用程序调用close方
但是如果程序出现问题,close没有及时调用或者压根忘记调用
就可能使机器上出现大量的CLOSEWAIT
TIME_WAIT:存在的意义,就是为了应对最后一个ACK丢包这样的场景~~
客户端在收到服务器返回的fin之后,不能立即释放tcp连接.(如果立即释放了,后续一旦对端重传了fin,此时客户端就无法应对了,无法返回ack了)
因此客户端这边就需要有一个特殊的状态TIME_WAIT状态来等待可能到达的fin重传的数据.
TIMEWAIT状态不是持续的,而是有,潜合词就是,最后个ack,已经被对方收到了,就不会重传fin此时TIME_WAIT就可以释放了.
CLOSEWAIT不一定是服务器处于的状态(被动接受的一方)
TIMEWAIT也不一定是客户端处于的状态(主动发起的一方)
TIME_WAIT持续一段时间,等待对方的FIN的重传.
理论上,网络中两个节点之间传输数据的最大时间
这个数值通常是1min(也是可配置)
意味着2min之后,还没有收到重传的FIN,就认为对方不会重传了
面试题:如果发现服务器端出现大量的TIMEWAIT,如何处理?
出现大量TIME_WAIT,说明服务器这边触发了大量的主动断开TCP连接的操作.
这个操作对于服务器来说,很可能是不科学的一般都是客户端主动断开连接。
4.滑动窗口
TCP除了保证可靠传输之外,也希望能够尽可能高效的完成数据传输滑动窗口,就是一种,提高传输效率的机制~
不引入滑动窗口,数据传输过程,A这边每次收到一个ACK才发送下一个数据,低效。
把一条一条发送=>批量发送,虽然是鼻梁发送,但是还是要等待ack。
滑动窗口:不等待ack,批量发送多少数据,这个过程就是称为“窗口大小”。
当前批量发了这四组数据等待着四组数据的ack
1001-2000的数据得到了确认后,就会发送新的ack了,此时1001-2000的数据也就标记成灰色了,
滑动窗口中发了4组数据之后,不是等到4个ack都回来才继续发送新的数据
而是收到一个ack,就往后发一个新的。这样就形成了滑动窗口。
如果发送方收到了3001的ack之后,那就说明了3001之前的数据都收到了。
滑动窗口丢包了怎么办?
情况一:数据包已经抵达,ACK被丢了,
上述情况~
情况二:数据包就直接丢了
虽然主机A仍然在继续给B往后发送接下来的每个数据,B都是再向A索要1001这个数据包~~
次数也是有一定确定性的(不一定是3次,都是可配置的).
A这边连续收到若干个1001这样的ack,明白了,原来是1001-2000这个数据丢了!!
上述针对丢包的处理,整个过程都是很高效的
1)对于ack丢失,不做任何处理
2)对于数据丢失,只需要把缺失的数据重传即可.其他的数据不必重传.
快速重传(滑动 窗口下,搭配的丢包处理机制)
超时重传,和快速重传,相当于两种不同的重传机制,是否是冲突的呢??
当然不冲突!不同情况下,采取的重传策略.快速重传相当于超时重传在滑动窗口下的特殊变种
如果你TCP传输的数据比较少,此时就不会触发滑动窗口仍然按照超时重传方式来解决丢包问题
如果你短时间传输大量的数据,此时才能触发滑动窗口此时才触发快速重传,按照ack反馈的次数来解决丢包问题,
滑动窗口,其实是“亡羊补牢”的机制
为了保证TCP的可靠性,牺牲了效率.
5.流量控制
滑动窗口,涉及到关键概念,窗口大小(一次批量多少个数据,数据量)。
窗口大小是可变的.窗口越大,单位时间发的数据就越多,效率就越高窗口越小,单位时间发的数据就越少。
这样的机制就是流量控制。
衡量接收方的处理速度呢??
接受方,有一个接受缓冲区(阻塞队列)。
以空闲空间的大小作为发送方数据的窗口大小,吧这个数值,告诉发送方。
这个东西只会在ack报文中生效含义就是接收方接受缓冲区,,空闲空间大小
选项中,包含特殊属性“窗口扩展因子”。
6.拥塞控制
和流量控制类似,都是和滑动窗口搭配的机制
流量控制是,站在接收方的角度,影响发送方的速度。
跟木桶效应相似。
链路上的任何一个节点,性能瓶颈都会制约发送方的发送速度!!
任凭你中间结构多复杂,tcp都把他们视为一个整体....然后通过“实验”的方式,找到一个合适的窗口大小(发送速度)
刚开始,按照小的速度,小的窗口来发送数据,如果没有丢包现象就加速,加窗口大小,
达到一定值的时候,设备达到瓶颈期,出现了丢包现象,那么就减小窗口大小,然后在反复确认后确定一个合适的大小,达到动态平衡。
如果两个窗口出现了一个为500byte的窗口 那么就要听500byte (较小的)。
一个为1kb的出窗口
1.刚开始以比较小的窗口来传输数据
主要因为刚开始不知道网络是否拥堵。
2.按照指数方式扩大窗口(*2)指数增长,(这里的“慢”说的是刚开始窗口大小比较小,传输速度慢,而不是窗口大小的变化速度慢曼(指数增长非常快的)
3.指数增长过程中,达到某个阔值,就要变成线性增长.(+n)
4.线性增长,也是增长,发送速度越来越快增长到一定程度,就会出现丢包,此时,发送方大概就摸到了网络大概的能力是在啥样的水平~此时就会立即把窗口变小(发送速度减下去)
5.缩小有两种方式
1.直接缩到底(回到了最初慢启动的时候)接下来指数增长-线性增长。废弃了
2.缩到出现丢包时窗口大小一半这样的位置接下来线性增长。