TCP
封包格式
- Source Port & Destination Port: 源端口,目的端口。
- Sequence Number : TCP封包必须要放到IP封包中,如果TCP封包大于IP封包,就要进行分段,Sequence Number 就是记录这是第几个分段,用于重新组装数据。
- Acknowledge Number: 用于确认之前传递的封包是否被正确的接收。
- Data Offset: 配合Options使用,用于说明整个封包区段的起始位置。
- Reserved: 未使用的保留字段。
- Code: 用于说明联机状态,让接受段了解这个封包的主要动作。若为1则为启动。(下面会具体解释6种封包动作)
- Window: 用来控制封包流量,如果为0,则要暂停传输数据
- Checksum: 校验码,接收方通过校验码来对封包进行校验,校验失败会要求重新发送此封包
- Urgent Pointer: 配合Code字段内 URG = 1 生效,用于告知紧急数据所在位置。
- Options: 用于表示接收端可以接收的最大数据区段容量
- Padding: Options由于字段为非固定,需要Padding字段补齐。
TCP封包Code
当我们在进行网络联机的时候,必须要说明这个联机的状态,好让接收端了解这个封包的主要动作。 这可是一个非常重要的句柄喔!这个字段共有 6 个 bits , 分别代表 6 个句柄,若为 1 则为启动。分别说明如下:
- URG(Urgent):若为1则代表该封包为紧急封包,接收端应该要紧急处理,Urgent Pointer 字段也会被启用。
- ACK(Acknowledge):若为1代表这个封包为响应封包, 则与上面提到的 Acknowledge Number 有关。
- PSH(Push function):若为1时,代表要求对方立即传送缓冲区内的其他对应封包,而无须等待缓冲区满了才送。
- RST(Reset):如果 RST 为 1 的时候,表示联机会被马上结束,而无需等待终止确认手续。这也就是说, 这是个强制结束的联机,且发送端已断线。
- SYN(Synchronous):若为 1,表示发送端希望双方建立同步处理, 也就是要求建立联机。通常带有 SYN 标志的封包表示『主动』要连接到对方的意思。
- FIN(Finish):若为 1,表示传送结束,所以通知对方数据传毕, 是否同意断线,只是发送者还在等待对方的响应而已。
TCP三次握手
三向交握(Three-way handshake)。
- 当客户端想要对服务器端联机时,就必须要送出一个要求联机的封包,此时客户端必须随机取用一个大于1024以上的端口来做为程序沟通的接口。然后在 TCP 的表头当中,必须要带有 SYN 的主动联机(SYN=1),并且记下发送出联机封包给服务器端的序号 (Sequence number seq = x) 。
- 当服务器接到这个封包,并且确定要接收这个封包后,就会开始制作一个同时带有 SYN=1, ACK=1 的封包, 其中那个 ack 的号码是要给 client 端确 认用的,所以该数字会比(1步骤)里面的 seq 号码多一号 ack = x+1 , 那我们服务器也必须要确认客户端确实可以接收我们的封包才行, 所以也会发送出一个 seq=y 给客户端,并且开始等待客户端给 我们服务器端的回应喔!
- 当客户端收到来自服务器端的 ACK 与 ack 后就能够确认之前那个要求封包被正确的接收了, 接下来如果客户端也同意与服务器端建立联机时,就会再次的发送一个确认封包 (ACK=1) 给服务器,亦即是 ack = y+1。
- 取得最后确认若一切都顺利,在服务器端收到带有 ACK=1 且 ack=y+1 序号的封包后,就能够建立起这次的联机了。
- 客户端:你能接收我吗 (SYN)
- 服务器:我能接收你,你能接收我吗 (ACK, SYN)
- 客户端:我能接收你 (ACK)
TCP 四次挥手
- 客户端进程发送连接释放封包,并且停止发送数据。释放数据报文首部,FIN=1,其序列号为seq=u 。此时客户端进入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连接还没有释放,必须经过2分钟(最长报文段寿命)的时间后,才进入CLOSED状态。
- 服务器只要收到了客户端发出的确认,立即进入CLOSED状态。可以看到,服务器结束TCP连接的时间要比客户端早一些。
- 客户端: 我要关闭连接了(FIN)
- 服务端: 我知道了,你等等 (ACK)
- 服务端: 我好了,我要关闭连接了(ACK,FIN)
- 客户端: 知道了(ACK)