共计 1922 个字符,预计需要花费 5 分钟才能阅读完成。
1. TCP 连贯的建设
TCP 建设连贯的过程须要在客户端和服务端之间替换 3 个 TCP 报文段,故而也称为“三次握手”。
假如 A 运行 TCP 客户端程序,B 运行 TCP 服务端程序,则三次握手过程如下所示:
服务端 B 执行的代码大抵如下:
struct sockaddr addr;
int listenSock, backlog, clientSock;
// 设置各变量 ...
listenSock = socket(AF_INET, SOCK_STREAM, 0);
bind(listenSock, &addr, sizoef(addr));
listen(listenSock, backlog);
clientSock = accept(listenSock, NULL, NULL);
客户端 A 执行的代码大抵如下:
struct sockaddr serverAddr;
int sock;
// 设置各变量 ...
sock = socket(AF_INET, SOCK_STREAM, 0);
connect(sock, &serverAddr, sizeof(serverAddr));
- 两者通过调用
socket()
来创立 TCP 套接字,此时两者处于 CLOSED 状态; - 服务端 B 先运行,在调用
listen()
之后,进入 LISTEN 状态,监听客户端连贯申请; - A 调用
connect()
向 B 发动建设连贯的申请:A 向 B 发送一个 SYN 报文段,其中的同步位 SYN=1,同时抉择一个初始序号 seq=x;SYN 报文段不能携带数据,但要耗费一个序号,在发送完 SYN 报文段之后,进入 SYN_SENT 状态; - B 收到 A 的连贯申请报文后进入 SYN_RCVD 状态,如果批准建设连贯,则调用
accept()
,而后向 A 发送确认:确认报文段的 SYN=1、ACK=1,确认号为 ack=x+1,同时为本人抉择一个初始序号 seq=y,此报文段也不能携带数据,但要耗费一个序号; - A 收到 B 的确认后,还要向 B 返回确认,而后进入 ESTABLISHED 状态:确认报文的 ACK=1,确认序号为 ack=y+1,而本人的序号为 seq=x+1,此报文段能够携带数据,如果不携带数据则不耗费序号(下一个报文段的序号仍为 seq=x+1);
- B 收到 A 的确认后也进入 ESTABLISHED 状态。
为什么 A 最初还要发送一次确认? 次要是为了避免已生效的连贯申请报文段忽然又传送到了 B:如果 A 收回的第一个连贯申请报文段因为网络提早没有及时达到 B;此时 A 收回第二个连贯申请报文段,且胜利建设了连贯,数据传输结束后,开释了连贯;一段时间后,第一个连贯申请报文段终于达到了 B(B 认为是一个新的连贯申请),如果 B 不须要 A 的确认就建设了连贯,而 A 又不理睬 B 的确认,则 B 就白白浪费了资源。
2. TCP 连贯的开释
假如 A 被动敞开连贯,则连贯的开释过程如下:
- A 通过调用
close()
来敞开套接字,向 B 发送连贯开释报文段:报文段的 FIN=1,序号 seq=u;而后进入 FIN-WAIT-1 状态,期待 B 的确认;FIN 报文段不能携带数据,但要耗费一个序号; - B 收到连贯开释报文段后立刻收回确认:确认报文段的 ACK=1,确认号为 ack=u+1,序号为 seq=v;而后进入 CLOSE-WAIT 状态(期待己方敞开连贯);此时的 TCP 连贯处于半敞开状态,即 A 曾经没有数据要发送了,但如果 B 发送数据,A 仍要接管,也就是说 B 到 A 这个方向的连贯仍未敞开;
- A 收到 B 的确认后进入 FIN-WAIT-2 状态,期待 B 发送连贯开释报文段;
- B 发送完数据之后也调用
close()
来敞开连贯,向 A 发送连贯开释报文段:报文段的 FIN=1,ACK=1,序号为 seq=w,确认号仍为 ack=u+1;而后进入 LAST-ACK 状态,期待 A 的确认(最初一个确认); - A 收到 B 的连贯开释报文段后,向 B 收回确认:报文段的 ACK=1,序号为 seq=u+1,确认号为 ack=w+1;而后进入 TIME-WAIT 状态,此时连贯仍未开释;
- B 收到 A 的确认后开释连贯,进入 CLOSED 状态;
- A 在 TIME-WAIT 状态中期待 2MSL(Maximum Segment Lifetime)的工夫之后才进入到 CLOSED 状态,即 B 先于 A 完结 TCP 连贯。
为什么 A 须要在 TIME-WAIT 状态中期待 2MSL 的工夫? 起因有如下两点:
(1)为了保障 A 发送的最初一个 ACK 报文段可能达到 B。如果此 ACK 报文段失落,B 会因为没收到确认而超时重传 FIN+ACK 报文段,而 A 就可能在这 2MSL 工夫内收到重传的 FIN+ACK 报文段,而后 A 重传一次确认,并重新启动 2MSL 计时器。
(2)A 在发送完最初一个 ACK 报文段后,再通过 2MSL 工夫,就能够使本连贯期间所产生的所有报文段都从网络中隐没,这样就可保障新连贯中不会呈现旧连贯的申请报文段。
正文完