当前位置: 首页 > news >正文

QT网络通信

九、网络

  1. 基础概念

1.1 TCP/UDP

TCP/UDP

UDP TCP 协议相同点:都存在于传输层,全双工通信

TCP:全双工通信、面向连接、可靠

TCP(即传输控制协议):是一种面向连接的传输层协议,它能提供高可靠性通信(即数据无误、数据无丢失、数据无失序、数据无重复到达的通信)。

高可靠原因:1.三次握手、四次挥手

2. 序列号和应答机制

3. 超时,错误重传机制

适用场景

适合于对传输质量要求较高的通信

在需要可靠数据传输的场合,通常使用TCP协议

MSN/QQ等即时通讯软件的用户登录账户管理相关的功能通常采用TCP协议

UDP:全双工通信、面向无连接、不可靠

UDP(User Datagram Protocol)用户数据报协议,是不可靠的无连接的协议。在数据发送前,因为不需要进行连接,所以可以进行高效率的数据传输。

适用场景

发送小尺寸数据(如对DNS服务器进行IP地址查询时)

适合于广播/组播式通信中。

MSN/QQ/Skype等即时通讯软件的点对点文本通讯以及音视频通讯通常采用UDP协议

1.2 IP地址与端口号

IP地址

1. IP地址是Internet中主机的标识,本质:  二进制

    IP地址一般分割为 4个八位二进制的数(4字节-32位)

2. Internet中的主机要与别的机器通信必须具有一个IP地址

3. IP地址(长度)为32位(IPv4),128位(IPv6),目前ipv6还未普及,主要学习ipv4

4. 每个数据包都必须携带目的IP地址和源IP地址,路由器依靠此信息为数据包选择路由 

5. 表示方法 :  点分十进制

  点分十进制表示就是用4组从0~255的数字,来表示一个IP地址。

端口号Port

1. 为了区分一台主机接收到的数据包应该给哪个进程来进行处理,使用端口号来区别

     (通过 IP地址 找到哪台主机  通过 port端口号 来找到哪台主机的哪个进程)

2. TCP端口号与UDP端口号独立 (UDP port为8888,TCP port也可为8888 )

3. 端口号一般由IANA (Internet Assigned Numbers Authority) 管理

4. 端口(sin_prot)用2个字节表示 2byte  (IP地址占4个字节)

众所周知端口(被占用): 1~1023(1~255之间为众所周知端口,通常由UNIX系统占用)

比如文件传输端口 TFTP  端口号为 69 

已登记端口:1024~49151   (----可用来建立与其它主机的会话----) 

动态或私有端口:49152~65535  --固定某些服务使用--

自定义的端口号建议使用2000以上,且非豹子号(例如6666/8888等)。

仅以使用2000以上,非豹子号的端口号,本次授课采用8887

2、准备工作

与数据库编程一样,Qt的网络功能需要在.pro项目配置文件中增加network模块。

网络编程主要用到两个类:

  • QTcpServer

表示一个基于Tcp的服务器,需要注意的是,此类直接继承了QObject类,不继承QIODevice类,因此不具备任何IO的能力。

  • QTcpSocket

表示一个基于TCP的Socket连接,间接继承了QIODevice类,因此使用此类对象进行IO读写。

3、相关函数

// 构造函数,堆内存开辟
QTcpServer::​QTcpServer(QObject * parent = 0)

// 开启监听服务,等待客户端发起连接
// 参数1:监听来源(那个网段的IP地址),默认值表示不加任何限制
// 参数2:服务器占用的端口号。默认值为0表示随机选取。8887
bool QTcpServer::​listen(const QHostAddress & address = QHostAddress::Any, quint16 port = 0)

// 查看当前是否正在监听
bool QTcpServer::​isListening() const

// 关闭监听服务
void QTcpServer::​close()

#include "dialog.h"
#include "ui_dialog.h"Dialog::Dialog(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::Dialog)
{
    ui->setupUi(this);
    // 抢占前台
    setWindowFlags(Qt::WindowStaysOnTopHint);
    server = new QTcpServer(this);    // 开启监听
    bool result = server->listen(QHostAddress::Any,8887);
    if(!result)
    {
        ui->textBrowser->append("监听失败");
        return;
    }
    ui->textBrowser->append("监听开启成功,端口号为8887");
}Dialog::~Dialog()
{
    // 关闭监听功能
    if(server->isListening()) // 判断是否正在监听
    {
        server->close();
    }
    delete ui;
}

客户端

// 构造函数,堆区开辟
QTcpSocket::​QTcpSocket(QObject * parent = 0)

// 连接到服务器
// 参数1:服务器的IP地址
// 参数2:服务器的端口号
// 参数3:打开模式。默认读写模式
void QAbstractSocket::​connectToHost(const QString & hostName,
            quint16 port, 
            OpenMode openMode = ReadWritel)[virtual]

#include "dialog.h"
#include "ui_dialog.h"Dialog::Dialog(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::Dialog)
{
    ui->setupUi(this);
    setWindowFlags(Qt::WindowStaysOnTopHint);    connect(ui->pushButtonConn,SIGNAL(clicked()),
            this,SLOT(btnConnClickedSlot()));
    connect(ui->pushButtonSend,SIGNAL(clicked()),
            this,SLOT(btnSendClickedSlot()));    socket = new QTcpSocket(this);
}Dialog::~Dialog()
{
    // 如果数据流处于打开状态
    if(socket->isOpen())
    {
        // 如果打开则关闭
        socket->close();
    }
    delete ui;
}void Dialog::btnConnClickedSlot()
{
    // 获取用户输入的IP和端口
    QString ip = ui->lineEditIp->text();
    int port = ui->spinBox->value();    // 建立连接
    socket->connectToHost(ip,port);
}void Dialog::btnSendClickedSlot()
{}

我们怎么直到,是否有客户端连接了那?

所有通知类,第一时间想到到的信号槽。

// 每当有新的连接可以用时,就会发出此信号
void QTcpServer::​newConnection() [signal]

// 连接成功的信号
void QAbstractSocket::​connected()[signal]

// 连接失败的信号
void QAbstractSocket::​disconnected()[signal]

#include "dialog.h"
#include "ui_dialog.h"Dialog::Dialog(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::Dialog)
{
    ui->setupUi(this);
    setWindowFlags(Qt::WindowStaysOnTopHint);    connect(ui->pushButtonConn,SIGNAL(clicked()),
            this,SLOT(btnConnClickedSlot()));
    connect(ui->pushButtonSend,SIGNAL(clicked()),
            this,SLOT(btnSendClickedSlot()));    socket = new QTcpSocket(this);
    connect(socket,SIGNAL(connected()),
            this,SLOT(connectedSlot()));
    connect(socket,SIGNAL(disconnected()),
            this,SLOT(disconnectedSlot()));
}Dialog::~Dialog()
{
    // 如果数据流处于打开状态
    if(socket->isOpen())
    {
        // 如果打开则关闭
        socket->close();
    }
    delete ui;
}void Dialog::btnConnClickedSlot()
{
    // 获取用户输入的IP和端口
    QString ip = ui->lineEditIp->text();
    int port = ui->spinBox->value();    // 建立连接
    socket->connectToHost(ip,port);
}void Dialog::btnSendClickedSlot()
{}// 连接成功
void Dialog::connectedSlot()
{
    // 屏蔽连接按钮
    ui->pushButtonConn->setEnabled(false);
    ui->pushButtonConn->setText("已连接");    // 释放发送按钮
    ui->pushButtonSend->setEnabled(true);
}// 断开连接
void Dialog::disconnectedSlot()
{
    // 释放连接按钮
    ui->pushButtonConn->setEnabled(true);
    ui->pushButtonConn->setText("连接");    // 屏蔽发送按钮
    ui->pushButtonSend->setEnabled(false);
}

// 返回与客户端连接的QTcpSocket对象
QTcpSocket * QTcpServer::​nextPendingConnection()[virtual]

// 获取对面(客户端)的IP地址
// 返回值为IP地址封装类
QHostAddress QAbstractSocket::​peerAddress() const

// 返回对面的(客户端)端口号
quint16 QAbstractSocket::​peerPort() const

// 转换为IP地址字符串,在计算机中会自动增加一个前缀
QString QHostAddress::​toString() const

客户端.cpp

#include "dialog.h"
#include "ui_dialog.h"Dialog::Dialog(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::Dialog)
{
    ui->setupUi(this);
    setWindowFlags(Qt::WindowStaysOnTopHint);    connect(ui->pushButtonConn,SIGNAL(clicked()),
            this,SLOT(btnConnClickedSlot()));
    connect(ui->pushButtonSend,SIGNAL(clicked()),
            this,SLOT(btnSendClickedSlot()));    socket = new QTcpSocket(this);
    connect(socket,SIGNAL(connected()),
            this,SLOT(connectedSlot()));
    connect(socket,SIGNAL(disconnected()),
            this,SLOT(disconnectedSlot()));
}Dialog::~Dialog()
{
    // 如果数据流处于打开状态
    if(socket->isOpen())
    {
        // 如果打开则关闭
        socket->close();
    }
    delete ui;
}void Dialog::btnConnClickedSlot()
{
    // 获取用户输入的IP和端口
    QString ip = ui->lineEditIp->text();
    int port = ui->spinBox->value();    // 建立连接
    socket->connectToHost(ip,port);
}void Dialog::btnSendClickedSlot()
{}// 连接成功
void Dialog::connectedSlot()
{
    // 屏蔽连接按钮
    ui->pushButtonConn->setEnabled(false);
    ui->pushButtonConn->setText("已连接");    // 释放发送按钮
    ui->pushButtonSend->setEnabled(true);
}// 断开连接
void Dialog::disconnectedSlot()
{
    // 释放连接按钮
    ui->pushButtonConn->setEnabled(true);
    ui->pushButtonConn->setText("连接");    // 屏蔽发送按钮
    ui->pushButtonSend->setEnabled(false);
}

服务端.cpp

#include "dialog.h"
#include "ui_dialog.h"Dialog::Dialog(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::Dialog)
{
    ui->setupUi(this);
    // 抢占前台
    setWindowFlags(Qt::WindowStaysOnTopHint);
    server = new QTcpServer(this);    // 开启监听
    bool result = server->listen(QHostAddress::Any,8887);
    if(!result)
    {
        ui->textBrowser->append("监听失败");
        return;
    }
    ui->textBrowser->append("监听开启成功,端口号为8887");
    connect(server,SIGNAL(newConnection()),this,
            SLOT(newConnectionSlot()));
}Dialog::~Dialog()
{
    // 关闭监听功能
    if(server->isListening()) // 判断是否正在监听
    {
        server->close();
    }
    delete ui;
}void Dialog::newConnectionSlot()
{
    // 如果不是第一次连接,就踢掉上一个人
    if(socket != NULL)
    {
        // 踢掉上一个人
        socket->close();
    }    // 保存当前连接对象
    socket = server->nextPendingConnection();    // 获取对面的IP地址
    QString ip = socket->peerAddress().toString();    // 获取对面的端口号
    quint16 port = socket->peerPort();    ip.prepend("新连接来了!").append(":").append(QString::number(port));    ui->textBrowser->append(ip);
}

// 构造函数
// 参数事Qt的读写类,可以是QFile,也可以是QTcpSocket........
QTextStream::​QTextStream(QIODevice * device)

// 输出字符串内容,支持链式调用
QTextStream &	operator<<(const QString & string)

// 有数据可读时发射
void QIODevice::​readyRead()[signal]

// 读取最大长度为maxlen个QChar的内容,返回值为读取的字符串
QString QTextStream::​read(qint64 maxlen)

// 读取所有字符
QString QTextStream::​readAll()

// 一次读取一行文本
// 参数为一行文本的最大字符数
QString QTextStream::​readLine(qint64 maxlen = 0)

dialog.cpp 服务端

void Dialog::readyReadSlot()
{
    // 创建文本对象
    QTextStream input(socket);
    // 读取内容
    QString text = input.read(128);
    ui->textBrowser->append(text);
}

dialog.cpp 客户端

// 发送信息
void Dialog::btnSendClickedSlot()
{
    QString text = ui->lineEditSend->text();
    if(text == "")
    {
        QMessageBox::warning(this,"提示","请输入发送的内容");
        return;
    }    // 方法一:QTextStream 文本流
    // QTextStream直接使用Unicode编码,适合Qt与Qt之间通信。
    // 简化文本的读写操作
    QTextStream output(socket);
    // 发送数据
    output << text;
}

dialog.cpp 服务端

void Dialog::readyReadSlot()
{
//    // 创建文本对象
//    QTextStream input(socket);
//    // 读取内容
//    QString text = input.read(128);
//    ui->textBrowser->append(text);    // 读取所有内容
    QByteArray bufer = socket->readAll();
    // QByteArray -> QString
    QString text(bufer);
    // 显示
    ui->textBrowser->append(text);
}

dialog.cpp 客户端

void Dialog::btnSendClickedSlot()
{
    QString text = ui->lineEditSend->text();
    if(text == "")
    {
        QMessageBox::warning(this,"提示","请输入发送的内容");
        return;
    }    // 方法一:QTextStream 文本流
    // QTextStream直接使用Unicode编码,适合Qt与Qt之间通信。
    // 简化文本的读写操作
//    QTextStream output(socket);
//    // 发送数据
//    output << text;    // 方法二、QByteArray
    // 以字节为单位,可以与其他编程语言通信
    // 可以操作非文本内容
    // QString -> QByteArray
    QByteArray buffer = text.toUtf8();
    socket->write(buffer);
}

相关文章:

QT网络通信

九、网络 基础概念 1.1 TCP/UDP TCP/UDP UDP TCP 协议相同点&#xff1a;都存在于传输层&#xff0c;全双工通信 TCP&#xff1a;全双工通信、面向连接、可靠 TCP&#xff08;即传输控制协议&#xff09;&#xff1a;是一种面向连接的传输层协议&#xff0c;它能提供高可靠性通…...

案例分析|山西某光伏发电站轨道巡检机器人解决方案

随着光伏发电技术的不断发展&#xff0c;光伏变电站配电室作为能量转换和输送的关键节点&#xff0c;承担着重要的电力分配和保护功能。然而&#xff0c;传统的人工巡检方式存在诸多问题&#xff0c;如巡检周期长、效率低、安全风险高等&#xff0c;已经无法满足光伏变电站配电…...

Apache POl

介绍 Apache POl是一个处理Miscrosoft Ofice各种文件格式的开源项目。简单来说就是&#xff0c;我们可以使用 POI 在 Java 程序中对Miscrosoft Office各种文件进行读写操作,一般情况下&#xff0c;POI都是用于操作 Excel 文件。 Apache POl 的应用场景 1.银行网银系统导出交易…...

高防服务器托管应注意什么

选择高防服务器托管主要考虑的因素&#xff1a;1.服务商的服务器大小。2.服务器的防御值大小。3.服务器机房的位置以及机房的资质。 具体内容如下&#xff1a; 1&#xff0e;服务器大小是按照U来定的&#xff0c;U是一种表示服务器外部尺寸的单位(计量单位&#xff1a;高度或厚…...

swagger-ui.html报错404,解决办法

swagger-ui.html报错404,解决办法&#xff01;现在后端开发项目中&#xff0c;为了节省时间&#xff0c;使用swagger插件&#xff0c;可以方便的快捷生成接口文档。但是如果你在请求前端页面路径比如&#xff1a;http://127.0.0.1:7777/swagger-ui.html。找不到。那是因为你的配…...

golang 函数式编程库samber/mo使用: Future

golang 函数式编程库samber/mo使用&#xff1a; Future 如果您对samber/mo库不了解&#xff0c; 请先阅读第一篇 Option 本节讲述Future的使用&#xff0c;它可以帮助我们处理异步编程问题。 示例 我们先来看看下面代码的示例&#xff0c; 注释解释了每一步的操作。 packa…...

【Spring连载】使用Spring Data访问 MongoDB(十四)----Mongodb特有的查询方法

【Spring连载】使用Spring Data访问 MongoDB&#xff08;十四&#xff09;----Mongodb特有的查询方法 一、定义通用查询方法二、MongoDB特有的查询方法2.1 地理空间查询Geo-spatial Queries2.2 基于JSON的查询方法和字段限制2.3 使用SpEL表达式的基于JSON的查询2.4 全文检索查询…...

消息中间件篇之RabbitMQ-消息重复消费

一、导致重复消费的情况 1. 网络抖动。 2. 消费者挂了。 消费者消费消息后&#xff0c;当确认消息还没有发送到MQ时&#xff0c;就发生网络抖动或者消费者宕机。那当消费者恢复后&#xff0c;由于MQ没有收到消息&#xff0c;而且消费者有重试机制&#xff0c;消费者就会再一次消…...

常见设计模式之单例模式

单例模式 单例模式是一种常用的软件设计模式&#xff0c;主要目的是确保一个类在整个应用程序生命周期中只有一个实例&#xff0c;并提供一个全局访问点以获取该实例。 单例模式分为几种不同的实现方式&#xff0c;包括懒汉模式和饿汉模式。每种方式都有其特点和适用场景。例如…...

VL817-Q7 USB3.0 HUB芯片 适用于扩展坞 工控机 显示器

VL817-Q7 USB3.1 GEN1 HUB芯片 VL817-Q7 USB3.1 GEN1 HUB芯片 VIA Lab的VL817是一款现代USB 3.1 Gen 1集线器控制器&#xff0c;具有优化的成本结构和完全符合USB标准3.1 Gen 1规范&#xff0c;包括ecn和2017年1月的合规性测试更新。VL817提供双端口和双端口4端口配置&…...

【Android安全】Windows 环境下载 AOSP 源码

准备环境 安装 git 安装 Python 硬盘剩余容量最好大于 800G 打开 Git Bash&#xff0c;用 git 克隆源代码仓库 git clone https://android.googlesource.com/platform/manifest.git //没有梯子使用清华源 git clone https://aosp.tuna.tsinghua.edu.cn/platform/manifest.git这…...

Vue.js+SpringBoot开发快递管理系统

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、研究内容2.1 数据中心模块2.2 快递类型模块2.3 快递区域模块2.4 快递货架模块2.5 快递档案模块 三、界面展示3.1 登录注册3.2 快递类型3.3 快递区域3.4 快递货架3.5 快递档案3.6 系统基础模块 四、免责说明 一、摘要 1.1 项目介绍 …...

Linux/Spectra

Enumeration nmap 第一次扫描发现系统对外开放了22&#xff0c;80和3306端口&#xff0c;端口详细信息如下 22端口运行着ssh&#xff0c;80端口还是http&#xff0c;不过不同的是打开了mysql的3306端口 TCP/80 进入首页&#xff0c;点击链接时&#xff0c;提示域名不能解析&…...

C 嵌入式系统设计模式 08:硬件代理模式

本书的原著为&#xff1a;《Design Patterns for Embedded Systems in C ——An Embedded Software Engineering Toolkit 》&#xff0c;讲解的是嵌入式系统设计模式&#xff0c;是一本不可多得的好书。 本系列描述我对书中内容的理解。本文章描述访问硬件的设计模式之一&…...

【k8s配置与存储--持久化存储(PV、PVC、存储类)】

1、PV与PVC 介绍 持久卷&#xff08;PersistentVolume&#xff0c;PV&#xff09; 是集群中的一块存储&#xff0c;可以由管理员事先制备&#xff0c; 或者使用存储类&#xff08;Storage Class&#xff09;来动态制备。 持久卷是集群资源&#xff0c;就像节点也是集群资源一样…...

【Vite】解决Vite http proxy error: Error: connect ECONNREFUSED

今天写bug&#xff0c;发现了这个问题 我经过我一晚上的搜索努力&#xff0c;在github上找到了解决办法&#xff0c;不得不说&#xff0c;交友网站还是很好用的。 参考 这一行是关键代码。 因为我连的是本地后台服务&#xff0c;所以最后配置成这样 server: {open: true,pro…...

FPGA领域顶级学术会议

FPGA领域顶级学术会议主要有FPGA,FCCM,FPL和FPT。 1 FPGA 会议全名是: ACM/SIGDA International Symposium on Field-Programmable Gate Arrays 网站是:https://dl.acm.org/conference/fpga FPGA常年在美国举办,每年2月,偏FPGA基础研究; 该会议的论文免费下载。这个比…...

罗技鼠标滚轮模式介绍 | 鼠标滚轮异响 - 解决方案

滚轮模式介绍 针对罗技的滚轮模式进行介绍&#xff1a; 普通滚轮&#xff1a;滚动时有明显段落感&#xff0c;无法快速滚动。 智能滚轮&#xff1a;滚动力量较弱时&#xff0c;与普通滚轮无异&#xff1b;滚动力量大时&#xff0c;鼠标会自动减小滚轮阻尼&#xff0c;从而使滚…...

Scrapy与分布式开发(2.2):正则表达式

使用Python的re模块进行正则表达式操作详细讲解 一、引言 正则表达式是一种强大的文本处理工具,它使用特定的模式来搜索、匹配和替换文本。Python的re模块(正则表达式模块)提供了正则表达式匹配操作的所有功能。下面我们将详细讲解如何使用re模块进行正则表达式的操作。 …...

今年“全国爱耳日”主题确定!立聪堂助听器组织社区义诊

2024年3月3日是第二十五个“全国爱耳日”。 今年的活动主题定为“科技助听&#xff0c;共享美好生活”&#xff0c;旨在倡导全社会关注听力健康&#xff0c;并鼓励听力受损人群利用科技手段实现早期康复。 为响应这一主题&#xff0c;知名助听器验配连锁机构立聪堂迅速行动起…...

[特殊字符] 智能合约中的数据是如何在区块链中保持一致的?

&#x1f9e0; 智能合约中的数据是如何在区块链中保持一致的&#xff1f; 为什么所有区块链节点都能得出相同结果&#xff1f;合约调用这么复杂&#xff0c;状态真能保持一致吗&#xff1f;本篇带你从底层视角理解“状态一致性”的真相。 一、智能合约的数据存储在哪里&#xf…...

css实现圆环展示百分比,根据值动态展示所占比例

代码如下 <view class""><view class"circle-chart"><view v-if"!!num" class"pie-item" :style"{background: conic-gradient(var(--one-color) 0%,#E9E6F1 ${num}%),}"></view><view v-else …...

STM32+rt-thread判断是否联网

一、根据NETDEV_FLAG_INTERNET_UP位判断 static bool is_conncected(void) {struct netdev *dev RT_NULL;dev netdev_get_first_by_flags(NETDEV_FLAG_INTERNET_UP);if (dev RT_NULL){printf("wait netdev internet up...");return false;}else{printf("loc…...

ETLCloud可能遇到的问题有哪些?常见坑位解析

数据集成平台ETLCloud&#xff0c;主要用于支持数据的抽取&#xff08;Extract&#xff09;、转换&#xff08;Transform&#xff09;和加载&#xff08;Load&#xff09;过程。提供了一个简洁直观的界面&#xff0c;以便用户可以在不同的数据源之间轻松地进行数据迁移和转换。…...

Linux-07 ubuntu 的 chrome 启动不了

文章目录 问题原因解决步骤一、卸载旧版chrome二、重新安装chorme三、启动不了&#xff0c;报错如下四、启动不了&#xff0c;解决如下 总结 问题原因 在应用中可以看到chrome&#xff0c;但是打不开(说明&#xff1a;原来的ubuntu系统出问题了&#xff0c;这个是备用的硬盘&a…...

用docker来安装部署freeswitch记录

今天刚才测试一个callcenter的项目&#xff0c;所以尝试安装freeswitch 1、使用轩辕镜像 - 中国开发者首选的专业 Docker 镜像加速服务平台 编辑下面/etc/docker/daemon.json文件为 {"registry-mirrors": ["https://docker.xuanyuan.me"] }同时可以进入轩…...

ArcGIS Pro制作水平横向图例+多级标注

今天介绍下载ArcGIS Pro中如何设置水平横向图例。 之前我们介绍了ArcGIS的横向图例制作&#xff1a;ArcGIS横向、多列图例、顺序重排、符号居中、批量更改图例符号等等&#xff08;ArcGIS出图图例8大技巧&#xff09;&#xff0c;那这次我们看看ArcGIS Pro如何更加快捷的操作。…...

STM32---外部32.768K晶振(LSE)无法起振问题

晶振是否起振主要就检查两个1、晶振与MCU是否兼容&#xff1b;2、晶振的负载电容是否匹配 目录 一、判断晶振与MCU是否兼容 二、判断负载电容是否匹配 1. 晶振负载电容&#xff08;CL&#xff09;与匹配电容&#xff08;CL1、CL2&#xff09;的关系 2. 如何选择 CL1 和 CL…...

通过MicroSip配置自己的freeswitch服务器进行调试记录

之前用docker安装的freeswitch的&#xff0c;启动是正常的&#xff0c; 但用下面的Microsip连接不上 主要原因有可能一下几个 1、通过下面命令可以看 [rootlocalhost default]# docker exec -it freeswitch fs_cli -x "sofia status profile internal"Name …...

Sklearn 机器学习 缺失值处理 获取填充失值的统计值

💖亲爱的技术爱好者们,热烈欢迎来到 Kant2048 的博客!我是 Thomas Kant,很开心能在CSDN上与你们相遇~💖 本博客的精华专栏: 【自动化测试】 【测试经验】 【人工智能】 【Python】 使用 Scikit-learn 处理缺失值并提取填充统计信息的完整指南 在机器学习项目中,数据清…...