两个主机中间的通信
两个主机之间的通信是一个主机的进程与另一个主机的进程在交换数据, IP 协议只是把数据包文传输到目的主机, 但并没有交付给目的主机的具体应用进程. 只有端到端的通信才是真正的应用进程之间的通信
TCP 概述
TCP 把链接作为最基础的对象, 每一条 TCP 链接都有两个端点, 端点也叫作套接字, 套接字的定义为: IP 地址拼接端口号, 如: 192.168.77.91:8080.
TCP 报文关键首部
序号, 占 4 个字节, TCP 连接中传输的字节流中每个字节都按顺序编号. 例如一个报文的序号字段是 301, 而其携带的数据公有 100 的字节, 故而下一个报文段 (如果有的话) 数据序号应该是从 401 开始.
确认号, 占 4 个字节, 是期望收到下一个报文的第一个数据字节的序号.
确认 ACK, 只有当 ACK=1 时, 确认号字段才有效. TCP 规定, 建立连接后所有报文的传输都必须把 ACK 置一. TCP 规定, ACK 报文段可以携带数据, 但是如果不携带数据则不需要消耗序号.
同步 SYN, 在连接建立时用来同步序号. 当 SYN=1,ACK=0, 表明是连接请求报文, 若同意连接, 则响应报文中应该使 SYN=1,ACK=1.TCP 规定, SYN 报文段 (SYN=1) 不能携带数据, 但要消耗一个序号.
终止 FIN, 用来释放连接. 当 FIN=1, 表明此报文的发送方的报文已经发送完毕, 请求释放连接. TCP 规定, FIN 报文段即使不携带数据, 也要消耗一个序号.
TCP 三次握手
最开始的时候客户端和服务器都是处于 CLOSED 状态. 主动打开连接的为客户端, 被动打开连接的是服务器.
TCP 服务器进程先创建传输控制块 TCB, 时刻准备接受客户进程的连接请求, 此时服务器就进入了 LISTEN(监听)状态;
TCP 客户进程也是先创建传输控制块 TCB, 然后向服务器发出连接请求报文, 这是报文首部中的同部位 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 报文段可以携带数据, 但是如果不携带数据则不消耗序号.
当服务器收到客户端的确认后也进入 ESTABLISHED 状态, 此后双方就可以开始通信了.
TCP 四次挥手
数据传输完毕后, 双方都可释放连接. 最开始的时候, 客户端和服务器都是处于 ESTABLISHED 状态, 然后客户端主动关闭, 服务器被动关闭.
客户端进程发出连接释放报文, 并且停止发送数据. 释放数据报文首部, 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 连接还没有释放, 必须经过 2? *?MSL(最长报文段寿命)的时间后, 当客户端撤销相应的 TCB 后, 才进入 CLOSED 状态.
服务器只要收到了客户端发出的确认, 立即进入 CLOSED 状态. 同样, 撤销 TCB 后, 就结束了这次的 TCP 连接. 可以看到, 服务器结束 TCP 连接的时间要比客户端早一些.
2MSL
确保最后一个 ACK 报文能够到达目标服务器.
消耗本次连接中的旧报文.
为什么建立连接是三次握手, 关闭连接确是四次挥手呢?
三次握手中, 服务端将同步 SYN 和确认 ACK 放到一个报文里发送给客户端. 关闭连接时, 服务端接收到客户端连接终止请求, 这仅表示对方不再发送数据但还能继续接受数据, 而自身还可有数据未发送, 所以先对客户端的连接终止请求恢复确认报文, 如果还有数据需要发送则接着发送未发送的数据, 待数据发送完毕再发送 FIN 报文给客户端表示同意现在关闭连接. 由于己方的 ACK 和 FIN 报文是分开发送的, 所以会多了一次请求.
如果已经建立了连接, 但是客户端突然出现故障了怎么办?
TCP 保活计时器, 多次发送探测报文.
参考
来源: http://www.bubuko.com/infodetail-2990766.html