一、TCP运输连接阶段
TCP建立连接要解决三个问题:
- 使TCP双方能确认对方的存在
- 使对方能够协商一些参数(如最大窗口值、是否使用窗口扩大选项和时间戳以及服务质量等)
- 使TCP双方能够对运输实体资源(如缓存大小、建立连接的项目等)进行分配。
三报文握手
- SYN:同步位
- ACK:确认位
- seq:初始序号\初始序号
- ack:确认号
- 两台要基于TCP进行通信的主机,其中一台主机的某个应用进程主动发起TCP连接建立,成为TCP客户,另一台被动等待TCP连接建立的应用进程称为TCP服务器。
- 可以将TCP建立连接的过程比喻为”握手”。”握手”需要在TCP客户和TCP服务器间交换3个TCP报文段。
- 最初,两端的TCP进程都处于关闭(close)状态,一开始TCP服务进程首先创建传输控制模块TCB,用来存储TCP连接中的一重要信息,例如:TCP连接表,包含指向接收缓存的指针、指向队列的指针、当前接收序号等。之后就准备接受TCP客户进程的连接请求。此时,TCP服务进程就进入监听(lisen)状态,等待TCP客户进程的连接请求。
注意:TCP服务进程是被动等待来自TCP客户进程的连接请求,被称为“被动打开连接” TCP连接建立是TCP客户主动发送的,因此被称为“主动打开连接“。
- TCP客户进程也是先创建传输控制模块TCB,然后在打算建立TCP连接时向TCP服务进程发送TCP连接请求报文段。TCP连接请求报文段首部中的同步位SYN设置为1,表明这是一个TCP连接请求报文段。TCP规定同步位SYN设置为1的报文段不能携带数据,但要消耗掉一个序号。序号字段seq被设置为初始值x,被作为TCP客户进程所选择的初始序号。 并进入“SYN-SENT”同步发送状态。
- 服务器进程收到连接请求报文段后,如果同意建立连接,则向TCP客户进程发送一个确认。在确认报文段中应把同步位和SYN和确认位ACK设置位1。确认号ack设置位x+1(这是因为TCP规定同步位SYN=1的报文段不能携带数据,但要消耗掉一个序号),同时也为自己选择一个初始序号为y的seq(随机)。这个报文段也不能携带数据,但同样也消耗掉一个序号。这是TCP服务器进程进入了同步收到状态。
- TCP客户进程收到B的确认报文段后,还要给B发送一个确认。确认报文段的确认位ACK置为1,确认号ack置为y+1,TCP规定,客户进程的确认报文段可以发送数据,如果不发送数据,则序号字段seq设置为x+1(第一次发送请求连接时没有发送数据,但又消耗掉了一个序号,就从序号为x+1开始发送数据)。这是TCP客户进程进入了已建立连接(ESTABLISH)状态
- 当TCP服务器进程收到了来自TCP客户的确认,也进入了已建立连接状态。
上面给出的连接建立称为“三次握手”。在服务器进程给客户进程的确认报文,可以分成两个报文段发送。 比如先发送一个确认报文段 ACK=1, ack=x+1 然后发送一个同步报文段 SYN=1, seq=y 这样就成了“四次握手“
TCP客户最后为什么还要发送一次确认呢? 答:是为了防止”已失效的连接请求报文“又突然到达了TCP服务器进程,因而产生错误。 “已失效的连接请求报文”是如何产生的: 正常情况: 当TCP客户进程发送给TCP服务器进程的连接请求报文丢失了,由于TCP客户进程迟迟收不到服务器进程的确认报文,导致了超时计时器超时,重新发送了连接请求报文,并收到了确认,建立了连接。数据传输完成就,释放了连接。客户进程发送了两次连接请求报文,其中一个丢失,其中一个被接收。此时B没有收到”这个失效了的请求报文“
能否简化成两次握手? 不能,如果客户端发送的连接请求报文由于在某个网络结点中被长时间滞留了,客户端因没有收到确认报文导致超时计数器重传连接请求报文,并与客户端建立了连接,发送完数据后释放了该连接,在网络结点被滞留的请求报文这时才到达服务端,这本来是一个已经失效了的请求报文,假设只有两次握手,服务端接收了该连接请求报文并发送了确认后进入了已连接状态,等待客户端发送数据,客户端现在没有对服务端发送连接请求,就会对客户端发送的确认报文不理睬,但是服务端以为已经建立了连接而一直等待客户端发送数据。这样导致了服务端的大量资源被浪费。所以不能是两次握手。