小伙伴们可以先了解TCP协议:面向连接的传输层协议——TCP协议
在TCP/IP协议中传输层具有四个主要任务:
传输层在进程和进程之间进行数据传送的工作,它将应用层的数据进行分装以后,产生一个一个 process(进程);
这些进程通过复用技术,将它们进行分装,分装为 message;
接着送到网络层,进行IP分包以后,进入到网络链路中进行处理;
而在接收端,可以经过网络层到达传输层以后,经过解包解封用的技术,将这些进程还原成一个一个的process。
过程如下图:
TCP协议工作的三个阶段:(买家和卖家例子)
连接建立:建立一个连接需要三次握手
数据传输:连接建立后即可进行数据传输。
买家和卖家之间货物的收发过程。
当买家收到货物以后,进入到TCP的第三个阶段
连接释放:终止一个连接要经过四次挥手
TCP协议的 三次握手 和 四次挥手:
注:
seq:"sequance"序列号;
ack:"acknowledge"确认号;
SYN:"synchronize"请求同步标志;
ACK:“acknowledge"确认标志”;
FIN:"Finally"结束标志。
三次握手:
第一次握手是建立连接的时候
客户端发送一个SYN的包到服务器,并且进入到SYN SEND 的状态,等待服务器的确认;
第二次握手 就是服务器收到SYN包以后,必须给客户一个SYN的确认,
同时自己也会发一个SYN的包,也就是SYN+ACK这样的一个确认包,
此时服务器进入到SYN RECEIV的状态;
第三次握手 客户端收到服务器的SYN+ACK的包以后,向服务器发送一个确认包ACK,
当这个包发送完毕以后,客户端和服务器之间就建立起了它们的TCP连接,
进入到了ESTABLISHED的状态,完成了三次握手的工作。
当双方之间完成了三次握手的工作,建立起它们的TCP链路以后,就可以来进行数据收发的工作了。
当数据的收发完成以后,双方之间希望将它们的连接进行消除,这时,双方要经过一个四次挥手的过程。
总结:
首先Client端发送连接请求报文,Server端接受连接后回复ACK报文,并为这次连接分配资源。
Client端接收到ACK报文后也向Server段发生ACK报文,并分配资源,这样TCP连接就建立了。
三次握手状态图:
A 向 B 发出连接请求报文段,
其首部中的同步位SYN = 1,并选择序号seq = x,
表明传送数据时的第一个数据字节的序号是x;
B 收到连接请求报文段后,
如果同意,则发回确认,使 SYN = 1,ACK = 1,确认号ack = x﹢1,选择的序号 seq = y;
A 收到此报文段后向 B 给出确认,
其 ACK = 1,确认号ack = y﹢1,并通知上层应用进程,连接已经建立。
B 收到主机 A 的确认后,也通知其上层应用进程TCP连接已经建立。
四次挥手:
假设 客户端首先向服务器端发起中断连接请求,
也就是说 客户端向服务器端会发送一个报文,这个报文是FIN报文。
Server端接到FIN报文后,它的意思是说 "我的客户端这里没有任何数据要发送给你了",
但是如果你还有数据没有发送完成,则不必急着关闭Socket,可以继续发送数据。
服务器端会给客户端一个ACK的回馈,
这个回馈就是告诉客户端,"你的请求我收到了但是我还没有准备好,请你进一步等待我的其他消息"。
这时客户端就会进入到FIN_WAIT的状态,在这个状态中,它继续等待服务器端的FIN报文。
当服务器端确定数据已经完全发送完毕以后,就会向客户端发送一个FIN的报文,
这个FIN的报文告诉客户端,"服务器端的数据也完成了,现在可以关闭连接了"。
当客户端收到服务器端的FIN报文以后,就知道可以关闭连接了,
但这时它还不是很相信网络,怕服务器端不知道要关闭,
所以当客户端发送ACK以后,进入到TIME_WAIT状态;
如果服务器端没有收到它的ACK,则可以进行重传。
当服务器端收到ACK以后,就知道可以断开连接了,
这时客户端会等待一个RMSL(最大报文段的生存时间),等待这样一个时间以后,
如果依然没有收到服务器端的任何回复,就说明服务器端已经正常关闭。
服务器端已经关闭了,客户端也可以关闭连接了。
四次挥手状态图:
数据传输结束后,通信的双方都可释放连接。
例如:
A 的应用进程先发出连接释放报文段,并停止再发送数据,主动关闭TCP连接。
A 把连接释放报文段首部的FIN = 1,其序号seq = u,等待 B 的确认。
B 发出确认,确认号ack = u+1,而这个报文段自己的序号seq =v。
TCP服务器进程通知高层应用进程,从A到B这个方向的连接就释放了,TCP 连接处于半关闭状态。
若 B 发送数据,A 仍要接收。
若 B 已经没有要向 A 发送的数据,其应用进程就通知TCP释放连接。
A 收到连接释放报文段后,必须发出确认,
在确认报文段中ACK = 1,确认号ack=w﹢1,序号seq = u + 1。
TCP连接必须经过时间 2MSL 后才真正释放掉,
2MSL的时间是为了保证 A 发送的最后一个ACK报文段能够到达 B。
防止“已失效的连接请求报文段”出现在本连接中。
A 在发送完最后一个ACK报文段后,再经过时间2MSL,
就可以使本连接持续的时间内所产生的所有报文段,都从网络中消失。
这样就可以使下一个新的连接中不会出现这种旧的连接请求报文段。
经典面试题:
为什么要三次握手?
在只有两次"握手"的情形下,
假设Client想跟Server建立连接,但是却因为中途连接请求的数据报丢失了,
故Client端不得不重新发送一遍;
这个时候Server端仅收到一个连接请求,因此可以正常的建立连接。
但是,有时候Client端重新发送请求不是因为数据报丢失了,
而是有可能数据传输过程因为网络并发量很大在某结点被阻塞了,
这种情形下Server端将先后收到2次请求,并持续等待两个Client请求向他发送数据...
问题就在这里,Cient端实际上只有一次请求,而Server端却有2个响应,
极端的情况可能由于Client端多次重新发送请求数据而导致Server端最后建立了N多个响应在等待,
因而造成极大的资源浪费!
所以,"三次握手"很有必要!
为什么要四次挥手?
试想一下,假如现在你是客户端你想断开跟Server的所有连接该怎么做?
第一步,你自己先停止向Server端发送数据,并等待Server的回复。
但事情还没有完,虽然你自身不往Server发送数据了,
但是因为你们之前已经建立好平等的连接了,所以此时他也有主动权向你发送数据;
故Server端还得终止主动向你发送数据,并等待你的确认。
其实,说白了就是保证双方的一个合约的完整执行!