终于懂了TCP的三次握手和四次挥手(超精彩分析)

前言

由于之前有一篇文章获得了超高的认同:
在这里插入图片描述

在这里插入图片描述

主要写了TCP和UDP协议区别

如果你感兴趣可以看一下:
https://blog.csdn.net/qq_17623363/article/details/105109907

有粉丝建议可以把握手和挥手的过程贴出来:
在这里插入图片描述
现在已经超过2个月了,今天终于有时间来写了一下。

下面这种图还未画完,正在继续,欢迎大家关注,或者加我CSDN官方微信群哦,加入方式在最后面
在这里插入图片描述

一、计算机网络之TCP三次握手和四次挥手

(一)准备工作

在做实验之前呢,我准备好了一个web服务的接口:

package cn.agriculture.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

/**
 * @Auther: truedei
 * @Date: 2020 /20-6-15 21:52
 * @Description: tcpdump测试
 */
@Controller
@RequestMapping("/truedei/test")
public class TestController {


    @RequestMapping("")
    @ResponseBody
    public String index(String name){
        System.out.println("有人访问了,访问者:"+name);
        return "This is "+name;
    }

}

访问测试都是没问题的:

在这里插入图片描述

扫描二维码关注公众号,回复: 11299753 查看本文章

在Linux中可以使用wget访问:

[root@localhost ~]# 
[root@localhost ~]# 
[root@localhost ~]# wget http://192.168.101.5:8080/truedei/test?name=zhenghui

(二)tcpdump命令使用详解

如果没有这个命令的话,要自行安装

[root@localhost ~]# 
[root@localhost ~]# tcpdump
bash: tcpdump: 未找到命令
[root@localhost ~]# 

安装(我是Centos7环境下):

[root@localhost ~]# yum -y install tcpdump

使用help命令可以查看帮助:

[root@localhost ~]# 
[root@localhost ~]# tcpdump --help
tcpdump version 4.9.2
libpcap version 1.5.3
OpenSSL 1.0.2k-fips  26 Jan 2017
Usage: tcpdump [-aAbdDefhHIJKlLnNOpqStuUvxX#] [ -B size ] [ -c count ]
		[ -C file_size ] [ -E algo:secret ] [ -F file ] [ -G seconds ]
		[ -i interface ] [ -j tstamptype ] [ -M secret ] [ --number ]
		[ -Q|-P in|out|inout ]
		[ -r file ] [ -s snaplen ] [ --time-stamp-precision precision ]
		[ --immediate-mode ] [ -T type ] [ --version ] [ -V file ]
		[ -w file ] [ -W filecount ] [ -y datalinktype ] [ -z postrotate-command ]
		[ -Z user ] [ expression ]
[root@localhost ~]# 

使用man命令可以查看更详细的帮助;

[root@localhost ~]# 
[root@localhost ~]# 
[root@localhost ~]# man tcpdump
[root@localhost ~]# 

tcpdump选项介绍:

-a    将网络地址和广播地址转变成名字;
-d    将匹配信息包的代码以人们能够理解的汇编格式给出;
-dd    将匹配信息包的代码以c语言程序段的格式给出;
-ddd    将匹配信息包的代码以十进制的形式给出;
-e    在输出行打印出数据链路层的头部信息;
-f    将外部的Internet地址以数字的形式打印出来;
-l    使标准输出变为缓冲行形式;
-n    不把网络地址转换成名字;
-t    在输出的每一行不打印时间戳;
-v    输出一个稍微详细的信息,例如在ip包中可以包括ttl和服务类型的信息;
-vv    输出详细的报文信息;
-c    在收到指定的包的数目后,tcpdump就会停止;
-F    从指定的文件中读取表达式,忽略其它的表达式;
-i    指定监听的网络接口;
-r    从指定的文件中读取包(这些包一般通过-w选项产生);
-w    直接将包写入文件中,并不分析和打印出来;
-T    将监听到的包直接解释为指定的类型的报文,常见的类型有rpc (远程过程 调用)和snmp(简单网络管理协议;)

我们需要设置监听的网卡:

1、先查看一下自己需要监听网卡的名字:

可以看到enp0s3就是咱们想要的

[root@localhost ~]# 
[root@localhost ~]# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
2: enp0s3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 08:00:27:83:48:fb brd ff:ff:ff:ff:ff:ff
    inet 192.168.101.25/24 brd 192.168.101.255 scope global noprefixroute dynamic enp0s3
       valid_lft 84279sec preferred_lft 84279sec
    inet6 2408:8214:8311:5010:ace3:42de:a5e:7/128 scope global noprefixroute dynamic 
       valid_lft 6882sec preferred_lft 3282sec
    inet6 2408:8214:8311:5019:6b53:af13:ac60:ceb1/64 scope global noprefixroute dynamic 
       valid_lft 7185sec preferred_lft 3585sec
    inet6 fe80::601b:c404:a3dc:b509/64 scope link noprefixroute 
       valid_lft forever preferred_lft forever
[root@localhost ~]# 
[root@localhost ~]# 

设置监听的端口:

[root@localhost ~]# 
[root@localhost ~]# tcpdump -i enp0s3

当我直接回车之后,会发现一直,出现ssh的连接,这是因为我本来就在远程着我这台linux系统

在这里插入图片描述

所以我们可以过滤一下,设置只监听某一个网卡的某一个端口:

[root@localhost ~]# tcpdump -i enp0s3 port 8080

现在就一直处于一个等待的状态了,这是因为这个网卡还没请求过任何东西:

在这里插入图片描述

我们重新开一个ssh,然后再另一个ssh中访问web服务的接口:

从下图中,可以看到,当我访问的时候,监听的tcpdump就会触发,然后就会发生变化

[root@localhost ~]# 
[root@localhost ~]# 
[root@localhost ~]# wget http://192.168.101.5:8080/truedei/test?name=zhenghui

在这里插入图片描述

下图是全屏之后的图,可能更清楚一些:

在这里插入图片描述

第一行为:

这里说的是,你可以使用-v来查看协议

tcpdump: verbose output suppressed, use -v or -vv for full protocol decode

-v:

在这里插入图片描述

-vv:

在这里插入图片描述

(三)分析三次握手与四次挥手

例如我们拿这个数据,,来分析一下三次握手和四次挥手:

[root@localhost ~]# tcpdump -i enp0s3 port 8080 -vv
tcpdump: listening on enp0s3, link-type EN10MB (Ethernet), capture size 262144 bytes




10:49:10.094025 IP (tos 0x0, ttl 64, id 40563, offset 0, flags [DF], proto TCP (6), length 60)
    localhost.localdomain.57290 > 192.168.101.5.webcache: Flags [S], cksum 0x4b9e (incorrect -> 0xdc83), seq 250118291, win 29200, options [mss 1460,sackOK,TS val 4595424 ecr 0,nop,wscale 7], length 0
10:49:10.094140 IP (tos 0x0, ttl 64, id 0, offset 0, flags [DF], proto TCP (6), length 60)
    192.168.101.5.webcache > localhost.localdomain.57290: Flags [S.], cksum 0xe96e (correct), seq 2336326088, ack 250118292, win 28960, options [mss 1460,sackOK,TS val 2480165653 ecr 4595424,nop,wscale 7], length 0
10:49:10.094172 IP (tos 0x0, ttl 64, id 40564, offset 0, flags [DF], proto TCP (6), length 52)
    localhost.localdomain.57290 > 192.168.101.5.webcache: Flags [.], cksum 0x4b96 (incorrect -> 0x8874), seq 1, ack 1, win 229, options [nop,nop,TS val 4595426 ecr 2480165653], length 0
10:49:10.095038 IP (tos 0x0, ttl 64, id 40565, offset 0, flags [DF], proto TCP (6), length 194)
    localhost.localdomain.57290 > 192.168.101.5.webcache: Flags [P.], cksum 0x4c24 (incorrect -> 0x0f76), seq 1:143, ack 1, win 229, options [nop,nop,TS val 4595426 ecr 2480165653], length 142: HTTP, length: 142
	GET /truedei/test?name=zhenghui HTTP/1.1
	User-Agent: Wget/1.14 (linux-gnu)
	Accept: */*
	Host: 192.168.101.5:8080
	Connection: Keep-Alive
	
10:49:10.095134 IP (tos 0x0, ttl 64, id 22245, offset 0, flags [DF], proto TCP (6), length 52)
    192.168.101.5.webcache > localhost.localdomain.57290: Flags [.], cksum 0x87df (correct), seq 1, ack 143, win 235, options [nop,nop,TS val 2480165654 ecr 4595426], length 0
10:49:10.097367 IP (tos 0x0, ttl 64, id 22246, offset 0, flags [DF], proto TCP (6), length 319)
    192.168.101.5.webcache > localhost.localdomain.57290: Flags [P.], cksum 0xc019 (correct), seq 1:268, ack 143, win 235, options [nop,nop,TS val 2480165657 ecr 4595426], length 267: HTTP, length: 267
	HTTP/1.1 200 
	Vary: Origin
	Vary: Access-Control-Request-Method
	Vary: Access-Control-Request-Headers
	Content-Type: text/plain;charset=UTF-8
	Content-Length: 16
	Date: Mon, 15 Jun 2020 14:49:10 GMT
	Keep-Alive: timeout=60
	Connection: keep-alive
	
	This is zhenghui[!http]
10:49:10.097381 IP (tos 0x0, ttl 64, id 40566, offset 0, flags [DF], proto TCP (6), length 52)
    localhost.localdomain.57290 > 192.168.101.5.webcache: Flags [.], cksum 0x4b96 (incorrect -> 0x86cc), seq 143, ack 268, win 237, options [nop,nop,TS val 4595429 ecr 2480165657], length 0
10:49:10.097971 IP (tos 0x0, ttl 64, id 40567, offset 0, flags [DF], proto TCP (6), length 52)
    localhost.localdomain.57290 > 192.168.101.5.webcache: Flags [F.], cksum 0x4b96 (incorrect -> 0x86cb), seq 143, ack 268, win 237, options [nop,nop,TS val 4595429 ecr 2480165657], length 0
10:49:10.098475 IP (tos 0x0, ttl 64, id 22247, offset 0, flags [DF], proto TCP (6), length 52)
    192.168.101.5.webcache > localhost.localdomain.57290: Flags [F.], cksum 0x86cb (correct), seq 268, ack 144, win 235, options [nop,nop,TS val 2480165658 ecr 4595429], length 0
10:49:10.098487 IP (tos 0x0, ttl 64, id 40568, offset 0, flags [DF], proto TCP (6), length 52)
    localhost.localdomain.57290 > 192.168.101.5.webcache: Flags [.], cksum 0x4b96 (incorrect -> 0x86c8), seq 144, ack 269, win 237, options [nop,nop,TS val 4595430 ecr 2480165658], length 0


1、三次握手

(1)三次握手报文

10:49:10.094025 IP (tos 0x0, ttl 64, id 40563, offset 0, flags [DF], proto TCP (6), length 60)
    localhost.localdomain.57290 > 192.168.101.5.webcache: Flags [S], cksum 0x4b9e (incorrect -> 0xdc83), seq 250118291, win 29200, options [mss 1460,sackOK,TS val 4595424 ecr 0,nop,wscale 7], length 0
10:49:10.094140 IP (tos 0x0, ttl 64, id 0, offset 0, flags [DF], proto TCP (6), length 60)
    192.168.101.5.webcache > localhost.localdomain.57290: Flags [S.], cksum 0xe96e (correct), seq 2336326088, ack 250118292, win 28960, options [mss 1460,sackOK,TS val 2480165653 ecr 4595424,nop,wscale 7], length 0
10:49:10.094172 IP (tos 0x0, ttl 64, id 40564, offset 0, flags [DF], proto TCP (6), length 52)
    localhost.localdomain.57290 > 192.168.101.5.webcache: Flags [.], cksum 0x4b96 (incorrect -> 0x8874), seq 1, ack 1, win 229, options [nop,nop,TS val 4595426 ecr 2480165653], length 0
10:49:10.095038 IP (tos 0x0, ttl 64, id 40565, offset 0, flags [DF], proto TCP (6), length 194)
    localhost.localdomain.57290 > 192.168.101.5.webcache: Flags [P.], cksum 0x4c24 (incorrect -> 0x0f76), seq 1:143, ack 1, win 229, options [nop,nop,TS val 4595426 ecr 2480165653], length 142: HTTP, length: 142
	GET /truedei/test?name=zhenghui HTTP/1.1
	User-Agent: Wget/1.14 (linux-gnu)
	Accept: */*
	Host: 192.168.101.5:8080
	Connection: Keep-Alive
	
10:49:10.095134 IP (tos 0x0, ttl 64, id 22245, offset 0, flags [DF], proto TCP (6), length 52)
    192.168.101.5.webcache > localhost.localdomain.57290: Flags [.], cksum 0x87df (correct), seq 1, ack 143, win 235, options [nop,nop,TS val 2480165654 ecr 4595426], length 0
10:49:10.097367 IP (tos 0x0, ttl 64, id 22246, offset 0, flags [DF], proto TCP (6), length 319)
    192.168.101.5.webcache > localhost.localdomain.57290: Flags [P.], cksum 0xc019 (correct), seq 1:268, ack 143, win 235, options [nop,nop,TS val 2480165657 ecr 4595426], length 267: HTTP, length: 267
	HTTP/1.1 200 
	Vary: Origin
	Vary: Access-Control-Request-Method
	Vary: Access-Control-Request-Headers
	Content-Type: text/plain;charset=UTF-8
	Content-Length: 16
	Date: Mon, 15 Jun 2020 14:49:10 GMT
	Keep-Alive: timeout=60
	Connection: keep-alive
	
	This is zhenghui[!http]

(2)详解三次握手

先来看一个图三次握手的流程图:

接下来看 TCP 建连的三次握手。

TCP 是基于链接的,所以在传输数据前需要先建立链接,TCP 在传输上是双工传输不区分 Client 端与 Server 端,为了便于理解,我们把主动发起建连请求的一端Client 端,把被动建立链接的一端Server 端

如下图,建连的时序是从上到下,左右两边的绿色字分别代表 Client 端与 Server 端当时的链接状态。

在这里插入图片描述

首先建立链接前需要 Server 端监听端口,因此 Server 端建立链接前的初始状态就是LISTEN 状态,这时 Client 端准备建立链接发送一个 SYN同步包,送完同步包Client 端的链接状态变成了SYN_SENT 状态Server 端收到 SYN 后同意建立链接,会向 Client 端回复一个 ACK

由于 TCP 是双工传输Server 端也会同时向 Client 端发送一个 SYN,申请 Server 向 Client 方向建立链接。发送完 ACK 和 SYN 后,Server 端的链接状态就变成了 SYN_RCVD。

Client 收到 Server 的 ACK 后,Client 端的链接状态就变成了 ESTABLISHED 状态,同时,Client 向 Server 端发送 ACK,回复 Server 端的 SYN 请求。

Server 端收到 Client 端的 ACK 后,Server 端的链接状态也就变成了的 ESTABLISHED 状态,此时建连完成,双方随时可以进行数据传输。

(3)结合请求报文深入分析三次握手过程

1、客户端—(主动请求)—>服务端

    localhost.localdomain.57290 > 192.168.101.5.webcache: Flags [S], cksum 0x4b9e (incorrect -> 0xdc83), seq 250118291, win 29200, options [mss 1460,sackOK,TS val 4595424 ecr 0,nop,wscale 7], length 0

如上代码所示,就是客户端主动与服务器建立连接时的状态;

从上面这个数据报可以看出我们的请求的方向是:localhost.localdomain.57290 > 192.168.101.5.webcache;

我们客户端的IP和端口是:localhost.localdomain.57290 # .57290是端口

我们服务端的IP和端口是:192.168.101.5.webcache

Flags [S]:是发送了一个SYN的请求;

seq:seq序列号是250118291;(现在需要你记住这个seq号

2、服务端—(返回请求)—>客户端

192.168.101.5.webcache > localhost.localdomain.57290: Flags [S.], cksum 0xe96e (correct), seq 2336326088, ack 250118292, win 28960, options [mss 1460,sackOK,TS val 2480165653 ecr 4595424,nop,wscale 7], length 0

可看到这个请求的方向是从服务端到客户端的;

Flags [S.]:是发送了一个SYN ACK的请求

现在seq号为:2336326088;

ack 250118292:可以看到是客户端向服务端请求的seq的值+1

3、客户端—(发送确认ACK包)—>服务端

localhost.localdomain.57290 > 192.168.101.5.webcache: Flags [.], cksum 0x4b96 (incorrect -> 0x8874), seq 1, ack 1, win 229, options [nop,nop,TS val 4595426 ecr 2480165653], length 0

请求的方向是从客户端到服务端;

Flags [.]:发送ACK请求

ack 1:ack等于1

到此为止,已经建立起来了连接,剩下的就是传输数据了。

4、发送请求的数据:

    localhost.localdomain.57290 > 192.168.101.5.webcache: Flags [P.], cksum 0x4c24 (incorrect -> 0x0f76), seq 1:143, ack 1, win 229, options [nop,nop,TS val 4595426 ecr 2480165653], length 142: HTTP, length: 142
	GET /truedei/test?name=zhenghui HTTP/1.1
	User-Agent: Wget/1.14 (linux-gnu)
	Accept: */*
	Host: 192.168.101.5:8080
	Connection: Keep-Alive
	
10:49:10.095134 IP (tos 0x0, ttl 64, id 22245, offset 0, flags [DF], proto TCP (6), length 52)
    192.168.101.5.webcache > localhost.localdomain.57290: Flags [.], cksum 0x87df (correct), seq 1, ack 143, win 235, options [nop,nop,TS val 2480165654 ecr 4595426], length 0
10:49:10.097367 IP (tos 0x0, ttl 64, id 22246, offset 0, flags [DF], proto TCP (6), length 319)
    192.168.101.5.webcache > localhost.localdomain.57290: Flags [P.], cksum 0xc019 (correct), seq 1:268, ack 143, win 235, options [nop,nop,TS val 2480165657 ecr 4595426], length 267: HTTP, length: 267
	HTTP/1.1 200 
	Vary: Origin
	Vary: Access-Control-Request-Method
	Vary: Access-Control-Request-Headers
	Content-Type: text/plain;charset=UTF-8
	Content-Length: 16
	Date: Mon, 15 Jun 2020 14:49:10 GMT
	Keep-Alive: timeout=60
	Connection: keep-alive
	
	This is zhenghui[!http]

另外:

下面这个在三次握手和四次挥手中间的这个报文消息是确认收到的

10:49:10.097381 IP (tos 0x0, ttl 64, id 40566, offset 0, flags [DF], proto TCP (6), length 52)
    localhost.localdomain.57290 > 192.168.101.5.webcache: Flags [.], cksum 0x4b96 (incorrect -> 0x86cc), seq 143, ack 268, win 237, options [nop,nop,TS val 4595429 ecr 2480165657], length 0
10:49:10.097971 IP (tos 0x0, ttl 64, id 40567, offset 0, flags [DF], proto TCP (6), length 52)

2、四次挥手

(1)四次挥手报文

发现只有三段报文,书上说四次挥手,为啥不一样呢,怎么变成了三次;

TCP/TP协议详解四次挥手过程是

1.客户端发送FIN报文

2.服务端响应发送ack

3.服务端发送FIN报文

4.客户端发送响应ack报文。

而抓包结果是第二和第三也就是服务端发送的ack和FIN合并成了一个报文。

经过翻阅资料是因为请求之后,服务端直接关闭了,所以只看到了三次的请求报文,

可以参考这个博文:https://blog.csdn.net/a7980718/article/details/82316880

数据报如下:

    localhost.localdomain.57290 > 192.168.101.5.webcache: Flags [F.], cksum 0x4b96 (incorrect -> 0x86cb), seq 143, ack 268, win 237, options [nop,nop,TS val 4595429 ecr 2480165657], length 0
10:49:10.098475 IP (tos 0x0, ttl 64, id 22247, offset 0, flags [DF], proto TCP (6), length 52)
    192.168.101.5.webcache > localhost.localdomain.57290: Flags [F.], cksum 0x86cb (correct), seq 268, ack 144, win 235, options [nop,nop,TS val 2480165658 ecr 4595429], length 0
10:49:10.098487 IP (tos 0x0, ttl 64, id 40568, offset 0, flags [DF], proto TCP (6), length 52)
    localhost.localdomain.57290 > 192.168.101.5.webcache: Flags [.], cksum 0x4b96 (incorrect -> 0x86c8), seq 144, ack 269, win 237, options [nop,nop,TS val 4595430 ecr 2480165658], length 0

(2)详解四次挥手

开局一张图:TCP 的断连,如下图所示。

在这里插入图片描述

TCP 链接的关闭,通信双方都可以先发起,我们暂且把先发起的一方看作 Client,从图中看出,通信中 Client 和 Server 两端的链接都是 ESTABLISHED 状态,然后 Client 先主动发起了关闭链接请求,Client 向 Server 发送了一个 FIN 包,表示 Client 端已经没有数据要发送了,然后 Client 进入了 FIN_WAIT_1 状态。

Server 端收到 FIN 后,返回 ACK,然后进入 CLOSE_WAIT 状态。此时 Server 属于半关闭状态,因为此时 Client 向 Server 方向已经不会发送数据了,可是 Server 向 Client 端可能还有数据要发送。

当 Server 端数据发送完毕后,Server 端会向 Client 端发送 FIN,表示 Server 端也没有数据要发送了,此时 Server 进入 LAST_ACK 状态,就等待 Client 的应答就可以关闭链接了。

Client 端收到 Server 端的 FIN 后,回复 ACK,然后进入 TIME_WAIT 状态。TIME_WAIT 状态下需要等待 2 倍的最大报文段生存时间,来保证链接的可靠关闭,之后才会进入 CLOSED 关闭状态。而 Server 端收到 ACK 后直接就进入 CLOSED 状态。

(3)结合请求报文深入分析四次挥手过程

1、客户端----(发起断开请求)---->服务端

  localhost.localdomain.57290 > 192.168.101.5.webcache: Flags [F.], cksum 0x4b96 (incorrect -> 0x86cb), seq 143, ack 268, win 237, options [nop,nop,TS val 4595429 ecr 2480165657], length 0
10:49:10.098475 IP (tos 0x0, ttl 64, id 22247, offset 0, flags [DF], proto TCP (6), length 52)

可以看出方向是从客户端到服务端;

Flags [F.]:F.是FIN的请求,代表着客户端要与服务端要结束了。

这几个值:seq 143, ack 268

2、服务端------(返回ACK,和FIN)---->客户端

 192.168.101.5.webcache > localhost.localdomain.57290: Flags [F.], cksum 0x86cb (correct), seq 268, ack 144, win 235, options [nop,nop,TS val 2480165658 ecr 4595429], length 0

现在的ack是144,可以看出是143+1;

再次就把ACK和FIN合并了

3、客户端------(确认ACK断开连接)------>服务端

 localhost.localdomain.57290 > 192.168.101.5.webcache: Flags [.], cksum 0x4b96 (incorrect -> 0x86c8), seq 144, ack 269, win 237, options [nop,nop,TS val 4595430 ecr 2480165658], length 0

二、有秘密告诉你

如果对你有帮助,可以分享给你身边的朋友。或者给俺点个大大的赞和大大的评论,点赞和评论就是给我最大的支持,感谢。
水平有限,难免会有疏漏或者书写不合理的地方,欢迎交流讨论。
作者:TrueDei
作者唯一博客CSDN:https://truedei.blog.csdn.net/
转载说明:如需转载请注明原地址和作者名。

如果喜欢我的文章,还没看够可以关注我,我会用心写好每一篇文章。

我已加入CSDN合伙人计划

亲爱的各位粉丝:可以添加我的CSDN官方企业微信号,和我近距离互动聊天,为您答疑解惑

直接使用微信扫码即可,不用下载企业微信。

在这里插入图片描述

也可以加入此群:到期后,可以加我上面微信哦
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/qq_17623363/article/details/106774219