1 预备知识
1.1 IP协议
IP协议是无连接的通信协议,他不会占用两个正在通信的计算机之间的通信线路,这样IP就降低了对网络线路的需求,每条线可以同时满足许多不同的计算机之间的通信需要。通过IP、消息或者其他数据会被分割为较小的独立的包,并通过因特网在计算机之间传送。IP负责将每个包路由至他的目的地,但IP协议没有确认数据包是否按顺序发送或者包是否损坏,所以IP数据包是不可靠的,需要由他的上层协议作出控制。
1.2 TCP协议(传输控制协议)
面向连接的、可靠地、基于字字节流的传输层通信协议
将应用层的数据流分割成报文段并发送给目标节点的TCP层
数据包都有序号,对方收到则发送ACK确认,未收到则重传
使用校验和检验数据在传输过程中是否有误
1.3 TCP报文头
TCP和UDP均不包含IP信息,但是包含了源端口和目的端口(端口属于传输层范畴)
两个进程在计算机内部进行通信可以有管道、内存共享、信号量、消息队列等方法。
通信前提:唯一的标识一个进程。本地通信中PID(进程标识符/进程号)来唯一标识进程,PID仅在本地唯一,两个进程在不同的计算机则可能重复。
IP+协议+端口号唯一标识网络中的一个进程。套接字Socket模式
1.4 TCP Flags:TCP控制位,由8个标志位来组成,每个标志位表示一个控制功能。
URG:紧急指针标志 1紧急指针有效;0忽略紧急指针
ACK:确认序号标志 1确认号有效;0报文中不含确认信息,忽略确认号字段
PSH:push标志 1是带有push标志的数据,指示接收方在接收到该报文段以后应尽快将该报文段交给应用程序,而不是在缓冲区排队
RST:重置连接标志 用于重置由于主机崩溃或者其他原因而出现错误的链接,或者用于拒绝非法的报文段和拒绝连接请求
SYN:同步序号 同于建立连接过程,在连接请求中SYN=1和ACK=0表示该数据段没有使用捎带的确认域,连接应答捎带确认则SYN=1和ACK=1
FIN:finish标志 用于释放连接,1表示发送方没有数据发送,即关闭本方数据流
2 三次握手和四次挥手
2.1 三次握手
现实场景简单理解:(自己是客户端,朋友是服务器)
我:在吗兄弟,出去玩?
兄弟:在的,你确定?
我:没问题
这三次握手然后成功建立交互出去玩!
2.2 四次挥手
现实场景简单理解:(自己是客户端,朋友是服务器)
我:再见了兄弟,我要回家了。
兄弟:你等等我收拾完咱们的东西再走啊!
兄弟:你确定不玩会儿?
我:不了,老婆叫我回家吃饭。
然后四次挥手结束。
3 备战面试面试题要说出这些
TCP三次握手和四次握手的工作流程是什么?为什么不是五次握手或者两次握手?
3.1 面试官心里分析
这个问题相当经典,大家可别以为就是考察应届生的,实际上在普通社招java面试中,一些大公司,很喜欢考察这个问题,尤其是后面第二个追加问题,让你聊聊为啥必须是三次握手,而不是两次呢?
3.2 tcp三次握手过程
详情理解:
在TCP/IP协议中,TCP协议提供可靠的连接服务,采用三次握手建立一个连接。
- 第一次握手:建立连接时,客户端发送同步序号SYN包(seq=j seq初始序号任意正整数)到服务器,并进入SYN_SEND状态,等待服务器确认;不能消耗
- 第二次握手:服务器收到SYN包,必须确认客户的SYN(ack=j+1) ,同时自己也发送一个SYN包(seq=k) , 即SYN+ACK包,此时服务器进入SYN_RECV状态;
- 第三次握手:客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(ack=k+1),此包发送完毕,如果携带数据seq+1,没有就不消耗客户端和服务器进入ESTABLISHED状态,完成三次握手。
解析:seq是序列号,这是为了连接以后传送数据用的,ack是对收到的数据包的确认,值是等待接收的数据包的序列号。 在第一次消息发送中,A随机选取一个序列号作为自己的初始序号发送给B;第二次消息B使用ack对A的数据包进行确认,因为已经收到了序列号为x的数据包,准备接收序列号为x+1的包,所以ack=x+1,同时B告诉A自己的初始序列号,就是seq=y;第三条消息A告诉B收到了B的确认消息并准备建立连接,A自己此条消息的序列号是x+1,所以seq=x+1,而ack=y+1是表示A正准备接收B序列号为y+1的数据包。
seq是数据包本身的序列号;ack是期望对方继续发送的那个数据包的序列号。
3.3 为啥不是2次或者4次握手呢?
现实场景简单理解:(自己是客户端,朋友是服务器)
我:在吗兄弟出去玩啊?(现在手机网不好卡主了。)
我(换个设备打电话):在吗兄弟出去玩啊?
兄弟:好,老地方见。------此时开始收拾东西准备出发
现在建立连接去玩。
过了几天...
我:【在吗兄弟出去玩啊?(现在手机网不好卡主了。)】这条信息wifi好了,又发出去了
兄弟:好,老地方见。------此时开始收拾东西准备出发
但是此时我并不知道要去玩,就让兄弟一直等着浪费资源,浪费时间!
假设两次握手就ok了,要是客户端第一次握手过去,结果卡在某个地方了,没到服务端;完了客户端再次重试发送了第一次握手过去,服务端收到了,ok了,大家来回来去,三次握手建立了连接。
结果,尴尬的是,后来那个卡在哪儿的老的第一次握手发到了服务器,服务器直接就返回一个第二次握手,这个时候服务器开辟了资源准备客户端发送数据啥的,结果呢?客户端根本就不会理睬这个发回去的二次握手,因为之前都通信过了。
但是如果是三次握手,那个二次握手发回去,客户端发现根本不对,就会发送个复位的报文过去,让服务器撤销开辟的资源,别等着了。
因为3次握手就够了,不需要4次或者5次浪费资源了。
3.4 tcp断开连接的4次挥手
TCP采用四次挥手来释放连接
第一次挥手:Client发送一个FIN,用来关闭Client到Server的数据传送,Client进入到FIN_WAIT_状态;
第二次挥手:Server收到FIN后,发送一个ACK给Client,确认序号为收到序号+1(与SYN相同,一个FIN占用一个序号),Server进入CLOSE_WAIT状态;
第三次挥手:Server发送一个FIN,用来关闭Server到Client的数据传送,Server进入LAST_ACK状态;
“挥手”是为了终止连接,TCP四次挥手的流程图如下(假设客户端触发Close)
第四次挥手:Client收到FIN后,Client进入TIME_WAIT状态,接着发送一个ACK给Server,确认序号为收到序号+1,Server进入CLOSED状态,Client在经过2MSL时间也会进入CLOSED状态,完成四次挥手。
MSL:最长报文段寿命,IFC793定义MSL为2分钟,而Linux定义为30秒
TCP连接必须经过时间2MSL后才真正释放掉