参考文献https://www.cnblogs.com/onepixel/p/7092302.html,这篇文章写得很好。
什么是TCP?
tcp是tcp/ip协议族中很重要的一个协议,位于第二层传输层,上层就是我们熟悉的http、ftp等应用协议,其兄弟协议是udp协议。
在上篇文章中有提到tcp/ip协议四层模型,分别是应用层、传输层、网络层、链路层,应用层直接面对计算机中的程序,http请求先到达应用层,应用层使用规定的格式,发送报文格式,接收报文格式等各种规范。完事再进入tcp位于的传输层。报文是在不同的计算机中间传输,每台计算机上有很多不同的应用程序,那怎么区分应用程序呢?每个应用程序都有相对应唯一的端口号,常见的有8080、20、3306等,通过端口号可解决这个问题。因此在传输层中引入了udp或者tcp协议,首部中包含发送方的源端口和接收方的目标端口。
udp协议比较简单,只是实现了数据的发送接收,没去考虑可靠性。为提高网络传输的可靠性,tcp莹然而生。tcp全称Transmission Control Protocol,传输控制协议。tcp是一种面向连接的、可靠性的、基于字节流的通信协议。可以说tcp是升级后更可靠的udp协议。TCP建立连接之后,通信双方都同时可以进行数据的传输,其次,他是全双工的;在保证可靠性上,采用超时重传和捎带确认机制。每次发送数据前都要进行可靠性连接,每个数据包都要确认,发送失败则重新发送。
为了保证传输的可靠性,TCP 协议在 UDP 基础之上建立了三次对话的确认机制,就是三次握手,也就是说,在正式收发数据前,必须和对方建立可靠的连接。断开传输需要四次挥手。
当你输入一个网址并按下回车键的时候,首先,应用层协议对该请求包做了格式定义;紧接着传输层协议加上了双方的端口号,确认了双方通信的应用程序;然后网络协议加上了双方的IP地址,确认了双方的网络位置;最后链路层协议加上了双方的MAC地址,确认了双方的物理位置,同时将数据进行分组,形成数据帧,采用广播方式,通过传输介质发送给对方主机。而对于不同网段,该数据包首先会转发给网关路由器,经过多次转发后,最终被发送到目标主机。目标机接收到数据包后,采用对应的协议,对帧数据进行组装,然后再通过一层一层的协议进行解析,最终被应用层的协议解析并交给服务器处理。(摘取)
各个协议层职责:
- 应用层:定义数据格式,并按照对应的格式解读数据。
- 传输层:定义端口,确认主机上应用程序的身份,并将数据包交给对应的应用程序;
- 网络层:定义IP地址,确认主机所在的网络位置,并通过IP进行MAC寻址,对外网数据包进行路由转发;
- 链路层:对0和1进行分组,定义数据帧,确认主机的物理地址,传输数据;
TCP连接三次握手
TCP协议是可靠性、全双工通信的。tcp开始通信之前需要进行可靠性连接,就是使用三次握手机制进行客户端与服务端连接。三次握手跟通俗的电话通信类似,需要双方确认没问题才开始通话内容。
(第一次握手)A:喂,能听到我讲话吗?
(第二次握手)B:嗯,我能听到,你能听到我讲话吗?
(第三次握手)A:嗯,我收到了你的回话了。
下面开始通话内容......
三次握手一次不可少,也不需要多余的次数。每次讲话相当于发送syn请求包,收到就生成了ack确认包。所以在第二次握手时有两个操作,一个接收动作一个回应包动作。
各个字段意义:
序列号seq | TCP把连接中发送的所有数据字节都编上一个序号,第一个字节的编号由本地随机产生;给字节编上序号后,就给每一个报文段指派一个序号。 |
确认号ack | 期待收到对方下一个报文段序号;序列号表示报文段携带数据的第一个字节的编号;而确认号指的是期望接收到下一个字节的编号;因此当前报文段最后一个字节的编号+1即为确认号。 |
同步SYN | 请求建立连接,连接建立时用于同步序号。当SYN=1,ACK=0时表示:这是一个连接请求报文段。若同意连接,则在响应报文段中使得SYN=1,ACK=1。因此,SYN=1表示这是一个连接请求,或连接接受报文。SYN这个标志位只有在TCP建产连接时才会被置1,握手完成后SYN标志位被置0。 |
确认ACK | 状态标识,表示确认号是否有效,一般置为1。仅当ACK=1时,确认号字段才有效。ACK=0时,确认号无效 |
终止FIN | 希望断开连接,用来释放一个连接。FIN=1表示:此报文段的发送方的数据已经发送完毕,并要求释放运输连接 |
ACK、SYN和FIN这些大写的单词表示标志位,其值要么是1,要么是0;ack、seq小写的单词表示序号。 |
TCP三次握手过程:
- 第一次握手:客户端的应用进程主动打开,并向服务器发出请求报文段。其首部中:SYN=1,seq=x。x为随机产生。此时状态为SYN_SENT;
- 第二次握手:服务器应用进程被动打开。服务器由SYN=1知道,客户端要求建立联机,若同意客户端的请求,则发回确认报文,其首部中:SYN=1,ACK=1,ack=x+1,seq=y。
- 第三次握手:客户端收到确认报文之后,通知上层应用进程连接已建立,并向服务器发出确认报文,其首部:ACK=1,ack=y+1。当服务器收到客户端的确认报文之后,也通知其上层应用进程连接已建立。
- 三次握手完成,开始传送数据。
【作图很辛苦,图转自这里】
TCP断开四次挥手
- 第一次挥手:数据传输结束以后,客户端的应用进程发出连接释放报文段FIN=1,seq=u,并停止发送数据。
- 第二次挥手:服务器端收到连接释放报文段之后,发出确认报文,其首部:ack=u+1,seq=v。此时本次连接就进入了半关闭状态,客户端不再向服务器发送数据。而服务器端仍会继续发送。
- 第三次挥手:若服务器已经没有要向客户端发送的数据,其应用进程就通知服务器释放TCP连接。这个阶段服务器所发出的最后一个报文的首部应为:FIN=1,ACK=1,seq=w,ack=u+1。
- 第四次挥手:客户端收到连接释放报文段之后,必须发出确认:ACK=1,seq=u+1,ack=w+1。 再经过2MSL(最长报文端寿命)后,本次TCP连接真正结束,通信双方完成了他们的告别。
为什么连接是三次握手,断开却是四次呢?
因为服务器收到断开报文时,无法立刻真正的断开连接,仅仅代表客户端不需要发送数据到服务器,服务器可能还需要传送数据给客户端,等传送完毕才能确认断开。
最后一次挥手客户端收到断开报文后为什么还需要等待一段时间才真正断开?2MSL是什么?为什么是2MSL?
MSL是最大报文段生存时间,2MSL可以保证收发一次报文。2MSL是两倍的MSL(Maximum Segment Lifetime)。MSL指一个片段在网络中最大的存活时间,2MSL就是一个发送和一个回复所需的最大时间。
客户端在收到服务端断开报文后,立即发出确认ACK,开启倒计时2MSL是因为要保证最后一个ACK能被服务端接收到。
假如由于网络原因最后的客户端发送给服务端的ACK发送失败,服务端没能接收到,如果客户端不等待直接关闭的话,服务端将一直处于非关闭状态,且不断向客户端发送请求断开报文。加上等待2MSL机制可避免此类情况出现,解决了由于网络故障出现的问题。
摘取:需要保证服务器端收到了客户端的最后一条确认报文。假如这条报文丢失,服务器没有接收到确认报文,就会对连接释放报文进行超时重传,而此时客户端连接已关闭,无法做出响应,就造成了服务器端不停重传连接释放报文,而无法正常进入关闭状态的状况。而等待2MSL,就可以保证服务器端收到了最终确认;若服务器端没有收到,那么在2MSL之内客户端一定会收到服务器端的重传报文,此时客户端就会重传确认报文,并重置计时器。