TCP两次挥手,你见过吗?那四次握手呢?

      最后更新:2022-07-05 02:23:58 手机定位技术交流文章

      正如我们所知道的,TCP是一个面向连接、可靠、基于字节流的传输层通信协议。

      因此,这里提到的“面向连接”意味着您需要创建连接,使用连接,并释放连接。

      建立一个连接意味着摇动一个熟悉的TCP三次.

      连接是用来以一个发送和一个确认的形式传输数据的。

      释放连接,这是我们常见的四向TCP波。

      TCP波是四次的你应该知道更多,但你有没有三次或两次的波浪?

      你见过他们吗?那四个手?

      今天的话题是,我不想只是打猎,也不想做冷酷的知识。

      我们开始四次挥手获取一些实际知识。

      TCP四次挥手

      回顾一下TCP,然后四次摇摆。

      通常.一旦数据传输完成,客户或服务端可以启动四向波来释放连接。

      正如在图中所示,假设四个波是由客户端发起的,就是那个发起的。 服务器是客户端的波浪请求的被动接收器,称为被动侧面。

      客户端和服务器, 最初, 在 ESTABLISHED 状态.

      第一波:一般来说,启动器执行关闭()或关闭()方法,该方法发送一个“我不再发送数据”的 FIN消息。

      第二波:在接收发起者 FIN 声明后,被动quad 会用 ACK 响应,这意味着“我收到了你的 FIN,我知道你不再发送数据”。

      上面提到,发起者不再发送数据,但此时,被动方仍然有发送数据,所以继续发送。 注意,在第二和第三波之间,被动方能够向主动方发送数据,但不一定是主动方能正常接收数据。

      第三波:在被动知道第二波后,被动执行一系列关闭任务,最后调用 close(),在该点发出第三波的 FIN-ACK。

      第四个手势:积极的党派返回ACK,这意味着它已经收到。

      第一个波和第三波是我们在应用程序中主动触发的(例如 Call close() 方法),这是我们通常需要注意的代码。

      第二波和第四波是由内核协议堆栈自动完成的,所以当我们写代码时我们不会到达这个位置,所以我们不必担心太多。

      此外,无论是主动还是消极,每个方都发出 FIN和ACK。 同时,我们还收到了 FIN和ACK。

      FIN需要执行关闭()或关闭()才能发布?

      不一定。一般情况下,最后通过在接口上执行关闭()或关闭()方法发布。但实际上,只要应用程序退出,不管是主动退出,或者被动退出(因为某些未知原因已经被杀害),并会发出 FIN。

      FIN表示“我不再发送数据”,所以 shutdown() Shutdown read不发送 FIN给另一方, shutdown write不发送 FIN。

      如果 FIN-WAIT-2状态在机器上特别高,为什么

      根据上述四个波形图表,可以看到 FIN-WAIT-2是活动侧的另一边状态。

      这个状态的程序一直在等待Fin的第三波。 第三波需要被动在代码中执行close()。

      因此,如果机器上的 FIN-WAIT-2状态特别高,那么一般来说,另一台机器将会有大量的CLOSE_WAIT。

      因此,如果 FIN-WAIT-2状态在机器上特别高,这通常是因为端子不总是执行 close() 方法给出第三波。

      启动程序如何处理关闭后收到的数据

      在前面的一篇文章中,“代码执行成功发送时发送的数据是 吗? ”,从程序启动clo()时的源点来看;

      • 如果当前连接的相应接口的接收缓冲区包含数据,则会发出RST。

      • 如果缓冲区被发送数据,它等待到它被发送,然后发送第一个挥动 FIN。

      正如我们所知道的,TCP是完全双重通信,这意味着在发送数据的同时,它也可以接收数据。

      关闭()的含义是关闭发送和接收消息的功能。

      也就是说,虽然从理论上看,在第二和第三波之间,被动者可以将数据传递给主动者。

      但是如果第一四个波被关闭()触发的话,第一波不会收到消息。

      此外,我们还组织了一些C++后端开发面试问题、教学视频和后端学习路线图免费共享,如果您需要,您可以自行添加它们: Learn to communicate group click to join ~ group file share

      我们强烈推荐C++后端开发免费学习地址:C/C++Linux服务器开发高级架构师/C++后端开发架构师 icon-default.png?t=M5H6https://ke.qq.com/course/417774?flowToken=1013189

      数据不能在第二波和第三波之间传输吗?

      完全没有。 Close()的上述意义是关闭发送和接收消息的功能。

      因此,如果您只能关闭发送消息而不是关闭接收消息,那么您可以继续接收消息。

      在这种情况下,如何是切断的方法。

      • SHUT_RD:关闭阅读。此时,应用程序层不再尝试接收数据,并且接收缓冲器中接收的数据甚至在内核协议堆栈中都会被丢弃。

      • SHUT_WR: 关闭写字.如果发送缓冲区没有输出,数据将转移到目标主机。

      • SHUT_RDWR: 关闭读写. 关紧了.

      如何知道前端插座是否执行关闭或关闭

      不管主动的关闭调用是关闭()或关闭(),被动只接收一个 FIN。

      “我怎么知道另一个人不会让我继续发送数据?”

      事实上,你不必修理它,你只是必须。

      在第二波和第三波之间,如果被动关闭器想发送数据,则发送()方法在代码级别执行。

      send()将数据复制到机器上的 send缓冲区。 如果 send缓冲区没有问题,它可以被复制进去,所以通常 send() 会成功返回。

      ![tcp_sendmsg logic] (https://cdn.Jsdelivr.Net/gh/xiaobaiTech/image/tcp_sendmsg logic.(png)

      然后被动内核协议堆发送数据到主动关闭。

      • 最后的主动关闭称为关闭(socket_fd, SHUT_WR)。此时,主动关闭的党派不再发送消息,而是可以接收被动的党派的消息,一切都如往常,每个人都很高兴。

      • 最后一次激活关闭被调用是关闭()。 激活派对将直接接收被动派对的数据后丢弃数据,然后返回RTS。

      针对第二种情况。

      被动内核协议堆接收了RST并关闭了连接,但内核连接关闭,应用程序层不知道(除非通知)。

      被动层的下一个动作是读写.

      • 如果读完, 它返回了RST错误, 这是我们共同的联接重新设置的同行.

      • 如果写成,程序生成SIGPIPE信号,应用程序层代码可以捕捉和处理信号,如果没有处理,进程将默认终止,异常将退出。

      总而言之,当被动关闭返回EOF与 recv()时,第一个波由主动关闭()或关闭(fd, SHUT_WR)启动。

      如果被动端执行 send() 两次,此时。

      • 首先发送(), 通常会成功返回.

      • 第二次发送时间。如果第一波由关闭(fd, SHUT_WR)启动,然后发送()仍然成功。如果开创者第一次通过闭(),然后将生成一个SIGPIPE信号,进程默认会终止,异常退出。不想异常退出的话,记住要捕捉和处理这个信号。

      如果被动人没有第三次挥手,会发生什么呢?

      第三波是由被动的触发,例如接近()。

      如果有代码错误或其他原因,被动方不会执行第三波。

      在此情况下,启动者会使用 close() 或 shutdown(fd, SHUT_WR) 作为其第一个波浪,视行为而定。

      • 如果关闭(fd, SHUT_WR)被使用,它表明主动党只关闭了写字,而且还能读,并且仍然在FIN-WAIT-2中,被动党第三波,例如死亡。

      • 如果关闭(),解释 iniciator的阅读和写作是封闭的,一会儿是 FIN-WAIT-2,这次由 net.ipv4.tcp_fin_timeout控制,一般是 60s,这个值与2MSL完全相同。超过这段时间之后,国家不会成为“IME-WAIT”,相反,它直接关闭。

      TCP三次挥手

      四波之后, 有三波的可能性 吗?

      是可能的。

      我们知道TCP有四个哨戒,在第二个和第三个哨戒之间,可以进行数据传输。 第三波的目的是告诉积极的一方,"被动的一方没有数据发送。

      因此,在第一波之后,如果被动没有给主动的数据,那么第二波和第三波很可能被结合并传输。

      如果要发送数据,我们不该三次握手吗?

      上面提到,没有数据可以传输,如果在第二波和第三波之间有数据可以传输,那么不可能转换成三波吗?

      在TCP中还有一个叫做延迟确认的特性,它很容易理解接收者不需要在接收数据后立即返回ACK确认包。

      基于此,并非每个发送的数据包都应该收到ACK确认包,因为接收者可以合并确认。

      这个合并确认,放置了四次,可以发送第二波,第三波,和数据传输之间一起,方便。 因此,有三个波。

      ​TCP两次挥手

      如前四次握手所述,双方在闭幕时发出 FIN 和 ACK 。

      通常,TCP连接的两个端是不同的IP+端口的进程。

      但是如果TCP连接的两个端口,IP+端口,是相同的,那么关闭连接时,一个端口会发生同样的事情,发送 FIN,并接收ACK,正如两个端口是相同的插座。

      这些IP+端口的两个端口都以相同的方式连接,称为TCP自联。

      是的,你没弄错,我没弄错。 同样的插头确实可以连接起来形成连接。

      一个接口能建立连接 吗?

      正如上面提到的那样,同一客户端套接头本身就向自己发起连接请求,可以成功地建立连接。

      这是我们打算做的。

      注意,我在下面的系统中进行了一个实验,在Mac上几乎不可能恢复。

      使用nc命令很容易创建一个TCP自连

      上面的-p可以指定源端口号,即指定连接的66端口号的客户端:66。

      整个过程没有服务方面的参与。 你可以拿一个袋子,看看它。

      正如你所看到的,同样的插座,当你把自己捆绑在一起时,你握手三次。

      在上面的图中,两边都是相同的客户,并且它被划分为两部分,以便让每个人更容易理解移徙的状况。

      我们可以将自己连接的震动状态与正常TCP震动进行三次比较。

      看看自联状态图,然后看看以下问题。

      此外,我们还组织了一些C++后端开发面试问题、教学视频和后端学习路线图免费共享,如果您需要,您可以自行添加它们: Learn to communicate group click to join ~ group file share

      我们强烈推荐C++后端开发免费学习地址:C/C++Linux服务器开发高级架构师/C++后端开发架构师 icon-default.png?t=M5H6https://ke.qq.com/course/417774?flowToken=1013189

      如果从一个端接入SYN包后第一次握手后,TCP连接状态如何改变?

      第一次握手后,连接状态变为SYN_SENT状态。 如果此时收到第一个SYN包,连接状态将从SYN_SENT变为SYN_RCVD。

      如果SYN+ACK包在第二次握手后收到第二次握手,那么TCP连接状态如何改变?

      第二次握手后,连接状态被更改为SYN_RCVD,在第二次握手后将收到SYN+ACK包。

      在端部的第一个波和端部的第一个波之后,TCP连接状态如何变化?

      第一波之后,端态变为FIN-WAIT-1。 通常是等待ACK的第二波。

      就像隐藏情节一样。

      CLOSING是罕见的,通常发生在两个TCP结束同时关闭连接时,除非自连接关闭。

      处于闭合状态时,只要再拿一张卡片,你可以进入等待时间状态,然后等个2MSL,连接就彻底断开了。它有点不同于正常的四向波。你可以在文章的开头滑到TCP上,然后四次波动来比较。

      代码复现自连接

      你可能怀疑这并不是nc软件本身的错误。

      然后我们用绳子观察它在里面的动作。

      只需创建一个客户端插座手柄,然后执行该手柄的绑定,将其端口号绑定到66,然后启动连接方法到:66。

      我们可以用C语言复制它。

      下面的代码仅用于复制问题。 直接跳动并不影响阅读。

      保存为 client.c文件,然后执行下列命令,以成功地找到连接。

      说明这不是nc错误。 事实上,这也是内部允许的情况。

      自连接的解决方案

      自我联系并不常见,但遇到的并不难解决。

      解决方案相对简单,只要它确保客户端端口和服务端口不一致。

      事实上,当我们写代码时,我们通常不指定客户端的端口,系统会随机分配端口给客户端的某个范围。 这个范围可以用下面的命令来查询

      也就是说,只要我们的服务器端口不在32768-6099范围内,例如设置为88。

      另一个解决办法,基于Golang标准网络库的实现,是确定IP和端口在连接建立后是否相同,并在自连接发生时禁用重新测试。

      四次握手

      上述的TCP自联是连接自己的场景的客户端。

      答案是:是的,有一个情况,TCP是同时开的。

      相反,当它同时打开时,当握手时,TCP的状态会发生变化,与TCP的自我连接非常相似。

      例如,在SYN_SENT状态中,另一个SYN被接收,这实际上与在第一手发送后自动连接中的第一手请求相符。

      在SYN_RCVD状态中,接收到SYN+ACK,相当于自连接,然后接收到第二次握手请求,结果是ESTABLISHED。 他们的源代码实际上是相同的逻辑。

      复现TCP同时打开

      在两个控制面板下, 分别执行下列两个行命令.

      上述两个命令的含义也很简单:两个客户端要求彼此的端口号码连接,如果失败,再试一次。

      执行后你看到的现象是,在开始时,你会发疯地失败,然后再尝试。

      在检索过程中,得到了以下结果。

      正如你所看到的,它使用了四个相互作用来建立联系,因此,可以说这是通过四个握手建立的联系。

      更重要的是,它只涉及两个客户,没有服务端。

      看到这一点,我不知道你们是否像我一样,一种新的认知波,一种新的对接头的理解。

      在前面的概念中,连接必须有一个客户端和服务端,而服务端必须执行一个听()和一个接受()。

      因此,下次面试官问你“TCP可以不听就建立连接吗?”,我想我们应该知道该怎么回答。

      但是还有另一个问题:只有两个客户端没有听(),为什么我能设置一个TCP连接?

      如果你感兴趣的话, 我们会有机会再填满坑子.

      总结

      • 如果FI-WAIT-2状态在机器上特别高,这通常是因为端子不总是执行 close()方法来给出第三波。

      • 关闭()关闭同时发送和接收消息的能力。 shutdown()可以单独关闭发送或接收消息。

      • 第二波和第三波可以结合在一起,所以四个波变为三个波。

      • 如果相同的插座连接到自己,TCP自接会发生,并且自接的波浪是两次波浪。

      • 如果没有听力,两个客户端之间可以建立连接。 这种情况叫TCP同时打开,这是由四个握手生成的。

      参考资料

      建议举办一个免费的公共课程,以开发教育的零声C/C++后端,我个人认为老师讲得很好,分享给大家: C/C++后端开发者,内容包括Linux,Nginx,ZeroMQ,MySQL,Redis,fastdfs,MongoDB,ZK,流媒体,CDN,P2P,K8S,Docker,TCP/IP,协程,技术内容,如DPDK,立即学习

      TCP两次挥手,你见过那四个手吗?

      本文由 在线网速测试 整理编辑,转载请注明出处,原文链接:https://www.wangsu123.cn/news/29256.html

          热门文章

          文章分类