主要写了TCP和UDP协议区别
如果你感兴趣可以看一下:
https://blog.csdn.net/qq_17623363/article/details/105109907
有粉丝建议可以把握手和挥手的过程贴出来:
现在已经超过2个月了,今天终于有时间来写了一下。
下面这种图还未画完,正在继续,欢迎大家关注,或者加我CSDN官方微信群哦,加入方式在最后面
。
在做实验之前呢,我准备好了一个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;
}
}
访问测试都是没问题的:
在Linux中可以使用wget
访问:
[root@localhost ~]#
[root@localhost ~]#
[root@localhost ~]# wget http://192.168.101.5:8080/truedei/test?name=zhenghui
如果没有这个命令的话,要自行安装
[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
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]
先来看一个图三次握手的流程图:
接下来看 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 状态,此时建连完成,双方随时可以进行数据传输。
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)
发现只有三段报文,书上说四次挥手,为啥不一样呢,怎么变成了三次;
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
开局一张图: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 状态。
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官方企业微信号,和我近距离互动聊天,为您答疑解惑
。
直接使用微信扫码即可,不用下载企业微信。