计算机网络实验 实验5 运输层和应用层协议解析

Posted i-rong

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了计算机网络实验 实验5 运输层和应用层协议解析相关的知识,希望对你有一定的参考价值。

实验5 运输层和应用层协议解析

一、 实验目的

   本实验通过运用Wireshark对网络活动进行分析,观察TCP协议报文,分析通信时序,理解TCP的工作过程,掌握TCP工作原理与实现;学会运用Wireshark分析TCP连接管理、流量控制和拥塞控制的过程,发现TCP的性能问题。

二、 实验内容

任务1:TCP正常连接观察

实验准备:

 

 

 

用PC1 ping 一下PC2,看是否能ping通,观察到两主机能联通:

 

 

 

 

  1. 利用 python 自带的 SimpleHTTPServer 模块,在 PC2 上启动一个简易的 web 服务器。终端上运行 echo "TCP lab test" > index.html 创建 index.html 文件为测试站首页,运行 sudo python -m SimpleHTTPServer 80 启动一个简易 web 服务器;打开新终端,键入 ss -tln查看当前主机打开的 TCP 连接,确认 80 端口处于监听状态。

 

 

 

  1. 在 PC1 上打开一个终端,键入 sudo wireshark 启动抓包软件;再打开一个新终端,键入curl <PC2 的 IP> ;停止抓包,在 wireshark 过滤出 TCP 类型报文。观察首个 TCP 报文头,并分析各段值代表的意义。如果想要关闭相对序号/确认号,可以选择 Wireshark 菜单栏中的EditPreferenceprotocolsTCP,去掉 Relative sequence number 勾选项。使用 Wireshark 内置的绘制流功能,选择菜单栏中的 StatisticsFlow Graph, Flow Type 选择 TCP flows 可以直观地显示 TCP 序号和确认号是如何工作的。

 

 

 

实验要求:

  1. 利用Wireshark,抓包分析并截图,分析该报文TCP首部各字段的定义、值及其含义

(1)      利用Wireshark抓包并截图(保存在tcp1.pcapng中):

在Wireshark软件中设置display filter如下,进行报文过滤:

 

抓取到整个TCP报文流:

 

使用Statistics->Flow Graph工具,可以清楚地看到三次握手过程:

 

四次挥手过程:

 

可是,这里我观察到了一个“奇怪”的现象。不是说好了四次挥手吗?怎么只看到两次挥手。为了解决这个问题,我上网查找了很多资料。首先连接释放的时候不一定需要四次挥手,事实上,很多情况下都只有三次挥手。而满足三次挥手需要两个条件,当被动关闭方(上图的客户端)在TCP挥手过程中,[没有数据要发送]并且[开启了TCP延迟确认机制],那么第二次和第三次挥手就会合并传输,这样就出现了三次挥手。这里的合并传输也就是这个FIN包和ACK包合并传输了。

那么,分析完了四次挥手变成三次挥手的原因,可是我这里观察到的只有两次挥手啊,这是为什么呢?

这个问题困惑了我一整天,查阅资料发现,并不一定是客户端会主动断开连接,服务器端也有这个功能。于是我就去看了[FIN,ACK]之前的那个由服务器发给客户端的HTTP包,果然找到了答案:

 

我发现这个报文里的FIN标志位竟然是1,说明这是服务器向客户端发送的第一个FIN包,也就是第一次挥手。于是,四次挥手便再次显现出来。

(2)      分析报文TCP首部各字段的定义、值及其含义

这里,我选择了三次握手的第一个报文:SYN报文进行分析

 

下面依据TCP报文的首部格式分析该TCP报文首部各字段:

 

前两个字节是16位源端口号,该报文的源端口号为34318

 

接下来两个字节是16位目标端口号,该报文的目标端口号为80

 

接下来四个字节是32位客户端随机初始化的序列号,该报文的序列号为1551970934

 

接下来四个字节是32位的确认应答号,该报文是三次握手的第一个SYN报文,没有设置确认应答号,故该报文确认应答号为0

 

接下来4位bit是首部长度,该报文的首部长度为40Bytes

 

接下来6位标志位保留,报文中都为0

 

接下来6位标志位,该报文中只有SYN被置1

 

接下来两个字节是窗口大小,该报文的窗口大小为64240

 

接下来两个字节是校验和

 

接下来两个字节是紧急指针字段,该报文URG标志位为0,故这里的紧急指针字段也为0

 

最后的20字节是选项字段,这里不多分析

 

至此,该报文的首部各字段分析完毕。

  1. 画出该TCP流的流图

 

任务2:TCP异常传输观察分析

  1. 尝试连接未存活的主机或未监听端口

(1)      用 curl 访问一个不存在的主机 IP,抓包观察共发送了几次 SYN 报文。根据每次时间间隔变化,估算 RTO(重传超时)。

 

抓包观察到共发送了两次SYN报文:

 

估算RTO:

由上图可以大致估算出,RTO ≈ 9.514 – 6.443 = 3.071s

(2)      查看 Linux 主机的系统的 TCP 参数 SYN 重传设定:

`cat /proc/sys/net/ipv4/tcp_syn_retries`

 

(3)      更改 SYN 重传次数为 3:

`echo "3" > /proc/sys/net/ipv4/tcp_syn_retries`

注意,这里要切换到root用户下才能更改,否则会“Permission Denied”

 

(4)      再次 curl 访问,观察抓包内容。

 

(5)      关闭服务器端的 SimpleHTTPServer(ctrl+C 中断,或关闭所在终端),客户端 curl 访问服务器 80 端口,观察应答报文。

 

 

(6)      运行 nmap -sS <PC2 的 IP> 扫描服务器,并抓包。

 

 

(7)      在报告中总结以上观察结果,解释 SYN 扫描原理。

  1. 观察客户端发送了第一个SYN连接请求,服务器无响应的情景

(1)      服务器开启 telnet 或 ssh 服务,客户端先尝试连接服务器,连接成功后,在双方键入 ss -tan 查看所有 TCP 连接状态。我们看到的 TCP 连接建立过程同 1 中的 HTTP 访问类似。在客户端,利用 iptables 拦截服务器回应的 SYN ACK 包,命令如下:

` sudo iptables -I INPUT -s 192.168.13.128 -p tcp -m tcp --tcp-flags ALL SYN,ACK -j DROP `

为了让服务器能够开启ssh服务,需要先`sudo apt install openssh-server`

 

输入`sudo service ssh start`启动ssh服务

 

输入`sudo ps -e |grep ssh`查看ssh服务是否启动,观察到服务器已启动:

 

接下来尝试使用客户端连接服务器,服务器的ip为192.168.13.128

 

在客户机上使用`sudo ssh rongrong@192.168.13.128`远程连接服务器(注意这里需要root权限,否则会Permission Denied):

 

看到如上界面说明成功远程连接到了服务器。

连接成功后,在双方键入`ss -tan`查看所有TCP连接状态:

 

 

在客户端输入命令` sudo iptables -I INPUT -s 192.168.13.128 -p tcp -m tcp --tcp-flags ALL SYN,ACK -j DROP `利用iptables拦截服务器回应的SYN ACK包:

 

(2)      再次尝试连接并启动 wireshark 抓包,并在双方多次用 ss -tan 观察 TCP 状态。

 

服务器:

 

客户机:

 

(3)      观察 TCP 的状态变化,分析 wireshark 捕获的 TCP 异常报文。

 

会产生这样的异常报文的原因是,由于我们设置了防火墙,阻塞了从服务器端发过来的SYN&ACK包,这样客户机发第一个SYN包后,就始终不会收到服务器端的SYN&ACK包,它就会以为是传输过程中丢包了,于是重新传输SYN包;而服务器那边也就不会收到客户机发来的三次挥手中的最后一个ACK包,超时后就会重传SYN&ACK包。这就是产生图中异常报文的原因。

(4)      服务端的 SYN-RECV 状态何时释放?

当终端显示”Connection timed out”时释放

(5)     SYN ACK 重传了几次,时间间隔有何变化?

 

可以观察到SYN ACK重传了11次

 

可以观察到时间间隔一开始呈指数级别增大,最后稳定在16s左右

(6)      参考 1 中的操作,在服务端修改 SYN ACK 重传次数 (tcp_synack_retries),再次观察,此任务结束后清空防火墙规则 (iptables -F)。

在服务端改重传次数为3次:

 

再次观察(注意这里我连续尝试连接了两次):

 

清空防火墙规则:

 

之后就可以顺利连接了:

 

任务3:拥塞控制

  1. 配置虚拟机设置:

 

  1. 使用ftp传输大文件:

首先,我自己编写了一个程序gen_ran.c,使用命令`./gen_ran <filename> [size(MB)]`

 

该程序可生成一个大小为size的文件,名称为filename,size可选,默认为100MB

使用`./gen_ran scpfile`生成一个大小为50MB的大文件scpfile:

 

 

使用ftp传输该文件,同时使用wireshark抓包:

首先在终端输入命令`ftp 192.168.13.128`与服务端连接:

 

连接成功后显示如上。

然后使用命令`put ftpfile`传输大文件,同时wireshark抓包:

 

 

  1. 传输完毕,进行结果分析(该结果存放在ftp.pcapng中):

  

刚开始时,执行慢开始算法,说是慢开始,其实它并不慢,因为它是呈指数增长的。

超时,网络发生拥塞,这时可能连续收到三个重复确认,执行快恢复算法,拥塞窗口变为原来的一半。

然后拥塞避免算法,加法增大拥塞窗口。

任务4:HTTP协议分析

  1. 搭建HTTP1.0服务器

任务1搭建的即为HTTP1.0服务器。使用命令` sudo python -m SimpleHTTPServer 80`在虚拟机UbuntuV2上搭建服务器,在虚拟机Ubuntu 64bit上使用命令`curl 192.168.13.128`向服务器请求数据,

即可抓到HTTP1.0报文:

 

 

 

data的内容即为网页中的内容。

  1. 搭建HTTP1.1服务器

在Ubuntu 64bit中编写python脚本(源代码文本见附件),将协议的版本类型修改为HTTP/1.1,即可搭建HTTP1.1服务:

 

终端输入命令运行服务器,并打开wireshark进行抓包:

 

输入后,终端会自动打开一个网页,该网页是我在该目录下写的一个html文件(源码见附件):

 

可以使用wireshark捕捉到HTTP1.1的报文:

 

  1. 搭建HTTP2.0服务器

在搭建HTTP1.1的基础上,将协议的类型修改为HTTP2.0即可:

 

与上一步类似,使用wireshark抓包,可以抓到TLS1.2的报文,该报文是HTTP2.0报文加密后的结果:

 

若想要分析HTTP2.0报文,需要对wireshark进行解密,步骤如下:

(1)     配置系统环境变量:

在~/.profile文件下加入`export SSLKEYLOFFILE=/home/rongrong/Desktop/sslkey.log`

终端输入命令:`source ~/.profile`

重启Ubuntu。

然后打开一个浏览器,会看到密钥已经写入到sslkey.log文件中了:

 

(2)     配置Wireshark:

Wireshark->Edit->Protocols->TLS下,将(Pre)-Master-Secret log filename设置为刚刚设置的环境变量值:

 

然后就可以看到HTTP2.0报文

 

点开该报文可以看到,内容与index.html中的一致:

 

 

  1. 接下来对三种HTTP版本的报文进行分析

(1)     HTTP1.0

 

右键点击该报文,选择Follow->HTTP Stream可以追踪HTTP流:

 

 

其中,红色的部分是请求格式,蓝色的部分是响应格式,可以很清楚地看到该HTTP流的请求响应流程。

可以分析一下HTTP1.0的报文结构:

起始行是状态行:HTTP/1.0 200 OK

可以看到版本为HTTP1.0;状态码为200,表示成功;短语为OK。

(2)     HTTP1.1

 

与上一步的(1)相同,可以肯定看到HTTP stream:

 

可以对HTTP1.1的请求报文结构和响应报文结构进行分析:

起始行除了版本,其他与HTTP1.0相同

可以看到Server与HTTP/1.0不同,HTTP/1.1的Server为nginx;

HTTP/1.1报文还会将使用的是什么浏览器显示出来:Via: 1.1 google

HTTP/1.1相比于HTTP/1.0做了如下几点优化:

  • 使用长连接的方式改善了HTTP/1.0短连接造成的性能开销
  • 支持管道(pipeline)网络传输,只要第一个请求发出去了,不必等其回来,就可以发第二个请求出去,可以减少整体的响应时间。

(3)     HTTP2.0

 

与前面两步相同,我们同样可以在这里看到HTTP2.0的HTTP stream:

 

HTTP/2.0协议与HTTP/1.1协议有很大的不同,前者把后者存在的性能问题全部一一攻破了。

HTTP/2.0相比于HTTP/1.1在性能上的改进有如下几点:

l  头部压缩

HTTP/2 会压缩头(Header)如果你同时发出多个请求,他们的头是一样的或是相似的,那么,协议会帮你消除重复的部分。

这就是所谓的 HPACK 算法:在客户端和服务器同时维护一张头信息表,所有字段都会存入这个表,生成一个索引号,以后就不发送同样字段了,只发送索引号,这样就提高速度了。

l  二进制格式

HTTP/2 不再像 HTTP/1.1 里的纯文本形式的报文,而是全面采用了二进制格式,头信息和数据体都是二进制,并且统称为帧(frame):头信息帧(Headers Frame)和数据帧(Data Frame)。

这一点观察报文也能稍微看出一些区别。

 

这样虽然对人不友好,但是对计算机非常友好,因为计算机只懂二进制,那么收到报文后,无需再将明文的报文转成二进制,而是直接解析二进制报文,这增加了数据传输的效率

比如状态码 200 ,在 HTTP/1.1 是用 \'2\'\'0\'\'0\' 三个字符来表示(二进制:00110010 00110000 00110000),共用了 3 个字节,如下图:

 

在 HTTP/2 对于状态码 200 的二进制编码是 10001000,只用了 1 字节就能表示,相比于 HTTP/1.1 节省了 2 个字节,如下图:

 

l  并发传输

l  服务器主动推送资源

三、 实验结果分析

本次实验遇到了很多奇怪的现象,比如对于任务1,始终无法观察到连接释放时候的四次挥手,只能观察到两次挥手:由客户机向服务器发送一个FIN包,然后服务器再向客户机发送一个ACK包,然后就结束了,并没有观察到服务器向客户机发送的FIN包,如下图:

 

可以看到只有两次。

多次尝试好不容易抓到了一个四次挥手的报文,可是奇怪的事情又发生了。按理来说第一次的FIN包应该由客户机发给服务器才对,但是我观察到的却是服务器先发送非客户机:

 

发生这个现象的原因可能是HTTP/1.0是短连接的,每发起一个请求都要新建一次TCP连接,这样服务端就会先发FIN包;若是使用HTTP/1.1则不会是这样的现象。

 

经过我的不懈努力,搜索了大量的有关TCP抓包的资料,终于解决了上述两个问题。

以及在做观察快恢复现象的时候无法观察到与教材上相同的现象,只能根据包的数量大致分析这个阶段是在执行哪个算法。

除此以外,本次实验都完成地比较顺利。

四、 实验小结与感想

据老师所说,本次实验是最后一个需要写实验报告的实验。太好啦!终于不用写实验报告啦!!!

不过,和wireshark打了快一个学期的交道了,我深深感受到了wireshark这个抓包工具的强大。它除了可以抓包外,还提供了可视化分析网络包的图形界面,还内置了一系列的汇总分析工具。就拿本次实验来说,我就用到了许多除了抓包以外的工具,比如Flow Graph以及IO Graph里面的HTTP Stream等工具。通过这些工具分析流,可比光看报文方便多了。

五、 思考题

  1. 在 TCP 状态机中,有些状态停留时间较长,易观察到,有些状态很短暂不易观察到。试列出不易观察到的状态,并考虑观察到它们的可能方法。

不易观察到的状态有: FIN_WAIT_1、FIN_WAIT_2、CLOSE_WAIT、LAST_ACK。可以阻断中间的某个报文,以观察到接下来预计达到的状态。

  1. TCP 在不可靠的 IP 层上建立了可靠的端对端连接,如果要在不可靠的 UDP 上建立可靠的端对端传输系统,需要考虑哪些方面?

现在市面上已经有基于 UDP 协议实现的可靠传输协议的成熟方案了,那就是 QUIC 协议,已经应用在了 HTTP/3。

要基于 UDP 实现的可靠传输协议,那么就要在应用层下功夫,也就是要设计好协议的头部字段。

需要把TCP 可靠传输的特性(序列号、确认应答、超时重传、流量控制、拥塞控制)在应用层全部实现一遍。

六、 附件

gen_ran.c

#include<stdio.h>

#include<stdlib.h>

#include<time.h>

#include<stdint.h>

 

#define ONE_MB_SIZE 262144

int32_tout[ONE_MB_SIZE];

 

intmain(intargc, char* argv[])

    if(argc < 2 || argc > 3)

        fprintf(stderr, "Usage: ./gen_ran <filename> [size(MB)]\\n");

        exit(1);

   

    int size;

    if(argc == 2) size = 100; // 如果只有两个参数即只有一个文件名称默认生成100MB的文件

    else size = atoi(argv[2]);

    FILE* outfile;

    if((outfile = fopen(argv[1], "wb")) == NULL)

        fprintf(stderr, "open error\\n");

        exit(1);

   

    srand((unsignedint)time(0));

    int i, j;

    for(i = 1; i <= size; i++)

        for(j = 0; j < ONE_MB_SIZE; j++)

            out[j] = rand();

       

        fwrite(out, sizeof(int32_t), ONE_MB_SIZE, outfile);

   

    fprintf(stdout, "random input file %s was generated successfully\\n", argv[1]);

    exit(0);

 

HTTPserver.py

   import json

from http.server import HTTPServer, SimpleHTTPRequestHandler

import webbrowser

 

ip = "localhost"  # 监听IP,配置项

port = 8800  # 监听端口,配置项

index_url = "http://%s:%d/index.html" % (ip, port)  # 监听主页url,配置项

 

# 创建http server

classGetHttpServer(SimpleHTTPRequestHandler):

    protocol_version = "HTTP/1.0"

    server_version = "PSHS/0.1"

    sys_version = "Python/3.9.x"

    target = "./"  # 监听目录,配置项

 

    defdo_get(self):

        ifself.path.find("/json/") > 0:

            print(self.path)

            self.send_response(200)

            self.send_header("Content-type", "json")

            self.end_headers()

            req = "success": "ok"

            self.wfile.write(req.encode("utf-8"))

        else:

            SimpleHTTPRequestHandler.do_GET(self)

 

    defdo_post(self):

        ifself.path == "/signin":

            print("postmsg recv, path right")

        else:

            print("postmsg recv, path error")

            data = ""

            data = json.loads(data)

            self.send_response(200)

            self.send_header("Content-type", "text/html")

            self.end_headers()

            rspstr = "recv ok, data = "

            rspstr += json.dumps(data, ensure_ascii=False)

            self.wfile.write(rspstr.encode("utf-8"))

 

defhttp_server():

    server = HTTPServer((ip, port), GetHttpServer)

    try:

        # 弹出窗口

        webbrowser.open(index_url)

        # 输出信息

        print("服务器监听地址: ", index_url)

        server.serve_forever()

    exceptKeyboardInterrupt:

        server.socket.close()

 

# 执行服务器脚本

http_server()

 

index.html

<!DOCTYPEhtml>

<htmllang="en">

<head>

    <metacharset="UTF-8">

    <metahttp-equiv="X-UA-Compatible"content="IE=edge">

    <metaname="viewport"content="width=device-width, initial-scale=1.0">

    <title>Document</title>

</head>

<body>

    hello world

</body>

</html>

第三次实验报告:通过抓取TCP了解运输层

第三次实验报告:通过抓取TCP了解运输层

  • 姓名:王璐璐
  • 学号:201821121037
  • 班级:计算1812

0 摘要

 在本次实验中,通过对TCP报文的解析,理解TCP协议的连接建立与连接释放过程,以此了解运输层之间可靠传输的工作原理。在使用Cisco Packet Tracer时,将会通过路由器来连接客户端与服务器,在此次实验中还会使用命令行来设置路由器,以此达到网络的联通。

1 实验目的

使用路由器连接不同的网络

  • 使用命令行操作路由器
  • 通过抓取HTTP报文,分析TCP连接建立的过程

2 实验内容

使用Packet Tracer,正确配置网络参数,通过抓取HTTP数据包,分析TCP连接建立过程。

  • 建立网络拓扑结构
  • 配置参数
  • 抓包
  • 分析数据包

3 实验报告

此次实验报告主要是通过建立客户端、路由器与服务器之间的连接,分析TCP运输的连接建立中的三次握手与连接释放的四次握手,借此了解运输层是如何达到可靠传输的。

3.1 建立网络拓扑结构

技术图片

 

 

上图中PC-PT为客户端,Router为路由器,Server-PT为服务器,图中连线中的红色倒三角表示线路还未联通,客户端还无法访问到服务器。

3.2 配置参数 

3.2.1 客户端IP地址的设置

技术图片

 

 3.2.2 服务器IP地址的设置

技术图片

 

 

在设置完客户端与服务器的IP地址后,我们将对路由器中的各个参数进行设置,将处于两个网络中的客户端与服务器联系起来。

3.2.3 路由器参数的设置

技术图片

1)以下是上图中各行代码所表示的含义:

Router>enable                                               # 进入特权执行模式 

Router#configure terminal                             # 进入全局配置模式 

Router(config)#hostname R                          # 将路由器名称配置为R 

2)配置G0/0接口: 

R(config)#interface G0/0                               #进入端口配置模式

R(config-if)#ip address 192.168.1.80 255.255.255.0    #配置端口

R(config-if)#no shutdown                              # 激活接口 

3)当配置完路由器的端口号时,客户端与服务器之间的连接确立,下图是成功连接后的网络拓扑结构:

技术图片

4)路由器的参数设置好后,我们需要对客户端与服务器的IP地址中的默认网关进行设置,其图如下:

客户端IP地址默认网关的设置——

技术图片

服务器IP地址默认网关的设置——

技术图片

5)即使客户端与服务器之间连接成功,两者之间也无法做到可靠传输,所以我们需要对路由器设置一个协议,通过该路由协议来约定客户端与服务器之间传输连接。

3.2.4 路由协议的配置

技术图片

R(config)#router rip                       #进入rip路由协议配置模式

R(config-router)#version 2               #选择的rip的版本

R(config-router)#no auto-summary    #关闭自动路由汇总

R(config-router)#network 192.168.1.0

R(config-router)#network 192.168.2.0    #设置参与RIP协议的网络地址

对路由器设置完路由协议后,我们可以通过以下两个命令来验证路由器的连接情况:

1)R#show ip interface brief                   #检验IP地址正确并且接口处于激活状态

技术图片

2)R#show ip route                                    #查看路由表

 

技术图片

 

 3)ping 192.168.2.37                                   #在客户端上ping服务器,测试客户端与服务器之间能否正常通信

技术图片

3.3 抓包,分析TCP连接建立过程

3.3.1 打开客户端的浏览器,对服务器进行访问

技术图片

3.3.2 在仿真过程中,获取的数据包如下图,我们将会得到TCP包与HTTP包

技术图片

 

 

 3.3.3 画出TCP连接建立示意图

技术图片

3.3.4 分析序号和确认号的变化

1)上图第一个箭头表示客户端与服务器之间的第一次握手,在该次握手中,同步位SYN的值为1,表示PC向Server发出了连接请求,在发出连接请求时,设置了一个初始序号,即seq=0,并对确认号设置一个初值;

2)第二个箭头表示客户端与服务器之间的第二次握手,此次握手是Server向PC发送的确认报文,因此报文中的ACK与SYN均为1,并将改变ack的值,即ack=上一个报文中seq值+1,表示上一个报文中传输的数据全都正确收到,除此之外,还要再设置一个起始序号值,即seq值;

3)第三个箭头表示客户端与服务器之间的第三次握手,该次握手是发生在PC收到来自Server返回的确认包后,再次向Server发送一个确认包,该数据包中的起始序号值来源于Server发送回来的确认包中的确认号,即seq=上一个报文中ack的值,而对于确认号的设置则根据上一个报文中的序号进行设置,即ack=上一个报文中的seq值+1.

3.3.5 解答连接建立为什么要第三次握手

进行第三次的握手只要是为了防止客户端中发送的已失效的连接请求报文段突然又传送到服务器中,导致服务器认为又重新建立了运输连接,为新的连接开辟资源,造成资源的浪费。

3.4 TCP连接释放分析

由于TCP是面向连接的协议,所以用运输连接来传送TCP报文,而一条运输连接有三个阶段,即连接建立、数据传输、连接释放。在上面已经对TCP的连接建立过程进行了简单的分析,接下来将会对TCP的连接释放进行简单地分析。

3.4.1 画出TCP连接释放的示意图

技术图片

 

 3.4.2 解答连接释放为什么需要四次握手

当客户端中的数据都传送给了服务器时,客户端发送连接释放请求,服务器收到该请求后并不会马上就关闭SOCKET,服务器只能先发送一个ACK报文告诉客户端它发送的连接释放请求已收到。当服务器中的报文都发送完后,服务器才会向客户端发送FIN报文,因此服务器的ACK报文与FIN报文不会同时发送,需要四次握手才可以释放TCP运输连接。

以上是关于计算机网络实验 实验5 运输层和应用层协议解析的主要内容,如果未能解决你的问题,请参考以下文章

计算机网络概述

一 计算机网络

高级网络应用复习——三层和生成树实验 加 命令

TCP/IP协议

运输层知识要点——谢希仁《计算机网络》

第四次实验报告:RIP路由协议的解析