1、TCP/IP 四层体系结构
TCP/IP 四层体系结构 | 功能 | 协议簇 |
---|---|---|
应用层 | 定义应用进程间的交互规则 | HTTP、DNS、Telnet、SMTP(电子邮件) |
传输层 | 负责主机进程间的数据传输 | TCP、UDP |
网络层 | 负责数据报的路由和转发 | IP |
网络接口层 | 负责数据在物理媒介上的传输 |
PS:进程指主机中正在运行的程序。
2、TCP协议报文
- 序号seq:占4个字节,用来标记报文段的顺序。TCP是面向字节流的,每一个字节都会按顺序编号。序号seq就是本报文段所发送的数据的第一个字节的序号。
- 确认号ack:占4个字节,是期望收到对方下一个报文段的第一个数据字节的序号。序号seq表示报文段携带数据的第一个字节的序号,而确认号ack是期望接收到下一个字节的序号,因此当前报文段最后一个字节的编号+1即为确认号。
- 确认ACK:占1位,仅当ACK=1时,确认号字段才有效。ACK=0时,确认号无效。TCP规定,在连接建立后所有传送的报文段都必须把ACK置1。
- 同步SYN:连接建立时用于同步序号。当 SYN=1 而 ACK=0 时,表明这是一个连接请求报文段。对方若同意建立连接,则在响应报文段中使用 SYN=1 和 ACK=1。因此,SYN=1 表示这是一个连接请求或连接接受报文。SYN这个标志位只有在TCP建立连接时才会被置1,握手完成后SYN标志位被置0。
- 终止FIN:用来释放一个连接。当 FIN=1 时,表示此报文段的发送方的数据已经发送完毕,并要求释放运输连接。
PS:ACK、SYN、FIN 这些大写的单词表示标志位,其值要么是1,要么是0。ack、seq小写的单词表示序号。
3、TCP建立连接的三次握手
3.1 三次握手
- 客户端处于 CLOSED 状态,服务端处于 LISTEN 状态;
- 第一次握手:客户端发起连接,发送一个 SYN 包(SYN=1,seq=x)到服务端,并进入同步已发送(SYN_SENT)状态,等待服务端确认;
- 第二次握手:服务端收到 SYN 包,然后进行确认(即设置ack=x+1),同时自己发送一个 SYN+ACK 包(SYN=1,ack=x+1,ACK=1,seq=y)到客户端,此时服务端进入 同步接收( SYN_RCVD)状态;
- 第三次握手:客户端收到 SYN+ACK 包后,向服务端发送 ACK 确认包(ACK=1,ack=y+1,seq=x+1),进入 已建立连接(ESTABLISHED)状态;服务端收到 ACK 确认包,进入 已建立连接(ESTABLISHED)状态。
3.2 TCP建立连接为什么要三次握手,不可以二次握手吗?
采用三次握手是为了防止失效的连接请求报文段突然又传送到服务器端,因而产生错误。失效的连接请求报文段是指:客户端发出的连接请求没有收到服务器的确认,于是经过一段时间后,客户端又重新向服务器发送连接请求,且建立成功,顺序完成数据传输。考虑这样一种特殊情况,客户端第一次发送的连接请求并没有丢失,而是因为网络节点导致延迟到达服务器,服务器以为是客户端又发起的新连接,于是服务器同意连接,并向客户端发回确认,但是此时客户端根本不会理会,服务器就一直在等待客户端发送数据,导致服务器的资源浪费。
4、TCP释放连接的四次挥手
4.1 四次挥手
- 第一次挥手:当数据传输结束以后,客户端的应用进程发出连接释放报文段(FIN=1,seq=u),并停止发送数据,进入 终止等待1(FIN-WAIT-1)状态。
- 第二次挥手:服务器端收到连接释放报文段之后,发出确认报文(ACK=1,ack=u+1,seq=v),进入 关闭等待(CLOSE-WAIT)状态,此时服务器端仍会继续发送数据。客户端收到确认报文进入 终止等待2(FIN-WAIT-2)状态。
- 第三次挥手:若服务器已经没有要向客户端发送的数据,其应用进程就通知服务器释放TCP连接。这个阶段服务器发出最后一个报文(FIN=1,ACK=1,ack=u+1,seq=w),进入 最后确认(LAST-ACK)状态。
- 第四次挥手:客户端收到连接释放报文段之后,必须发出确认包(ACK=1,ack=w+1,seq=u+1),再经过 2MSL(Maximum Segment Lifetime最长报文寿命)后,本次TCP连接真正结束,通信双方断开连接。
4.2 在释放连接的过程中,为什么在收到服务器端的连接释放报文段之后,客户端还要继续等待2MSL之后才真正关闭TCP连接呢?
- 有两个原因:
- 第一个是:需要保证服务器端收到了客户端的最后一条确认报文。假如这条报文丢失,服务器没有接收到确认报文,就会对连接释放报文进行超时重传,而此时客户端连接已关闭,无法做出响应,就造成了服务器端不停重传连接释放报文,而无法正常进入关闭状态的状况。而等待2MSL,就可以保证服务器端收到了最终确认;若服务器端没有收到,那么在2MSL之内客户端一定会收到服务器端的重传报文,此时客户端就会重传确认报文,并重置计时器。
- 第二个是:存在一种“已失效的连接请求报文段”,需要避免这种报文端出现在本连接中,造成异常。这种“已失效的连接请求报文段”是这么形成的:假如客户端发出了连接请求报文,然而服务器端没有收到,于是客户端进行超时重传,再一次发送了连接请求报文,并成功建立连接。然而,第一次发送的连接请求报文并没有丢失,只是在某个网络结点中发生了长时间滞留,随后,这个最初发送的报文段到达服务器端,会使得服务器端误以为客户端发出了新的请求,造成异常。
4.3 建立连接是三次握手,为什么释放连接却是四次挥手呢?
因为服务端在LISTEN状态下,收到建立连接请求的SYN报文后,把ACK和SYN放在一个报文里发送给客户端。而关闭连接时,当收到对方的FIN报文时,仅仅表示对方不再发送数据了但是还能接收数据,己方也未必全部数据都发送给对方了,所以己方可以立即close,也可以发送一些数据给对方后,再发送FIN报文给对方来表示同意现在关闭连接,因此,己方ACK和FIN一般都会分开发送。