TCP通信简单梳理
一、什么是TCP协议
TCP协议是一种面向连接的可靠的通信协议,最重要的两个特点:连接、可靠。
二、TCP是如何进行通信的
TCP通过三次握手建立连接后客户端服务端的内核都分别开辟资源,这时候开始进行数据传输,最终通过四次挥手断开连接,释放资源,整体流程如下:
1、三次握手
三次握手流程如下:
1)客户端向服务端发送SYN包告诉服务端我的初始序列号为X;
2)服务端接收后回复ACK包表示我收到了;
3)服务端也通过一个SYN包告知客户端我的序列号为Y;
4)客户端收到后回复服务端ACK包表示我也收到了。
从上面的流程上可以看出来,三次握手就是为了让客户端、服务端都能确认自己能发数据也能收数据即自己的输入输出是正常的,这时有人可能问了那应该四次握手啊?
这是因为实际应用中为了减少客户端与服务端直接交互次数,将服务端发送ACK包和SYN包合并处理,因而最终只需交互三次即可建立连接。
2、数据传输
TCP是一种可靠的传输协议,那么它可靠在哪呢?—— 确认机制。在数据传输过程中每一次数据包的传递都需要发送ACK包进行确认,通过这样的方式确保每一次传输都是可靠的。
3、四次挥手
由于连接的资源总是有限的,所以当数据传输完毕我们需要关闭连接由于TCP是全双工的,所以要断开连接,两边都需要拆除连向对端的通信信道,所以四次挥手流程如下:
1)客户端发送一个 FIN 包来告诉服务端我已经没数据需要发送了;
2)服务端收到后回复一个 ACK 确认包说我知道了;
3)然后服务端在自己也没数据发送给客户端后,服务端也发送一个 FIN 包给客户端告诉客户端我也已经没数据发送了;
4)客户端收到后,就会回复一个 ACK 确认包说我知道了。
下面通过一个实际例子进行展示,我们通过tcpdump进行抓包,详细看下整个tcp通信过程。
首先通过如下命令监听80端口:
yangye@test:~$ sudo tcpdump -nn -i ens33 port 80 [sudo] password for yangye: tcpdump: verbose output suppressed, use -v or -vv for full protocol decode listening on ens33, link-type EN10MB (Ethernet), capture size 262144 bytes
接着我们通过curl请求百度首页:
curl www.baidu.com
我们来看一下抓包情况:
# 客户端发送SYN包 07:59:59.841169 IP 172.16.194.129.58766 > 110.242.68.3.80: Flags [S], seq 3215627872, win 64240, options [mss 1460,sackOK,TS val 1796006028 ecr 0,nop,wscale 7], length 0 # 服务端返回ACK和SYN包 07:59:59.944579 IP 110.242.68.3.80 > 172.16.194.129.58766: Flags [S.], seq 2542675112, ack 3215627873, win 64240, options [mss 1460], length 0 # 客户端发送ACK包,这时三次握手结束,连接建立 07:59:59.944614 IP 172.16.194.129.58766 > 110.242.68.3.80: Flags [.], ack 1, win 64240, length 0 # 客户端请求首页 07:59:59.945103 IP 172.16.194.129.58766 > 110.242.68.3.80: Flags [P.], seq 1:78, ack 1, win 64240, length 77: HTTP: GET / HTTP/1.1 # 服务端确认收到请求 07:59:59.945488 IP 110.242.68.3.80 > 172.16.194.129.58766: Flags [.], ack 78, win 64240, length 0 # 服务端返回数据包 07:59:59.968917 IP 110.242.68.3.80 > 172.16.194.129.58766: Flags [P.], seq 1:2782, ack 78, win 64240, length 2781: HTTP: HTTP/1.1 200 OK # 客户端确认收到 07:59:59.968955 IP 172.16.194.129.58766 > 110.242.68.3.80: Flags [.], ack 2782, win 62780, length 0 # 客户端告诉服务端我要关闭连接 07:59:59.970750 IP 172.16.194.129.58766 > 110.242.68.3.80: Flags [F.], seq 78, ack 2782, win 62780, length 0 # 服务端返回ACK 07:59:59.970959 IP 110.242.68.3.80 > 172.16.194.129.58766: Flags [.], ack 79, win 64239, length 0 # 服务端告诉客户端它也要关闭连接 07:59:59.993361 IP 110.242.68.3.80 > 172.16.194.129.58766: Flags [FP.], seq 2782, ack 79, win 64239, length 0 # 客户端返回ACK 07:59:59.993397 IP 172.16.194.129.58766 > 110.242.68.3.80: Flags [.], ack 2783, win 62780, length 0