深入协议栈了解TCP的三次握手、四次挥手、CLOSE-WAIT、TIME-WAIT。

news2024/10/6 12:25:30

        TCP网络编程的代码网上很多,这里就不再赘述,简单用一个图展示一下tcp网络编程的流程:        

1、深入connect、listen、accept系统调用,进一步理解TCP的三次握手

        这三个函数都是系统调用,我们可以分为请求连接方和被动连接两部分,我们知道请求连接方并非都是client,为了方便,本文用client代表主动连接方,server代表被动连接方。   

  • connect()是client的请求连接函数;处理client端的三次握手
  • listen()是server用来监听client端有没有连接请求,本质上它是监测半连接队列和全连接队列中有没有信息,这两个队列中存放的是需要和server端进行连接的客户端信息,下文对这两个队列有解释。下图listen函数的解析中可以看到,第二个参数backlog表示等待连接队列的最大长度。

  • accept()是server端为了独立管理每一个client连接,为其请求分配fd的函数,此函数调用时其实三次握手已经完成了。它从全连接队列中取出第一个节点,并为其分配fd。详情见下图

1、三次握手发生在那个函数?

   

  • 三次握手具体流程:
    • client端调用connect系统调用,发起连接请求,并阻塞等待返回结果;
    • server端协议栈收到client端发来的syn请求报文后,将该client的tcb信息放入半连接队列,并回复client端syn+ack;
    • client端的connect系统调用回复server端ack;
    • server端收到client端发来的确认ack后,从半连接队列中找到此client对应的tcb,修改其连接状态,并放入全连接队列中,此时协议栈层面的三次握手完成。

        因此对于client而言,三次握手发生在connect函数中;对于server而言,三次握手是由协议栈实现,不发生在任一网络编程函数中

2、listen(fd, backlog)中,第二个参数backlog是什么意思?

        经过对协议栈的分析,它首先创建一个半连接队列,存储发送了syn请求报文的client的信息,然后创建了一个全连接队列,存储回复了ack报文的client的信息(这个信息是从半连接队列中迁移来的),此时协议栈层面的三次握手已经完成;

        对于server来说,所有的client连接都会进行业务交互,但是这两个队列中的client连接都还未交由server的用户态管理,因此它们还都属于待连接状态,所以等待连接队列=半连接队列+全连接队列

       根据上述listen的函数解析和协议栈原理分析得知,backlog是等待连接队列的最大长度,即=半连接队列+全连接队列的最大长度和

3、accept函数的作用是什么?accept是如何分配fd的?

  1. 由上述函数解析和三次握手分析得,accept的作用为:
    1. 从全连接队列中取出第一个节点信息(tcb);
    2. 根据tcb信息为其重新分配一个sockfd。
  2. accept如何分配的fd:根据取出的tcb中的ip、port等信息,创建一个新的sockfd接收这个连接,交由server管理(多路io复用epoll)。

4、什么是半连接队列与全连接队列?

        半连接队列:由协议栈创建并管理,存放只发送来了syn请求报文的client的tcb信息

        全连接队列:由协议栈创建并管理,存放已经回复了ack确认报文的client的tcb信息。

2、深入TCP的四次挥手原理,进一步理解time_wait/close_wait状态

 

         我们要明确一点,close()关闭的只是sockfd(文件句柄,五元组),那tcp连接怎么断开呢?从accept函数我们可以知道,server为每一个连接tcb都分配了一个与之对应的sockfd,当server关闭了这个sockfd之后,与之对应的tcb也被删除,若server没有调用close()关闭sockfd,则这个连接就一直存在,除非等到系统超时或出现网络异常

        RFC 793 - Transmission Control Protocol

1、什么是四次挥手?为什么这样做?

  • 四次挥手过程:主动断开放用client表示,被动断开方用server表示
    • client调用close()函数,向server发送fin请求报文,client进入fin_wait_1状态;
    • server的协议栈收到fin后立即回应client一个ack报文,server进入close_wait状态;
    • server应用层得知recv() == 0时,及时调用close() 函数向client发送fin报文,server进入last_ack状态;
    • client收到fin报文后,立即回应server一个ack报文,client进入time_wait状态。
  • 四次挥手的原因:
    • server连接关闭的控制权在应用层,即调用close()后关闭,立即回复ack是协议栈的操作,所以两者不能做到同步。

2、什么是close_wait状态?产生大量close_wait的原因是什么?如何解决?

  • close_wait是server端的状态,表示等待来自本地用户的连接终止请求,从server的协议栈回复ack后到用户层调用close()关闭连接之前这段时间称为close_wait状态
  • 大量close_wait原因:收到client的断开请求报文(判断recv()== 0)后,没有调用或没有及时调用close()关闭连接。
  • 解决:收到client的断开请求报文(判断recv()== 0)后立即调用close(),在这之间不要出现多余的业务处理,如果无法避免就将业务抛给其他线程进行处理。

3、什么是time_wait状态?产生大量time_wait的原因是什么?如何解决?

  • time_wait是client端的状态,表示等待足够的时间,以确保远程tcp接收到对其连接终止请求的确认。client给server回复ack报文后,就进入到time_wait状态
  • 大量time_wait的原因:一般只有服务器或中间服务层才会出现大量对外链接,因此服务端主动发起大量短链接关闭,导致服务端存在大量的time_wait状态(比如HTTP)。
    •  HTTP默认的Connection值为close,那么就意味着关闭请求的一方几乎都会是由服务端这边发起的。那么这个服务端产生TIME_WAIT过多的情况就很正常了。

    • 虽然HTTP默认Connection值为close,但是,现在的浏览器发送请求的时候一般都会设置Connection为keep-alive了。所以,也有人说,现在没有必要通过调整参数来使TIME_WAIT降低了。 

  • 解决:
    • 1、规避大量短链接的使用,
    • 2、修改/etc/sysctl.conf文件,让服务器能够快速回收和重用那些time_wait的资源。

4、close_wait/time_wait的时长各自是多少?有什么作用?

  • 时长:
    • close_wait:如果没有调用close()至少存在两个小时,直到系统崩溃。如果没有及时调用close(),那就得看具体的业务处理时长。

    • time_wait:2MSL,RFC 793中规定MSL为2分钟,实际应用中常用的是30秒,1分钟和2分钟等。

      • 将TCP TIME-WAIT超时时间修改为小于60秒与TCP/IP协议quiet time概念相违背,可能导致您的系统将旧数据当做新数据接收,或者复制的新数据当做旧数据拒绝。因此请在网络专家建议下调整。

      • 你可以通过运行netstat -ant | grep TIME_WAIT | wc -l命令判断服务器中是否存在大量短连接,然后再确定要不要修改。

      • 修改 TIME-WAIT时间的方法有两种:

      • echo 5 > /proc/sys/net/ipv4/tcp_tw_timeout
      • sysctl -w "net.ipv4.tcp_tw_timeout=5"
  • 作用:      
    • close_wait:等待来自本地用户的连接终止请求。

    • time_wait:等待足够的时间,以确保远程tcp接收到对其连接终止请求的确认。

5、出现大量close_wait/time_wait的危害是什么?

        close_wait:1、如果因为没有调用close()导致存在大量close_wait,那将会消耗系统资源,导致系统崩溃;2、如果因为没有及时调用close(),则危害和time_wait一样。

        time_wait:占用的端口不能及时释放被使用,要等到2MSL时间后才能使用,则没有足够的sockfd分配,将大大降低并发量。

        所以它们有一个共同的危害就是“占着茅坑不拉屎”,资源得不到充分利用。

本文说提到的client和server不是表面上的客户端与服务器,client是主动请求方;server是被动响应方。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/974247.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

文案生成器-文章生成器

你是否曾经面对过频繁写作文案的问题?是不是觉得文案的撰写过程既繁琐又耗时?那么今天我要向你介绍一项令人兴奋的技术——文案自动生成。是的,现在我们可以借助人工智能技术,自动生成高质量的文案,为你在营销和推广方…

C++笔记基础全部完整版

01 面向对象 基本概念 面向对象程序设计(Object-Oriented Programming,OOP)是一种新的程序设计范型。程序设计范型是指设计程序的规范、模型和风格,它是一类程序设计语言的基础。 面向过程 面向过程程序设计范型是使用较广泛的…

【AIGC专题】Stable Diffusion 从入门到企业级实战0401

一、概述 本章是《Stable Diffusion 从入门到企业级实战》系列的第四部分能力进阶篇《Stable Diffusion ControlNet v1.1 图像精准控制》第01节, 利用Stable Diffusion ControlNet Inpaint模型精准控制图像生成。本部分内容,位于整个Stable Diffusion生…

遥感指数数据库

目前遥感指数多种多样,那怎么针对不同的应用领域选择合适的植被指数?不同卫星又有哪些可以反演的指数? Henrich等人开发了Index Database(网址:https://www.indexdatabase.de/),总结了目前主流的遥感指数,…

EMERSON 1X00781H01L电源模块

应用领域: EMERSON 1X00781H01L 电源模块广泛用于工业自动化、电力系统、通信设备、机器人技术和其他领域,以确保设备和系统的正常运行。 电源输出: 该电源模块通常提供不同的电压和电流输出选项,以满足不同设备和系统的电源需求…

Python(Web时代)—— Django管理工具

介绍 前言 通过模型我们可以进行数据库的操作,如果我们想要对数据表中的数据进行操作还需要单独的开发接口,颇有不方便,今天我们来通过Django提供的管理工具来编辑模型数据。 Django 为我们提供了强大的工具,可以全自动地根据模…

go语言--堆栈

根据隔离适应策略,使用内存时的最小单位为mspan 每个mspan为N个相同大小的“格子 Go中一共有67种mspan

算法:图解递归算法的应用场景和使用途径

文章目录 什么是递归?使用递归的原因?如何理解递归?递归的使用写法典型例题和分析汉诺塔问题合并两个有序链表反转链表两两交换链表中的节点pow 总结 什么是递归? 递归就是函数自己调用自己的情况,在二叉树&#xff0…

Spring Bean 别名处理原理分析

今天来和小伙伴们聊一聊 Spring 中关于 Bean 别名的处理逻辑。 1. Alias 别名,顾名思义就是给一个 Bean 去两个甚至多个名字。整体上来说,在 Spring 中,有两种不同的别名定义方式: 定义 Bean 的 name 属性,name 属性…

[machine learning]神经网路初步 basic neural network

这一篇写的很差....我会找时间慢慢补充的 1.神经网络是什么 在上一篇关于逻辑回归的博客中,简单介绍了逻辑回归模型,对于监督学习来说,模型可以理解为一个模块/函数,在足够的数据训练以后,通过梯度下降等手段进行拟合,最终根据输入来预测输出结果. 这一个东西,我们可以称之为…

修改了字符集,好多软件不能正常使用,所以,慎重。。。。

这里,默认是没有选中的。所以,你千万不要随便就选中了。(terminal里乱码的问题,可以通过命令: chcp 65001 解决)。如果你执意选中了这里,重启之后,至少4个软件异常: 1、…

华为OD机试 - TLV解析Ⅰ(Java 2023 B卷 100分)

目录 专栏导读一、题目描述二、输入描述三、输出描述四、Java算法源码五、效果展示1、输入2、输出3、说明 华为OD机试 2023B卷题库疯狂收录中,刷题点这里 专栏导读 本专栏收录于《华为OD机试(JAVA)真题(A卷B卷)》。 …

集成图片验证码Kaptcha-完成登录验证功能

下面展示的是用SpringBoot集成Kaptcha&#xff0c;当然用其他框架也是一样的。 导入Kaptcha 导入pom.xml&#xff0c;下面得到二选一&#xff0c;建议用github的&#xff0c;比google的快一点 <dependency><groupId>com.github.penggle</groupId><arti…

2024腾讯校招后端面试真题汇总及其解答(三)

21【算法题】反转链表 题目: 给定单链表的头节点 head ,请反转链表,并返回反转后的链表的头节点。 示例 1: 输入:head = [1,2,3,4,5] 输出:[5,4,3,2,1]示例 2: 输入:head = [1,2] 输出:[2,1]示例 3: 输入:head = [] 输出:[]提示: 链表中节点的数目范围是 [0, 5…

Chrome 和 Edge 上出现“status_breakpoint”错误解决办法

文章目录 STATUS_BREAKPOINTSTATUS_BREAKPOINT报错解决办法Chrome浏览器 Status_breakpoint 错误修复- 将 Chrome 浏览器更新到最新版本- 卸载不再使用的扩展程序和应用程序- 安装计算机上可用的任何更新&#xff0c;尤其是 Windows 10- 重启你的电脑。 Edge浏览器 Status_brea…

基于 Flink CDC 构建 MySQL 和 Postgres 的 Streaming ETL

官方网址&#xff1a;https://ververica.github.io/flink-cdc-connectors/release-2.3/content/%E5%BF%AB%E9%80%9F%E4%B8%8A%E6%89%8B/mysql-postgres-tutorial-zh.html官方教程有些坑&#xff0c;经过自己实测&#xff0c;记录个笔记。 服务器环境&#xff1a; VM虚拟机&am…

HarmonyOS 实现表单页面的输入,必填校验和提交

一. 样例介绍 本篇 Codelab 基于 input 组件、label 组件和 dialog 组件&#xff0c;实现表单页面的输入、必填校验和提交&#xff1a; 1. 为 input 组件设置不同类型&#xff08;如&#xff1a;text&#xff0c;email&#xff0c;date 等&#xff09;&#xff0c;完成表单页…

Burp插件HaE与Authz用法

HaE与Authz均为BurpSuite插件生态的一员&#xff0c;两者搭配可以避免“越权”、“未授权”两类漏洞的重复测试行为。&#xff08;适用于业务繁杂&#xff0c;系统模块功能多的场景&#xff09; 两个插件都可以在store里安装 安装完后&#xff0c;点击Filter Settings勾选Sho…

DSP_TMS320F28377D_算法加速方法4_C语言编程优化

前面3篇的优化思路是从硬件本身和函数库这些方向去加速&#xff0c; 本文则仅从代码本身的效率去考虑加速的方法。 1、用全局变量比用局部变量快 void testfunction1(){ // 局部变量int i;double s,a,b;a 1.023;b 12.23;for(i 0; i < 1000; i){s __divf32(a,b);} }int …