Qt --- 信号与槽

article/2025/10/1 15:35:53

信号与槽概述

信号与槽是 Qt 框架引以为豪的机制之一。所谓信号与槽,实际就是观察者模式(发布-订阅模式)。当某个事件发生之后,比如,按钮检测到自己被点击了一下,它就会发出一个信号(signal)。这种发出是没有目的的,类似广播。如果有对象对这个信号感兴趣,它就会使用连接(connect)函数,意思是,将想要处理的信号和自己的一个函数(称为槽(slot))绑定来处理这个信号。也就是说,当信号发出时,被连接的槽函数会自动被回调。这就类似观察者模式:当发生了感兴趣的事件,某一个操作就会被自动触发。

信号的本质

信号是由于用户对窗口或控件进行了某些操作,导致窗口或控件产生了某个特定事件,这时候Qt对应的窗口类会发出某个信号,以此对用户的挑选做出反应。

因此根据上述的描述我们得到一个结论:信号的本质就是事件,比如:

  • 按钮单击、双击

  • 窗口刷新

  • 鼠标移动、鼠标按下、鼠标释放

  • 键盘输入

那么在Qt中信号是通过什么形式呈现给使用者的呢?

  • 我们对哪个窗口进行操作, 哪个窗口就可以捕捉到这些被触发的事件。

  • 对于使用者来说触发了一个事件我们就可以得到Qt框架给我们发出的某个特定信号。

  • 信号的呈现形式就是函数, 也就是说某个事件产生了, Qt框架就会调用某个对应的信号函数, 通知使用者。

在QT中信号的发出者是某个实例化的类对象,对象内部可以进行相关事件的检测。

槽的本质

槽(Slot)就是对信号响应的函数。槽就是一个函数,与一般的C++函数是一样的,可以定义在类的任何部分(public、private或 protected),可以具有任何参数,可以被重载,也可以被直接调用(但是不能有默认参数)。槽函数与一般的函数不同的是:槽函数可以与一个信号关联,当信号被发射时,关联的槽函数被自动执行。

举个简单的例子:

女朋友说:"我肚子饿了!",于是我带她去吃饭。

上边例子中相当于女朋友发出了一个信号, 我收到了信号并其将其处理掉了。

  • 女朋友 -> 发送信号的对象, 信号内容:我饿了

  • 我 ->槽:收信号的对象并且处理掉了这个信号, 处理动作: 带她去吃饭

在Qt中槽函数的所有者也是某个类的实例对象。

写信:发件人 信的内容 收件人 收到信做事情 - - ->通过邮局把他们联系到一起

信号和槽的关系

在Qt中信号和槽函数都是独立的个体,本身没有任何联系,但是由于某种特性需求我们可以将二者连接到一起,好比牛郎和织女想要相会必须要有喜鹊为他们搭桥一样。

信号与槽关联是用 QObject::connect() 函数实现的,其基本格式是:

[static] QMetaObject::Connection  QObject::connect(const QObject *sender, 						    		const char *signal, 								const QObject *receiver, 							const char *method, 								Qt::ConnectionType type = Qt::AutoConnection);	静态成员 
发送者
信号的内容
接收者
方法
  • 参数:

    • sender:发出信号的对象

    • signal:信的内容,sender对象的信号,信号是一个函数

    • receiver:信号接收者

    • method:receiver对象的槽函数, 当检测到sender发出了signal信号, receiver对象调用method方法

connect函数相对于做了信号处理动作的注册,(建立关联)调用conenct连接信号与槽时,sender对象的信号并没有产生, 因此receiver对象的method也不会被调用,method槽函数本质是一个回调函数, 调用的时机是信号产生之后。 调用槽函数是Qt框架来执行的,connect中的sender和recever两个指针必须被实例化了, 否则conenct不会成功

标准信号与槽的使用

标准信号/槽

在Qt提供的很多类中都可以对用户触发的某些特定事件进行检测, 当事件被触发后就会产生对应的信号, 这些信号都是Qt类内部自带的, 因此称之为标准信号。

同样的,在Qt的很多类内部为我了提供了很多功能函数,并且这些函数也可以作为触发的信号的处理动作,有这类特性的函数在Qt中称之为标准槽函数。

系统自带的信号和槽通常如何查找,这个就需要利用帮助文档了,在帮助文档中比如我们上面的按钮的点击信号,在帮助文档中输入QPushButton,首先我们可以在Contents中寻找关键字 signals,但是我们发现并没有找到,这时候我们应该看当前类从父类继承下来了哪些信号,因此我们去他的父类QAbstractButton中就可以找到该关键字,点击signals索引到系统自带的信号有如下几个

clicked:鼠标点击按钮一次,信号就会被触发

pressed:鼠标的左键 | 右键按下,信号就会被触发

released:按钮被释放,信号就会被触发

 widget.cpp

#include "widget.h"
#include<QPushButton>
Widget::Widget(QWidget *parent): QWidget(parent)
{//构造函数//信号与槽//标准信号与槽:Qt类提供的,我们直接可以使用//connect(信号发送者,发送的内容|具体的信号,信号接收者,对应的处理动作)//先来一个按钮QPushButton *btn = new QPushButton;btn->setText("maye");//显示按钮btn->show();    //连接信号与槽connect(btn,&QPushButton::clicked,this,&Widget::close);//点击按钮按钮发送信号 类的成员函数指针:鼠标点击按钮时触发的信号//接收者:表示当前的Widget类用this指针标识 公有槽:关闭当前窗口
}//点击按钮后窗口关闭--->1.按钮发送clicked信号2.窗口对信号进行处理<->窗口关闭
Widget::~Widget()
{
}

使用

功能实现: 点击窗口上的按钮, 关闭窗口

  • 按钮: 信号发出者 -> QPushButton

  • 窗口: 信号的接收者和处理者 -> QWidget

// 单击按钮发出的信号
[signal] void QAbstractButton::clicked(bool checked = false)
// 关闭窗口的槽函数
[slot] bool QWidget::close();// 单击按钮关闭窗口
connect(ui->closewindow, &QPushButton::clicked, this, &MainWindow::close);

自定义信号槽使用

Qt框架提供的信号槽在某些特定场景下是无法满足我们的项目需求的,因此我们还设计自己需要的的信号和槽,同样还是使用connect()对自定义的信号槽进行连接。

如果想要使用自定义的信号和槽,首先要编写新的类并且让其继承 Qt 的某些标准类,我们自己编写的类想要在Qt中使用使用信号槽机制,那么必须要满足的如下条件:

  • 这个类必须从 QObject 类或者是其子类进行派生

  • 在定义类的第一行头文件中加入 Q_OBJECT 宏

// 在头文件派生类的时候,首先像下面那样引入Q_OBJECT宏:
class MyMainWindow : public QWidget
{Q_OBJECT
public:......
}

自定义信号与槽的简单了解

 signalAndslot.pro

QT += gui core widgetsCONFIG +=C++17HEADERS += \mywindow.hSOURCES += \main.cpp \mywindow.cpp

 mywindow.h

#ifndef MYWINDOW_H
#define MYWINDOW_H#include<QPushButton>class MyButton : public QPushButton  //1.必须间接或直接继承QObject QPushButton继承于QObject
{Q_OBJECT                         //2.必须包含Q_OBJECT宏
public:MyButton();
signals:                             //信号必须写在signals关键字下面,信号是函数的声明,不需要实现void testSignal();
public slots:                        //自定义槽函数:在访问权限词后面加slots代表槽函数void print();
};#endif // MYWINDOW_H

 mywindow.cpp

#include "mywindow.h"
#include<QDebug>
MyButton::MyButton()
{//连接按钮的信号//信号不仅可以连接槽函数,还可以连接信号 1.自己被点击发出信号2.自己接收3.再发出自己信号4.信号被外部捕获|处理connect(this,&MyButton::clicked,this,&MyButton::testSignal);//connect(信号发送者,发送的内容|具体的信号,信号接收者,对应的处理动作)//连接自己的信号--->1.自己发出信号2.自己接收信号3.自己关闭窗口connect(this,&MyButton::testSignal,this,&MyButton::close);//点击一次按钮打印一次printconnect(this,&MyButton::testSignal,this,&MyButton::print);}void MyButton::print()
{qDebug()<<"print";
}

 main.cpp

#include<QApplication>
#include"mywindow.h"
int main(int argc,char*argv[])
{QApplication a(argc,argv);MyButton w;      //创建按钮w.show();        //显示按钮 调用不了:没有继承任何类return a.exec();
}

自定义信号

  • 信号是类的成员函数

  • 返回值是 void 类型

  • 参数可以随意指定,信号也支持重载

  • 信号需要使用 signals 关键字进行声明, 使用方法类似于 public 等关键字

  • 信号函数只需要声明,不需要定义(没有函数体)

  • 在程序中发送自定义信号:发送信号的本质就是调用信号函数

emit mysignals();	//发送信号

 emit 是一个空宏,没有特殊含义,仅用来表示这个语句是发射一个信号,不写当然可以,但是不推荐。

// 举例: 信号重载
// Qt中的类想要使用信号槽机制必须要从QObject类派生(直接或间接派生都可以)
class MyButton : public QPushButton
{Q_OBJECT
signals:void testsignal();void testsignal(int a);
};
//qRegisterMetaType

信号参数的作用是数据传递, 谁调用信号函数谁就指定实参,实参最终会被传递给槽函数

自定义槽

槽函数就是信号的处理动作,自定义槽函数和自定义的普通函数写法是一样的。

特点

  • 返回值是 void 类型

  • 槽函数也支持重载

    • 槽函数参数个数, 需要看连接的信号的参数个数

    • 槽函数的参数是用来接收信号发送的数据的,信号的参数就是需要发送的数据

    • 举例

      • 信号函数:void testsig(int a,double b);

      • 槽函数:void testslot(int a,double b);

    • 总结

      • 槽函数的参数应该和对应的信号的参数个数, 类型一一对应

      • 信号的参数可以大于等于槽函数的参数个数,未被槽函数接受的数据会被忽略

        • 信号函数:void testsig(int a, double b);

        • 槽函数:void testslot(int a);

槽函数的类型

  • 成员函数

    • 普通成员函数

    • 静态成员函数

  • 全局函数

  • lambda表达式(匿名函数)

  1. 槽函数可以使用关键字进行声明: slots (Qt5中slots可以省略不写)

    • public slots:

    • private slots:

    • protected slots:

 场景举例

// 女朋友饿了, 我请她吃饭
// class GirlFriend
// class OneSelf
class GirlFriend:public QObject
{Q_OBJECT
public:GirlFriend(QObject*parent = nullptr):QObject(parent){}
signals:void hungry();
public slots:
};class OneSelf:public QObject
{Q_OBJECT
public:OneSelf(QObject*parent = nullptr):QObject(parent){}void goEat(){qDebug()<<"goEat";}static void goEatFood(){qDebug()<<"goEatFood";}
signals:
public slots:void onHungry(){qDebug()<<"宝贝饿了呀,多喝热水哟~";}
};class Widget : public QWidget
{Q_OBJECTpublic:Widget(QWidget *parent = nullptr);~Widget();
public slots:void onBtnClicked();
private:GirlFriend *girl;OneSelf* self;
};

 widget.cpp

#include "widget.h"
#include<QPushButton>Widget::Widget(QWidget *parent): QWidget(parent)
{girl = new GirlFriend(this);self = new OneSelf(this);//连接槽函数connect(girl,&GirlFriend::hungry,self,&OneSelf::onHungry);//连接普通成员函数connect(girl,&GirlFriend::hungry,self,&OneSelf::goEat);//连接静态成员函数connect(girl,&GirlFriend::hungry,self,&OneSelf::goEatFood);QPushButton*btn = new QPushButton("按下就饿了",this);//通过widget间接发送girl的hungry信号    connect(btn,&QPushButton::clicked,this,&Widget::onBtnClicked);//连接信号,直接发送girl的hungry信号   //connect(btn,&QPushButton::clicked,girl,&GirlFriend::hungry);    }Widget::~Widget()
{
}void Widget::onBtnClicked()
{emit girl->hungry();
}

信号槽拓展

信号槽使用拓展

  • 一个信号可以连接多个槽函数, 发送一个信号有多个处理动作

    • 需要写多个connect连接

    • 信号的接收者可以是一个对象, 也可以是多个对象

  • 一个槽函数可以连接多个信号, 多个不同的信号, 处理动作是相同的

    • 写多个connect就可以

  • 信号可以连接信号

    • 信号接收者可以不出来接收的信号, 继续发出新的信号 -> 传递了数据, 并没有进行处理

QPushButton*btn = new QPushButton("one",this);
QPushButton*btn2 = new QPushButton("two",this);
btn2->move(100,0);
//点击btn按钮,会让btn2按钮发出clicked信号
connect(btn,&QPushButton::clicked,btn2,&QPushButton::clicked);connect(btn2,&QPushButton::clicked,this,&Widget::onClicked);
void Widget::onClicked()
{qDebug()<<"okok";
}
  • 信号槽是可以断开的
disconnect(const QObject *sender, &QObject::signal, const QObject *receiver, &QObject::method);

信号槽的连接方式

Qt5的连接方式

// 语法:
QMetaObject::Connection QObject::connect(const QObject *sender, PointerToMemberFunction signal, const QObject *receiver, PointerToMemberFunction method, Qt::ConnectionType type = Qt::AutoConnection);// 信号和槽函数也就是第2,4个参数传递的是地址, 编译器在编译过程中会对数据的正确性进行检测
connect(const QObject *sender, &QObject::signal, const QObject *receiver, &QObject::method);

Qt4的连接方式

这种旧的信号槽连接方式在Qt5中是支持的, 但是不推荐使用, 因为这种方式在进行信号槽连接的时候, 信号槽函数通过宏SIGNALSLOT转换为字符串类型。

因为信号槽函数的转换是通过宏来进行转换的,因此传递到宏函数内部的数据不会被进行检测, 如果使用者传错了数据,编译器也不会报错,但实际上信号槽的连接已经不对了,只有在程序运行起来之后才能发现问题,而且问题不容易被定位。

// Qt4的信号槽连接方式
[static] QMetaObject::Connection QObject::connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type = Qt::AutoConnection);connect(const QObject *sender,SIGNAL(信号函数名(参数1, 参数2, ...)),const QObject *receiver,SLOT(槽函数名(参数1, 参数2, ...)));

 应用举例

class Me : public QObject
{Q_OBJECT
// Qt4中的槽函数必须这样声明, qt5中的关键字 slots 可以被省略
public slots:void eat();void eat(QString somthing);
signals:void hungury();void hungury(QString somthing);
};

基于上面写的信号与槽,我们来处理如下逻辑: 我饿了, 我要吃东西

  • 分析: 信号的发出者是我自己, 信号的接收者也是我自己

Me m;
// Qt4处理方式  注意不要把信号与槽的名字写错了,因为是转为字符串写错了不会报错,但是连接会失败
connect(&m, SIGNAL(eat()), &m, SLOT(hungury()));
connect(&m, SIGNAL(eat(QString)), &m, SLOT(hungury(QString)));// Qt5处理方式
connect(&m, &Me::eat, &m, &Me::hungury);	// error:no matching member function for call to 'connect'
  • 为什么Qt4的方式没有错误,Qt5的方式却有问题了呢?

    • Qt4的方式在传信号和槽的时候用了宏进行强转,而且都带了参数,不会有二义性问题产生

    • Qt5中,信号和槽都有重载,此事connect函数根本就不知道你要使用的是重载中的哪一个,所以只能报错咯!

  • 如何解决Qt5中的信号和槽重载中的二义性问题呢?

    • 一、通过函数指针解决

//信号
void (Me::*funchungury)() = &Me::hungury;
void (Me::*funchungury_QString)(QString) = &Me::hungury;
//槽
void (Me::*funceat)() = &Me::eat;
void (Me::*funceat_QString)(QString) = &Me::eat;
//有参连接
connect(me,funchungury_QString,me,funceat_QString);
//无参连接
connect(me,funchungury,me,funceat);
  • 二、通过Qt提供的重载类(QOverload)解决
//有参连接
connect(this,QOverload<QString>::of(&MyButton::hungury),this,QOverload<QString>::of(&MyButton::eat));
//无参连接
connect(this,QOverload<>::of(&MyButton::hungury),this,QOverload<>::of(&MyButton::eat));
  • 总结
  • Qt4的信号槽连接方式因为使用了宏函数, 宏函数对用户传递的信号槽不会做错误检测, 容易出bug

  • Qt5的信号槽连接方式, 传递的是信号槽函数的地址, 编译器会做错误检测, 减少了bug的产生

  • 当信号槽函数被重载之后, Qt4的信号槽连接方式不受影响

  • 当信号槽函数被重载之后, Qt5中需要给被重载的信号或者槽定义函数指针

自定义信号与槽使用案例

 girlfriend.h

#ifndef GIRLFRIEND_H
#define GIRLFRIEND_H#include<QObject>               //直接从Object类中继承
class GirlFriend  : public QObject
{Q_OBJECT
public:GirlFriend();
signals:void hungry();               //饿了信号void hungry(const QString);  //信号与槽的重载->可以存在多个名字相同的信号与槽函数 & 参数不同
};#endif // GIRLFRIEND_H

 widget.h

#ifndef WIDGET_H
#define WIDGET_H#include <QWidget>
#include "girlfriend.h"
class Widget : public QWidget
{Q_OBJECTpublic:Widget(QWidget *parent = nullptr);~Widget();
public slots:void onBtnClicked();                //自定义槽函数--->响应什么控件的什么信号void onHungry();    void onHungry(const QString str);   //自定义槽函数重载
private:                                //一般情况下为私有属性GirlFriend girl;                    //栈区变量
};
#endif // WIDGET_H

 girlfriend.cpp

#include "girlfriend.h"GirlFriend::GirlFriend()
{}

 main.cpp

#include "widget.h"#include <QApplication>int main(int argc, char *argv[])
{QApplication a(argc, argv);Widget w;w.show();return a.exec();
}

 widget.cpp

#include "widget.h"
#include<QPushButton>
#include<QDebug>
Widget::Widget(QWidget *parent): QWidget(parent)
{QPushButton *btn = new QPushButton(this);       //创建专门用来触发饿了信号的按钮--->this:显示在窗口左上角的位置btn->setText("我饿了");connect(btn,&QPushButton::clicked,this,&Widget::onBtnClicked);//如果信号有重载,那么再连接的时候会产生二义性的问题--->不知道连接的是哪个信号|需要告诉它是有参版本还是无参版本的
//  connect(&girl,&GirlFriend::hungry,this,&Widget::onHungry);//1.类的成员函数指针--->类名限定 参数写在前面 // void GirlFriend::hungry()void (GirlFriend::*h)() = &GirlFriend::hungry;                  //定义了指向无参信号的指针
//  connect(&girl,h,this,&Widget::onHungry);void (GirlFriend::*hh)(const QString) = &GirlFriend::hungry;    //定义了指向有参信号的指针
//  connect(&girl,hh,this,&Widget::onHungry);//槽函数重载导致出现二义性--->Qt提供了一个函数专门用来处理重载问题//2.使用QOverload--->告诉它使用哪个hungry|onHungryconnect(&girl,QOverload<>::of(&GirlFriend::hungry),this,QOverload<>::of(&Widget::onHungry));connect(&girl,QOverload<QString>::of(&GirlFriend::hungry),this,QOverload<QString>::of(&Widget::onHungry));//3.使用Qt4的方法,过时了,不推荐,为什么?//这两个宏实际上是把信号或槽函数转成了字符串,字符串不能一眼看出错误--->字符串不会进行检查
//  connect(&girl,SIGNAL(hungry()),this,SLOT(onHungry()));
//  connect(&girl,SIGNAL(hungry(const QString)),this,SLOT(onHungry(const QString)));connect(&girl,QOverload<QString>::of(&GirlFriend::hungry),this,QOverload<QString>::of(&Widget::onHungry));//信号与槽:/*1.一个信号可以和多个槽建立关联*2.信号也可以关联信号->转发*3.信号是函数的申明,而且返回值只能是void,信号的实现由Qt来实现*4.信号和槽都可以重载,但是在连接的时候,需要注意二义性问题(三种方法解决:函数指针、QOverload、Qt4方式)*5.5.1信号的参数一般和槽的参数一一对应*  5.2 槽的参数可以比信号的参数少(可以忽略信号的参数)*  5.3 槽的参数不能比信号的多(槽需要的参数信号没有,函数是需要传参的)*  5.4 槽是不能有默认参数的**///lambda表达式做槽函数QPushButton *btn1 = new QPushButton(this);btn1->setText("我是按钮");btn1->move(200,0);//可以使用=,this捕获,但是最好不要使用&引用捕获connect(btn1,&QPushButton::pressed,this,[=](){btn1->setText("你点了我");//this->move(100,100);//this->close();});
}Widget::~Widget()
{}void Widget::onBtnClicked()
{qDebug()<<"宝,我饿了";//触发女朋友饿了信号,发送信号实际上就是调用信号函数emit girl.hungry();                //1.先打印 2.发送信号--->空宏:标识是用来发送信号emit girl.hungry("我要吃汉堡包");   //调用重载版本应该如何接收信号?
}void Widget::onHungry()
{qDebug()<<"好的,带你去吃饭";
}void Widget::onHungry(const QString str)
{qDebug()<<"好的,带你去吃汉堡";
}


http://chatgpt.dhexx.cn/article/rbpsKGvD.shtml

相关文章

Qt中的信号和槽详解

一、背景介绍 信号和槽用于两个对象之间的通信。信号和槽机制是Qt的核心特征&#xff0c;也是Qt不同于其他开发框架的最突出特征。在GUI编程中&#xff0c;当改变了一个部件时&#xff0c;总希望其他部件也能了解到该变化。更一般来说&#xff0c;我们希望任何对象都可以和其他…

QT笔记(一)

学习目标&#xff1a; 总结学习的QT 学习内容&#xff1a; 1、 QT的一些固定格式 2、 控件和事件 3、 信号和槽 记录内容&#xff1a; 1、 QT的固定格式 (1) 引用头文件 自己创建的头文件用" "括起&#xff0c;eg: #include "mainwindow.h"QT提供的头文…

QT中信号和槽详解

一、QT中信号和槽的机制 1、贴图来理解信号和槽的关系 2、解释 &#xff08;1&#xff09;信号和槽是用于QT对象之间的通信&#xff0c;信号可以有某种动作触发&#xff0c;也可以直接由代码触发。 &#xff08;2&#xff09;槽也叫操函数&#xff0c;当完成了信号和槽的连接…

Qt核心特性之 —— 「信号(Signal)与槽(Slot)」机制

目录 1、Qt 与 Qt Creator简介&#xff1a; 2、关于引用头文件的一些事儿&#xff1a; 3、信号(Signal)与槽(Slot)机制&#xff1a; 3.1、一个小例子&#xff1a; 4、自定义信号与槽&#xff1a; 4.1、运行效果&#xff1a; 5、信号与槽的特性&#xff1a; 6、Qt 4…

三张图搞定TCP 握手、HTTPS、TLS加密过程

1. 抓包内容&#xff08;WireShark&#xff09; 2. 搞定握手、挥手、SSL加密过程 3. 消息内容&#xff08;Charles&#xff09; 之前看到写的比较好的文章&#xff0c;有文字详细叙述&#xff1a; TLS版本差异 https://zhuanlan.zhihu.com/p/27524995?utm_source协议解析 htt…

TCP三次握手学习心得

客户端A若要连接服务端B&#xff0c;首先A会向B发送一个连接请求&#xff0c;其中SYN1&#xff0c;ACK0&#xff0c;B为了告诉A成功收到了消息&#xff0c;则向A发送一个确认包&#xff0c;其中SYN1,ACK1,这时A收到之后又会向B发送一个确认收到确认包的确认包&#xff0c;SYN0,…

使用wireshark抓取Tcp三次握手

文章目录 wireshark的下载安装TCP协议段格式简单介绍确认应答机制介绍使用wireshark抓取TCP的三次握手 wireshark的下载安装 软件的下载可以直接去官网下载 wireshark&#xff0c;选择自己电脑适合的版本就行。 但是不咋推荐&#xff0c;原因是国外网站访问速度太慢&#xff…

TCP的三次握手、四次挥手

一、TCP的三次握手 第一次握手&#xff1a;你能和我建立连接吗&#xff0c;可以接受到我的数据吗。 SYN 1 &#xff0c;seq x 第二次握手&#xff1a;可以建立连接&#xff0c;我接受到你的请求了&#xff0c;能接受到我的数据吗&#xff0c;你的数据是这个吗 SYN 1 &#…

TCP三次握手原理

在众多的网络协议中&#xff0c;TCP协议占据着举足轻重的地位&#xff0c;你知道什么是TCP协议吗&#xff1f; 一、TCP协议 TCP(Transmission Control Protoco)协议属于计算机网络体系中的运输层。运输层的任务是负责向主机中应用层进程之间的通信提供通用的数据传输服务。所以…

TCP三次握手及四次挥手过程中的异常处理

1. 消息丢失的情况&#xff1a; 总的原则&#xff1a; ACK不会重传&#xff0c;SYN和FIN报文段有最大重传次数。无论是SYN还是FIN&#xff0c;达到最大重传次数后对端若仍无响应则直接进入CLOSED状态。 1.1 三次握手过程的消息丢失&#xff1a; 正常的三次握手的流程&#x…

HTTPS 中 TLS 和 TCP 能同时握手吗?

HTTPS 中 TLS 和 TCP 能同时握手吗&#xff1f; 大家好&#xff0c;我是小林。 有位读者在面试的时候&#xff0c;碰到这么个问题&#xff1a; 面试官跟他说 HTTPS 中的 TLS 握手过程可以同时进行三次握手&#xff0c;然后读者之前看我的文章是说「先进行 TCP 三次握手&#…

TCP优化一:TCP 三次握手的优化

TCP 三次握手的性能提升 TCP 是面向连接的、可靠的、双向传输的传输层通信协议&#xff0c;所以在传输数据之前需要经过三次握手才能建立连接。 那么&#xff0c;三次握手的过程在一个 HTTP 请求的平均时间占比 10% 以上&#xff0c;在网络状态不佳、高并发或者遭遇 SYN 攻击…

TCP握手过程和挥手过程

TCP报文首部 源端口和目的端口&#xff0c;各占2个字节&#xff0c;分别写入源端口和目的端口&#xff1b;序号&#xff0c;占4个字节&#xff0c;TCP连接中传送的字节流中的每个字节都按顺序编号。例如&#xff0c;一段报文的序号字段值是 301 &#xff0c;而携带的数据共有1…

TCP三次握手

TCP协议是传输层协议&#xff0c;是一种面向连接的传输控制协议&#xff0c;可以控制流量的传输。是一种可靠的传输&#xff0c;能够保证数据的完整性&#xff0c;有效性和有序性。 1.TCP建立连接&#xff08;三次握手&#xff09; 第一次握手&#xff1a;PC1发送SYN请求&…

TCP握手与挥手详解(附有图)

为什么不是4次握手 首先我们知道TCP是3次握手与4次挥手&#xff0c;为什么不是4次握手呢&#xff0c;因为其中握手请求同步过程中并不需要数据传输因此将两次合并为一次了。 我们需要掌握哪些标志量 SYN&#xff1a;请求同步标志&#xff0c;为1的时候为有效 ACK&#xff1…

为什么TCP需要握手

一、TCP握手流程 二、为什么不是4次握手 TCP的每次请求都是成对的&#xff0c;原则上应该是四次 【Client to Server】第一次SYN&#xff0c;seqx【Server to Client】第二次ACK&#xff0c;seqy&#xff0c;ackx1&#xff08;没有携带数据的ACK不消耗序列号&#xff09;【Se…

tcp_tw_recycle引起的TCP握手失败

背景 测试环境的一台Nginx服务器&#xff0c;最近一直被前端同事吐槽网络有问题&#xff0c;经常出现访问HTTP请求时超时&#xff0c;哪怕是静态文件也经常超时。 刚开始以为是公司网络抽风了&#xff0c;也就没放在心上&#xff0c;但持续了一个星期&#xff0c;而且复现率很…

TCP握手过程(正解版)

参考文章 Why do we need a 3-way handshake? Why not just 2-way https://blog.csdn.net/qq_36903042/article/details/102656641 https://blog.csdn.net/qq_36903042/article/details/102513465 大部分网络博客的错误解读 首先需要声明的是&#xff0c; 百度搜索到的大…

网络协议 (五) TCP握手建立连接

一、握手策略 为了可以准确的将数据准确无误地送达目标主机&#xff0c;所有基于 TCP 实现的协议&#xff0c;都需要先完成 TCP 协议的三次握手策略。 1. 首先我们需要了解一下图中提到的几个标志符&#xff1a; 1.序号seq seq 是TCP通信过程中&#xff0c;某一个传输方向上字…

TCP 握手没成功怎么办?

大家好&#xff0c;我是小林。 之前收到个读者的问题&#xff0c;对于 TCP 三次握手和四次挥手的一些疑问&#xff1a; 第一次握手&#xff0c;如果客户端发送的SYN一直都传不到被服务器&#xff0c;那么客户端是一直重发SYN到永久吗&#xff1f;客户端停止重发SYN的时机是什么…