首页 > 自考资讯 > 自考知识

TCP的“三握手四挥手”你真的了解吗?

2024-08-26

大家好,今天给各位分享TCP的“三握手四挥手”你真的了解吗?的一些知识,其中也会对进行解释,文章篇幅可能偏长,如果能碰巧解决你现在面临的问题,别忘了关注本站,现在就马上开始吧!

什么是“3次握手,4次挥手”TCP服务模型?为什么TCP头状态转换需要“3次握手,4次挥手”和“3次握手,4次挥手”?如何完成“三次握手、四次挥手”?三次握手,四次挥手。为什么建立连接是三向握手,关闭连接却是四向挥手? “三次握手,四次挥手” 高级ISN 序列号环绕Syn Flood 攻击无效连接监控和释放延迟TCB 分配方法使用SYN Proxy 防火墙连接队列半连接队列已满全连接队列已满命令摘要“三次握手,四次” Wave”redis实例分析参考。记得毕业后找工作面试时,经常有人问我:你知道“3次握手,4次挥手”吗?这时,我会“信心十足”地“背诵”我事先准备好的“答案”,第一次、第二次……答案之后就没有了,面试官似乎也没有要走的意思。更深。虽然我也不太明白,但是大家都很开心!

作为一名程序员,必须要有“刨根问底”的精神。你知道它是什么,你还需要知道为什么会这样。本文希望能够揭开茧的面纱,还原其背后的原理。

什么是“3次握手,4次挥手”

TCP 是面向连接的单播协议。在发送数据之前,通信双方必须建立彼此之间的连接。所谓“连接”,其实就是客户端和服务器端内存中保存的一条关于彼此的信息,比如IP地址、端口号等。

TCP 可以被视为处理IP 层或以下层的数据包丢失、重复和错误的字节流。在连接建立过程中,双方需要交换一些连接参数。这些参数可以放置在TCP 标头中。

TCP提供可靠的、面向连接的、字节流、传输层服务,使用三向握手来建立连接。使用4 次挥手来关闭连接。

TCP服务模型

了解了建立和关闭连接的“三次握手、四次挥手”之后,我们再来看看TCP相关的东西。

TCP 连接由一个4 元组组成,即两个IP 地址和两个端口号。一个TCP连接通常分为三个阶段:启动、数据传输、退出(关闭)。

当TCP接收到另一端的数据时,它会发送一个确认,但这个确认不会立即发送,通常会延迟一段时间。 ACK 是累积的。确认字节数N的ACK表示已成功接收到N(不包括N)的所有字节。这样做的好处是,如果一个ACK 丢失,很可能后续的ACK 就足以确认前一个报文段。

完整的TCP连接是双向的、对称的,数据可以在两个方向上平等地流动。向上层应用程序提供双工服务。连接建立后,连接一个方向上的每个TCP 段都包含相反方向段的ACK。

序列号的目的是使TCP接收端能够丢弃重复的报文段并记录以混乱顺序到达的报文段。由于TCP使用IP来传输报文段,因此IP不提供重复数据删除或确保正确顺序的功能。另一方面,TCP是字节流协议,永远不会以混乱的顺序向上层程序发送数据。因此,TCP接收端将被迫保留大序号的数据不被移交给应用程序,直到填补了丢失的小序号段。

TCP头

源端口和目的端口决定了TCP层双方的进程。序列号表示消息段数据中的第一个字节号。 ACK代表确认号。确认号的发送方期望接收下一个序列号,即最后成功接收到的数据字节的序列号加1。该字段仅在ACK位使能时有效。

当一个新的连接建立时,从客户端发送到服务器的第一个报文段的SYN位被使能。这称为SYN 段。此时,序列号字段包含了本次连接的该方向所要使用的信息。第一个序列号,即初始序列号ISN,之后发送的数据是ISN加1,所以SYN位域会消耗一个序列号,也就是说重传是为了可靠传输。不消耗序列号的ACK 则不是。

头长度(图中数据偏移量)以32位字为单位,即以4字节为单位,只有4位,最大为15,所以头的最大长度为60字节,最小为5、即最小标头大小为20字节(变量选项为空)。

ACK —— 确认,使确认号有效。

RST —— 重置连接(通常由对等方重置)是此字段的作用。

SYN —— 用于初始化连接的序列号。

FIN —— 该报文段的发送方已完成向对方发送数据。

当建立或终止连接时,交换的段仅包含TCP 标头,不包含数据。

状态转换

三向握手和四向挥手之间的状态转换如下所示。

为什么要“三次握手,四次挥手”

三向握手

我们从通俗易懂的角度来看看为什么需要三向握手。

客户端和服务器在通信之前必须先建立连接。 “3次握手”的作用是双方都可以知道自己和对方的接收和发送能力是否正常。

第一次握手:客户端发送网络数据包,服务器接收。这样,服务器就可以断定客户端的发送能力和服务器的接收能力都是正常的。

第二次握手:服务器发送数据包,客户端接收。这样,客户端就可以断定服务器的接收和发送能力以及客户端的接收和发送能力是正常的。

从客户端的角度来看,我收到了服务器发送的响应包,这意味着服务器收到了我第一次握手时发送的网络包,并成功发送了响应包。这说明服务器的接收和发送能力正常。另一方面,我收到了服务器的响应包,说明我第一次发送的网络包成功到达了服务器。这样我自己的发送和接收能力也正常了。

第三次握手:客户端发送数据包,服务器接收。这样,服务器就可以断定客户端的接收和发送能力以及服务器的发送和接收能力是正常的。

经过第一次和第二次握手后,服务器并不知道客户端的接收能力和自身的发送能力是否正常。在第三次握手期间,服务器收到了客户端对第二次握手的响应。从服务器的角度来看,我在第二次握手中的响应数据已发送,客户端也收到了。所以,我的发送能力是正常的。客户的接待能力也正常。

经过上述三次握手过程后,客户端和服务器双方都确认自己的接收和发送能力正常。之后就可以正常通讯了。

每次,接收数据包的一方都可以得出一些结论,但发送方实际上没有任何线索。虽然我已经发送了数据包,但是我怎么知道我是否发送了,对方是否收到了呢?

从上面的过程可以看出,至少需要3次握手。两次,双方都无法断定自己和对方的接收和发送能力都是正常的。事实上,每次接收网络数据包的一方至少可以得到:对方的发送和我们的接收都正常。每个步骤都是相关的。下一个“响应”是由第一个“请求”触发的,因此每次握手实际上都可以得到额外的结论。例如,第三次握手时,服务器收到数据包,说明服务器只能获取客户端的发送能力,服务器的接收能力正常。但是,结合第二次握手,表明服务器在第二次发送的响应中客户端收到了数据包并做出了响应,从而得出一个额外的结论:客户端的接收和服务器的发送都正常。

我们用一个表格来总结一下:

视角客户接收客户发送服务器接收发送客户视角二一+二一+二二服务器视角二+三一一二+三

挥手四次

TCP连接是一种点对点的双向传输模式,这意味着双方可以同时向对方发送或接收数据。当一方想要关闭连接时,就会发送一条指令,通知另一方我要关闭连接。此时对方会回复一个ACK,一个方向的连接就关闭了。但另一个方向仍然可以继续传输数据。当所有数据发送完毕后,会发送一个FIN报文段来关闭该方向的连接。接收方发送ACK 来确认关闭连接。请注意,接收FIN 消息的一方只能回复ACK。它无法立即返回FIN报文段给对方,因为结束数据传输的“指令”是上层应用层给出的,而我只是一个“搬运工”,无法理解“上头的旨意” 。

“三次握手,四次挥手”怎么完成?

其实3次握手的目的不仅是让通信双方都知道连接正在建立,也是利用数据包的选项来传输特殊信息,交换初始序列号ISN。

三次握手意味着发送三个报文段,四次握手意味着发送四个报文段。请注意,SYN 和FIN 段都会使用重传来实现可靠传输。

三次握手

客户端发送一个SYN报文段并指定客户端的初始序列号,即ISN(c)。服务器发送自己的SYN 段作为响应,同时指定自己的ISN。要确认客户端的SYN,请使用ISN(c)+1 作为ACK 值。这样,每发送一个SYN,序列号就会加1,如果有丢失,就会重传。为了确认服务器端的SYN,客户端使用ISN(s)+1作为返回的ACK值。挥手四次

客户端发送FIN 段并包含其希望接收方能够看到的当前序列号K。它还包含一个ACK来确认对方发送的最新数据。服务器在K值上加1作为ACK序号值,表示已经收到前一个数据包。这时,上层应用程序会被通知对方发起了关闭操作,这通常会导致应用程序发起自己的关闭操作。服务器发起自己的FIN报文段,ACK=K+1,Seq=L,客户端确认。 ACK=L+1 为什么建立连接是三次握手,关闭连接却是四次握手?

这是因为在LISTEN状态下,服务器收到建立连接请求的SYN报文后,会将ACK和SYN放在一个报文中发送给客户端。关闭连接时,当收到对方的FIN报文时,仅表示对方不再发送数据,但仍可以接收数据。此时己方是否关闭发送数据通道需要由上层应用程序决定。因此,自己的ACK和FIN一般都会分开发送。

“三次握手,四次挥手”进阶

ISN

三次握手的一个重要作用是客户端和服务器交换ISN(初始序列号),以便对方知道下次接收数据时如何根据序列号组装数据。

TCP的“三握手四挥手”你真的了解吗?

如果ISN是固定的,攻击者很容易猜测后续的确认号。

ISN=M + F(localhost,localport,remotehost,remoteport)M是一个计时器,每4毫秒增加1。

F是Hash算法,根据源IP、目的IP、源端口、目的端口生成随机值。需要保证哈希算法不能轻易被外界算出。

序列号环绕

由于ISN 是随机的,因此序列号很容易超过2^31-1。 TCP对丢包、重排序等问题的判断依赖于序列号大小比较。这时候就出现了所谓的TCP序列环绕问题。怎么解决呢?

/** 接下来的例程处理比较32 位无符号整数* 并担心环绕(自动使用无符号算术)。*/static inline int before(__u32 seq1, __u32 seq2){ return (__s32)(seq1-seq2) 0; }#define after(seq2, seq1) before(seq1, seq2) 以上代码是内核中解决环绕问题的代码。 __s32 表示有符号整数类型,而__u32 表示无符号整数类型。序列号环绕后,序列号变小。相减后,结果变成有符号数,因此结果变成负数。

假设seq1=255,seq2=1(发生回绕)。 seq1=1111 1111 seq2=0000 0001我们希望比较结果是seq1 - seq2=1111 1111-0000 0001----------- 1111 1110既然我们把结果转换成了有符号数,因为最高位是1、所以结果是负数,负数的绝对值为0000 0001 + 1=0000 0010=2 因此seq1 - seq2 0syn 洪水攻击

最基本的DoS攻击是利用合理的服务请求来占用过多的服务资源,使合法用户无法得到服务的响应。 Syn Flood 是一种DoS 攻击。

如果恶意向某个服务器端口发送大量SYN数据包,服务器就可以打开大量半开连接并分配TCB(传输控制块),从而消耗大量服务器资源并进行正常连接请求无法回复。当TCP端口打开时,该端口处于Listening状态,持续监听发送到该端口的Syn报文。一旦收到来自Client的Syn消息,就需要为该请求分配一个TCB,通常一个TCB至少需要280字节。在某些操作系统中,TCB甚至需要1300字节。它返回SYN ACK 命令并立即更改为SYN-RECEIVED,这是半开连接状态。系统将耗尽资源。

常见的攻击防御方法包括:

监控无效连接的释放

监视系统中半开和不活动的连接,并在达到特定阈值时拆除这些连接,从而释放系统资源。该方法对所有连接一视同仁,而且由于SYN Flood造成大量的半开连接,正常的连接请求也会通过这种方式被淹没并错误释放,所以该方法是一种入门级的SYN Flood方法。

延迟TCB分配方法

消耗服务器资源的主要原因是当SYN数据包到达时,系统立即分配TCB,从而占用资源。由于SYN Flood很难建立正常连接,因此在正常连接建立后分配TCB可以有效减少服务器资源的消耗。常见的方法是使用Syn Cache和Syn Cookie技术。

同步缓存技术

当系统收到SYN报文时,会将此半连接信息保存在专用的HASH表中,直到收到正确的响应ACK报文后才分配TCB。这个开销比TCB少很多。当然你还需要保存序列号。

同步饼干技术

Syn Cookie技术根本不使用任何存储资源。这个方法比较巧妙。它使用特殊的算法来生成序列号。这个算法考虑到了对方的IP、端口、自己的IP和端口等固定信息,而对方无法知道自己这边的一些相对固定的信息,比如MSS(Maximum Segment Size,指最大数据报) TCP报文长度,不包括TCP头长度。)、时间等,收到对方收到ACK报文后,重新计算看是否与报文中的(Sequence Number-1)相同对方的响应消息,从而决定是否分配TCB资源。

使用SYN 代理防火墙

一种方法是阻止防火墙在阻止dqywb 连接的有效性后向内部服务器发起SYN 请求。防火墙代表服务器发送的SYN ACK报文所使用的序列号为c,真实服务器响应的序列号为c'。这样,每个数据包通过防火墙时,序列号都会被修改。另一种方式是,防火墙判断连接安全后,会发出安全重置命令,客户端重新连接,此时出现的syn数据包会直接释放。这样就不需要修改序列号了。但客户端需要发起两次握手,因此建立连接的时间会延长。

连接队列

当外部请求到达时,在最终被服务程序感知之前,连接可能处于SYN_RCVD状态或ESTABLISHED状态,但尚未被应用程序接受。

相应的,服务器也会维护两个队列,SYN_RCVD状态的半连接队列,以及ESTABLISHED状态但尚未被应用程序接受的全连接队列。如果这两个队列满了,就会出现各种丢包的情况。

检查是否有连接溢出netstat -s | grep LISTEN 半连接队列已满

在三向握手协议中,服务器维护了一个半连接队列,为每个客户端的SYN数据包打开一个条目(当服务器收到SYN数据包时,它已经创建了request_sock结构并将其存储在半连接中)队列),该条目表明服务器已收到SYN数据包,向客户端发送了确认,正在等待客户端的确认数据包。这些条目标识的连接在服务器上处于Syn_RECV 状态。当服务器收到客户端的确认报文后,该表项被删除,服务器进入ESTABLISHED状态。

目前,Linux 默认会重发SYN-ACK 数据包5 次。重试间隔从1s开始。下一次重试间隔是前一次重试间隔的两倍。 5次重试间隔为1s、2s。4s,8s,16s,一共31s,这就是所谓的指数退避。第五次之后还要等32s才知道第五次也超时了。因此,总共需要1s + 2s + 4s + 8s + 16s + 32s=63s, TCP 才会断开连接。由于SYN超时需要63秒,这给了攻击者攻击服务器的机会。攻击者在短时间内向服务器发送大量SYN数据包(俗称SYN洪水攻击),以耗尽服务器的SYN队列。为了处理SYN过多的问题,Linux提供了几个TCP参数:tcp_syncookies、tcp_synack_retries、tcp_max_syn_backlog、tcp_abort_on_overflow来调整响应。

参数函数tcp_syncookiesSYNcookie将连接信息编码为ISN(initialsequencenumber)并返回给客户端。此时服务器不需要将半连接保存在队列中,而是利用客户端后续发送的ACK带回的ISN来恢复连接信息。完成连接的建立,防止半连接队列被攻击SYN报文填满。 tcp_syncookies内核放弃建立连接之前发送的SYN数据包的数量。 tcp_synack_retries 内核在放弃连接之前发送的SYN+ACK 数据包的数量。 tcp_max_syn_backlog默认值为1000,表示半连接队列的长度。如果超过,则当前连接将被放弃。如果设置了tcp_abort_on_overflow,则直接重置。否则,不执行任何操作,以便当服务器的半连接队列为空时,将重新接受连接。 Linux 坚持在其能力范围内不忽略传入的连接。在此期间客户端会重复发送sys报文。当重试次数达到上限时,会得到连接超时响应。

全连接队列已满

在第三次握手期间,当服务器收到ACK数据包时,它将进入一个名为accept的新队列。

当accept队列满时,即使客户端继续向服务器发送ACK包,也不会得到响应。此时ListenOverflows+1,服务器通过tcp_abort_on_overflow来决定如何返回。 0表示直接丢弃ACK,1表示发送RST通知。客户;相应地,客户端将分别返回读取超时或连接重置。另外,如果tcp_abort_on_overflow为0,服务器会在一段时间后再次向客户端发送syn+ack(即重新进行第二步握手)。如果客户端超时等待时间短,很容易引发异常。如果客户端收到多个SYN ACK数据包,它会认为之前的ACK数据包丢失了。这会提示客户端再次发送ACK,最终在accept队列空闲时完成连接。如果accept队列一直满的话,客户端最终会收到RST包(此时服务器发送syn+ack的次数超过了tcp_synack_retries)。

服务器只是创建一个计时器,并以固定的时间间隔向服务器重新传输syn 和ack。

参数功能tcp_abort_on_overflow 如果设置了此项,则直接重置。否则,不执行任何操作,以便当服务器的半连接队列变空时,将再次接受连接。 Linux 坚持在其能力范围内不忽略传入的连接。在此期间客户端会重复发送sys报文。当重试次数达到上限时,会收到连接超时响应。 min(backlog, somaxconn)全连接队列的长度。

命令

netstat -s 命令

[root@server ~]# netstat -s | egrep '听|听'

667399次socket监听队列溢出

667399 SYN 到LISTEN 套接字被忽略

比如上面看到的667399次就表示全连接队列溢出的次数。如果每隔几秒执行一次,如果这个数字不断增加,那么全连接队列肯定偶尔会满。

[root@server ~]# netstat -s | grep TCPBacklogDrop

检查Accept队列是否溢出

SS命令

[root@server ~]# ss -lnt

状态Recv-Q Send-Q 本地地址:端口对等地址:端口

听0 128 :6379 :

听0 128 :22 :

如果State为监听状态,则Send-Q表示第三列监听端口上的全连接队列最大数量为50,第一列Recv-Q表示当前使用了多少个全连接队列。

在非LISTEN状态下,Recv-Q表示接收队列中的字节数; Send-Q表示发送队列中的字节数。

概括

当外部连接请求到来时,TCP模块会首先检查max_syn_backlog。如果处于SYN_RCVD状态的连接数量超过此阈值,传入的连接将被拒绝。直接根据tcp_abort_on_overflow字段判断是丢弃还是重置。

TCP的“三握手四挥手”你真的了解吗?

从服务器端来说,三次握手中,第一步,服务器收到客户端发来的syn后,将相关信息放入半连接队列中,并向客户端回复syn+ack。第三步,当它收到客户端的ack时,它的连接就被添加到全连接队列中。

一般满连接队列比较小,会先满。此时半连接队列还没有满。如果此时收到syn消息,就会进入半连接队列,没问题。但如果收到三次握手中的第三步(ACK),则会根据tcp_abort_on_overflow字段决定是直接丢弃还是直接重置。这时客户端发送一个ACK,那么客户端就认为三次握手完成了,就认为服务端已经准备好接收数据了。但此时服务器可能因为全连接队列已满而无法放入连接,会重新发送第2步中的syn+ack。如果此时有数据到达,服务器TCP模块会将数据存储起来在队列中。一段时间后,客户端没有收到回复,超时,连接异常,客户端会主动关闭连接。

“三次握手,四次挥手”redis实例分析

我在dev机上部署了redis服务,端口号为6379,通过tcpdump工具获取数据包,使用如下命令tcpdump -w /tmp/a.cap port 6379 -s0-w 进行写入将数据写入文件, -s0 设置每个数据包的大小默认为68字节。如果使用-S 0,将捕获完整的数据包。使用redis-cli访问dev2机器上的dev:6379,发送ping,得到回复pong停止抓包,使用tcpdump读取。获取捕获的数据包tcpdump -r /tmp/a.cap -n -nn -A -x| vim - (-x以十六进制形式显示,方便后面分析)共收到7个数据包。

捕获的是IP数据包。 IP数据包分为IP头和IP数据部分。 IP数据部分是TCP报头加上TCP数据部分。

IP的数据格式为:

它由固定长度20B+可变长度组成。

10:55:45.662077 IP dev2.39070 dev.6379: 标志[S],seq 4133153791,win 29200,选项[mss 1460,sackOK,TS val 2959270704 ecr 0,nop,wscale 7],长度00x0 000: 4500 003c 08cf 4000 3606 14a5 0ab3 b5610x0010: 0a60 5cd4 989e 18eb f65a ebff 0000 00000x0020: a002 7210 872f 0000 0204 05b4 0402 080a0x0030: b062 e330 0000 0000 0103 0307 利用IP头格式拆解数据包的具体含义。

其余数据部分与TCP协议有关。 TCP也是20B定长+变长部分。

字节值字节含义0x989e16bit源端口。 1161616+81616+1416+11=390700x18eb16bit目标端口63790xf65a ebff32bit序列号。 41331537910x0000 000032位确认号。0xa4bit头长度,以4byte为单位。总计10*4=40 字节。因此,TCP消息的可选长度为40-20=200b0000006bit保留位。当前设置为0.0b0000106bitTCP 标志。从左到右分别是紧急URG、确认ACK、推送PSH、复位RST、同步SYN、终止FIN。0x7210 滑动窗口大小。滑动窗口是TCP接收缓冲区的大小,用于TCP拥塞控制。 2

92000x872f16bit校验和。0x0000紧急指针。仅在 URG = 1时才有意义,它指出本报文段中的紧急数据的字节数。当 URG = 1 时,发送方 TCP 就把紧急数据插入到本报文段数据的最前面,而在紧急数据后面的数据仍是普通数据。 可变长度部分,协议如下: 字节值字节含义0x0204 05b4最大报文长度为,05b4=1460. 即可接收的最大包长度,通常为MTU减40字节,IP头和TCP头各20字节0x0402表示支持SACK0x080a b062 e330 0000 0000时间戳。Ts val=b062 e330=2959270704, ecr=00x01无操作0x03 0307窗口扩大因子为7. 移位7, 乘以128 这样第一个包分析完了。dev2向dev发送SYN请求。也就是三次握手中的第一次了。 SYN seq(c)=4133153791 第二个包,dev响应连接,ack=4133153792. 表明dev下次准备接收这个序号的包,用于tcp字节注的顺序控制。dev(也就是server端)的初始序号为seq=4264776963, syn=1. SYN ack=seq(c)+1 seq(s)=4264776963 第三个包,client包确认,这里使用了相对值应答。seq=4133153792, 等于第二个包的ack. ack=4264776964. ack=seq(s)+1, seq=seq(c)+1 至此,三次握手完成。接下来就是发送ping和pong的数据了。 接着第四个包。 10:55:48.090073 IP dev2.39070 > dev.6379: Flags [P.], seq 1:15, ack 1, win 229, options [nop,nop,TS val 2959273132 ecr 3132256230], length 14 0x0000: 4500 0042 08d1 4000 3606 149d 0ab3 b561 0x0010: 0a60 5cd4 989e 18eb f65a ec00 fe33 5504 0x0020: 8018 00e5 4b5f 0000 0101 080a b062 ecac 0x0030: bab2 6fe6 2a31 0d0a 2434 0d0a 7069 6e67 0x0040: 0d0atcp首部长度为32B, 可选长度为12B. IP报文的总长度为66B, 首部长度为20B, 因此TCP数据部分长度为14B. seq=0xf65a ec00=4133153792 ACK, PSH. 数据部分为2a31 0d0a 2434 0d0a 7069 6e67 0d0a 0x2a31 -> *10x0d0a -> \r\n0x2434 -> $40x0d0a -> \r\n0x7069 0x6e67 -> ping0x0d0a -> \r\ndev2向dev发送了ping数据,第四个包完毕。 第五个包,dev2向dev发送ack响应。 序列号为0xfe33 5504=4264776964, ack确认号为0xf65a ec0e=4133153806=(4133153792+14). 第六个包,dev向dev2响应pong消息。序列号fe33 5504,确认号f65a ec0e, TCP头部可选长度为12B, IP数据报总长度为59B, 首部长度为20B, 因此TCP数据长度为7B. 数据部分2b50 4f4e 470d 0a, 翻译过来就是+PONG\r\n. 至此,Redis客户端和Server端的三次握手过程分析完毕。

用户评论

折木

这篇文章太棒了!终于让我彻底理解了TCP的“三握手四挥手”,之前一直都是模棱两可的。

    有12位网友表示赞同!

荒野情趣

之前对“三握手四挥手”的概念很模糊,这篇文章解释得非常清晰,通俗易懂。

    有7位网友表示赞同!

堕落爱人!

看了这篇文章,终于明白TCP连接建立和断开过程的细节了,对网络协议的理解更深了一层。

    有20位网友表示赞同!

此刻不是了i

“三握手四挥手”原来如此复杂!这篇文章分析得非常透彻,让我对TCP协议有了更深入的认识。

    有15位网友表示赞同!

心已麻木i

没想到TCP连接建立和断开的过程这么复杂,这篇文章用图示解释得很清楚,易于理解。

    有14位网友表示赞同!

有一种中毒叫上瘾成咆哮i

这篇文章简直就是“三握手四挥手”的宝典,强烈推荐给所有想要学习网络协议的朋友。

    有16位网友表示赞同!

金橙橙。-

终于找到了一篇解释“三握手四挥手”的文章,而且写的很好懂,强烈推荐!

    有13位网友表示赞同!

迷路的男人

感谢作者的分享!这篇文章让我对TCP协议的理解更加深刻,受益匪浅。

    有5位网友表示赞同!

命该如此

之前一直对“三握手四挥手”不太理解,现在看了这篇文章,终于豁然开朗了!

    有11位网友表示赞同!

命硬

这篇文章讲得通俗易懂,让我对TCP协议有了全新的认识,强烈推荐!

    有11位网友表示赞同!

鹿先森,教魔方

原来“三握手四挥手”还有这么多细节,这篇文章分析得很到位,值得学习。

    有12位网友表示赞同!

病态的妖孽

不错,文章写的很好,对TCP的“三握手四挥手”解释得非常清楚。

    有18位网友表示赞同!

一别经年

终于理解了TCP的“三握手四挥手”过程,这篇文章写的太好了!

    有17位网友表示赞同!

心脏偷懒

这篇文章对“三握手四挥手”的解释很到位,而且图文并茂,易于理解。

    有17位网友表示赞同!

高冷低能儿

学习网络协议必看文章!对“三握手四挥手”的解释非常详细,值得收藏。

    有20位网友表示赞同!

稳妥

这篇文章讲解的“三握手四挥手”非常清晰,让我对TCP协议有了更深入的了解。

    有14位网友表示赞同!

闲肆

终于理解了“三握手四挥手”背后的原理,这篇文章真的帮了大忙!

    有17位网友表示赞同!

淡写薰衣草的香

文章对“三握手四挥手”的过程解释得很详细,图文并茂,易于理解,非常棒!

    有16位网友表示赞同!

念初

学习网络协议的最佳文章!对“三握手四挥手”的讲解非常清晰,值得推荐。

    有7位网友表示赞同!

回忆未来

以前对“三握手四挥手”一直很迷糊,看了这篇文章后,终于弄懂了,感谢作者的分享!

    有6位网友表示赞同!

猜你喜欢