TCP的三次握手与四次握手
一,传输控制协议TCP
1,特点:TCP是面向连接的传输层协议。就是应用程序在使用TCP前要先建立TCP连接,等到数据传输完毕后,必须释放已经建立的TCP连接。
2,TCP连接:每一条TCP 连接有2个端点,TCP连接的端点叫套接字(socket)或插口。端口号连接到IP地址就构成了套接字。
套接字(socket)= (IP:端口号)
每一条TCP连接唯一地被通信两端的两个端点口(即两个套接字)所确定。
TCP连接 ::= {socket1, socket2} = { (IP:port1) , (ip:port2) }
二,TCP报文段的首部格式
TCP报文分为首部和数据两部分
1,源端口和目的端口:各占两个字节,分别写入源端口号和目的端口号。
2,序号:占4个字节,TCP连接中传送的字节流中的每个字节都按顺序编号。例如,一段报文的序号字段值是 301 ,而携带的数据共有100字段,显然下一个报文段(如果还有的话)的数据序号应该从401开始;
3,确认号:占4个字节。是期望收到对方下一个报文段的第一个数据字节的序号。
若确认号 = N,则表明到序号前N-1为止所有数据已经接收完毕。
4,数据偏移:指出TCP报文段的数据起始处距离TCP报文段的起始处有多远。
5,保留,占6位,保留今后使用,但目前应都位0;
6,紧急URG,当URG=1,表明紧急指针字段有效。告诉系统此报文段中有紧急数据;
7,确认ACK,仅当ACK=1时,确认号字段才有效。TCP规定,在连接建立后所有报文的传输都必须把ACK置1;
8,推送PSH,当两个应用进程进行交互式通信时,有时在一端的应用进程希望在键入一个命令后立即就能收到对方的响应,这时候就将PSH=1
9,复位RST,当RST=1,表明TCP连接中出现严重差错,必须释放连接,然后再重新建立连接;
10,同步SYN,在连接建立时用来同步序号。当SYN=1,ACK=0,表明是连接请求报文,若同意连接,则响应报文中应该使SYN=1,ACK=1;
11,终止FIN,用来释放连接。当FIN=1,表明此报文的发送方的数据已经发送完毕,并且要求释放;
12,窗口,占2字节,指的是通知接收方,发送本报文你需要有多大的空间来接受;端口字段明确表明了现在允许对方发送的数据量。窗口值在动态变化着
13,检验和,占2字节,校验首部和数据这两部分;
14,紧急指针,占2字节,指出本报文段中的紧急数据的字节数;
15,选项,长度可变,定义一些其他的可选的参数。
三,TCP连接的建立(三次握手)
最初的两端都处于CLOSED状态,A为主动打开连接,B为被动打开连接。B的TCP服务器先创建传输控制快TCB,准备接受客户端的连接请求,然后服务器进程就进入LISTEN(监听)状态。
A的TCP客户进程也是首先创立传输控制模块TCB,然后向B发送连接请求报文,同步位SYN=1,同时选择一个初始*** seq=x ,此时,TCP客户端进程进入了 SYN-SENT(同步已发送状态)状态。TCP规定,SYN报文段(SYN=1的报文段)不能携带数据,但需要消耗掉一个序号。
TCP服务器收到请求报文后,如果同意连接,则发出确认报文。确认报文中应该 ACK=1,SYN=1,确认号是ack=x+1,同时也要为自己初始化一个*** seq=y,此时,TCP服务器进程进入了SYN-RCVD(同步收到)状态。这个报文也不能携带数据,但是同样要消耗一个序号。
TCP客户进程收到确认后,还要向服务器给出确认。确认报文的ACK=1,ack=y+1,自己的***seq=x+1,此时,TCP连接建立,客户端进入ESTABLISHED(已建立连接)状态。TCP规定,ACK报文段可以携带数据,但是如果不携带数据则不消耗序号。
为什么A还要发送一次确认呢?
防止已经失效的连接报文段突然又传输到了B,因而产生错误。想象这样的情景,A发送连接请求,连接请求报文丢失,B没有收到,A会再重传一次,如果这个报文在传输迟到了,在某个时间才到达B,但是B收到失效的连接请求报文后,以为是A发送的新的连接请求,就会向B发送确认报文段,如果不采用3次握手的话,B就会认为连接已经建立,等待A发送数据,造成B的资源浪费。
四,TCP连接释放
数据传输结束后,上方都处于ESTABLISHED状态,A的应用进程先向TCP发送连接释放报文,并停止发送数据,主动关闭TCP连接,释放数据报文首部,FIN=1,其***为seq=u(等于前面已经传送过来的数据的最后一个字节的序号加1),此时,客户端进入FIN-WAIT-1(终止等待1)状态。 TCP规定,FIN报文段即使不携带数据,也要消耗一个序号。
服务器收到连接释放报文,发出确认报文,ACK=1,ack=u+1,并且带上自己的***seq=v,此时,服务端就进入了CLOSE-WAIT(关闭等待)状态。TCP服务器通知高层的应用进程,客户端向服务器的方向就释放了,这时候处于半关闭状态,即客户端已经没有数据要发送了,但是服务器若发送数据,客户端依然要接受。这个状态还要持续一段时间,也就是整个CLOSE-WAIT状态持续的时间。
客户端收到服务器的确认请求后,此时,客户端就进入FIN-WAIT-2(终止等待2)状态,等待服务器发送连接释放报文(在这之前还需要接受服务器发送的最后的数据)。
服务器将最后的数据发送完毕后,就向客户端发送连接释放报文,FIN=1,ack=u+1,由于在半关闭状态,服务器很可能又发送了一些数据,假定此时的***为seq=w,此时,服务器就进入了LAST-ACK(最后确认)状态,等待客户端的确认。
客户端收到服务器的连接释放报文后,必须发出确认,ACK=1,ack=w+1,而自己的***是seq=u+1,此时,客户端就进入了TIME-WAIT(时间等待)状态。
此时TCP连接还没有释放,必须经过2MSL(最长报文段寿命)的时间后,当客户端撤销相应的TCB后,才进入CLOSED状态。服务器只要收到了客户端发出的确认,立即进入CLOSED状态。同样,撤销TCB后,就结束了这次的TCP连接。可以看到,服务器结束TCP连接的时间要比客户端早一些。
为甚麽A要在time-wait状态等待2MSL时间呢?
1,为了保证A发送的最后一个ASK报文段能够到达B,如果报文段丢失,B会超时重传FIN+ASK报文段,A重传一次确认重新计时。
2,防止上一次提到的“已失效的连接请求报文段”出现在本连接中,A发送完最后一次ASK报文后,经过2MSL会使本连接持续的时间内的所有报文都从网络中消失。
如果已经建立了连接,但是客户端出问题怎末办?
TCP还设有一个保活计时器,显然,客户端如果出现故障,服务器不能一直等下去,服务器每收到客户端的请求后会复位计时器,时间为2小时,若2小时内没收到任何数据,服务器就会发送一个探测报文段,以后每个75分钟发送一次,连发10个仍没有反应,服务器就会认为客户端出现了故障,接着就关闭连接。