Qt下QTcpServer服务端识别多个QTcpSocket客户端

news2024/11/24 6:22:08

文章目录

  • Qt官方文档
  • 编写QTcpServerDemo和QTcpSocketDemo
    • 实现QTcpServerDemo
    • 实现QTcpSocketDemo
  • 使用windeployqt生成程序运行所需依赖文件

Qt官方文档

QTcpSocket Class :https://doc.qt.io/qt-5/qtcpsocket.html
QAbstractSocket Class:https://doc.qt.io/qt-5/qabstractsocket.html
QTcpServer Class:https://doc.qt.io/qt-5/qtcpserver.html

编写QTcpServerDemo和QTcpSocketDemo

看一下效果先:

在这里插入图片描述

实现QTcpServerDemo

头文件:

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QTcpServer>
#include <QTcpSocket>
#include <QNetworkConfigurationManager>
#include <QNetworkInterface>

QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();
public slots:
	/// 服务端接收到客户端连接的槽函数
    void TcpServerConnected();
    /// 服务端接收客户端发送的数据的槽函数
    void ReadAllData();
    /// 客户端连接断开的槽函数
    void ClientDisconnected();

private slots:
	/// 点击启动按钮
    void on_btnRun_clicked();

private:
    Ui::MainWindow *ui;
    /// QTcpServer是服务端
    QTcpServer *tcpServer = nullptr;
    /// QTcpSocket是服务端程序用来与客户端进行通信的
    QTcpSocket *tcpSocket = nullptr;
    /// 用来存储来自客户端的连接
    QList<QTcpSocket*> tcpSocketList;

};
#endif // MAINWINDOW_H

源文件:

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QDebug>

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    tcpServer = new QTcpServer(this); // 构造函数中实例化tcpServer
    connect(tcpServer,&QTcpServer::newConnection,this,&MainWindow::TcpServerConnected); // 当有客户端连接到服务端就执行TcpServerConnected槽函数
}

MainWindow::~MainWindow()
{
    delete ui;
    for(auto client : tcpSocketList)
        client->close();
}

/// 点击启动按钮
void MainWindow::on_btnRun_clicked()
{
    QHostAddress address = QHostAddress("127.0.0.1"); // ip
    int port = 5023; // 端口
    if(tcpServer->isListening()) // 判断服务端是否开启了监听
    {
        tcpServer->close()
        for(auto client : tcpSocketList)
            client->close();
        tcpSocketList.clear();
        ui->label->setText(QString("关闭监听成功,%1:%2").arg(address.toString()).arg(port));
        ui->btnRun->setText("开启");
    }
    else
    {
        if(!tcpServer->listen(address,port)) // 服务端开启监听
            ui->label->setText(QString("开启监听失败,%1:%2").arg(address.toString()).arg(port));
        else
        {
            ui->label->setText(QString("开启监听成功,%1:%2").arg(address.toString()).arg(port));
            ui->btnRun->setText("关闭");
        }
    }

}

/// 当有客户端连接到服务端
void MainWindow::TcpServerConnected()
{
    tcpSocket = tcpServer->nextPendingConnection();
    if(!tcpSocketList.contains(tcpSocket))
        tcpSocketList.append(tcpSocket);
    connect(tcpSocket,&QTcpSocket::readyRead,this,&MainWindow::ReadAllData);
    connect(tcpSocket,&QTcpSocket::disconnected,this,&MainWindow::ClientDisconnected);
    ui->txtLog->append(tcpSocket->localAddress().toString() + " 已连接");
}

/// 服务端接收客户端发送的数据
void MainWindow::ReadAllData()
{
    QTcpSocket *client = dynamic_cast<QTcpSocket*>(sender());
    QByteArray buff = client->readAll();
    qDebug() << buff;
    ui->txtLog->append(buff);
    client->write(buff);
}

/// 当关闭与客户端的连接时
void MainWindow::ClientDisconnected()
{
    QTcpSocket *client = dynamic_cast<QTcpSocket*>(sender());
    QString msg = QString("触发断开连接,%1:%2").arg(client->peerAddress().toString()).arg(client->peerPort());
    qDebug() << msg;
    ui->txtLog->append(msg);
}

实现QTcpSocketDemo

头文件:

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QTcpSocket>
#include <QTcpServer>
#include <QNetworkInterface>

QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();

public slots:
    void ReadAllData();
    void Connected();
    void Disconnected();

private slots:
    void on_btnSend_clicked();

    void on_btnDisconnect_clicked();

private:
    Ui::MainWindow *ui;
    QTcpSocket *tcpSocket = nullptr;
    QHostAddress address;
    int port;
};
#endif // MAINWINDOW_H

源文件:

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QDebug>

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    tcpSocket = new QTcpSocket(this);
    connect(tcpSocket,&QTcpSocket::readyRead,this,&MainWindow::ReadAllData);
    connect(tcpSocket,&QTcpSocket::connected,this,&MainWindow::Connected);
    connect(tcpSocket,&QTcpSocket::disconnected,this,&MainWindow::Disconnected);
    address = QHostAddress("127.0.0.1");
    port = 5023;
    ui->txtIp->setText(address.toString());
    ui->txtPort->setText(QString::number(port));
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::ReadAllData()
{
    QByteArray buff = tcpSocket->readAll();
    qDebug() << buff;
    ui->txtLog->append(buff);
}

void MainWindow::Connected()
{
    QString address = tcpSocket->peerAddress().toString();
    int port = tcpSocket->peerPort();
    qDebug() << QString("连接成功, %1:%2").arg(address).arg(port);
    ui->txtLog->append(QString("连接成功, %1:%2").arg(address).arg(port));
}

void MainWindow::Disconnected()
{
    ui->txtIp->setEnabled(true);
    ui->txtPort->setEnabled(true);
    ui->btnSend->setText("连接");
}

void MainWindow::on_btnSend_clicked()
{
    QString txt = ui->txtSend->toPlainText();
    tcpSocket->write(txt.toStdString().c_str());
}

void MainWindow::on_btnDisconnect_clicked()
{
    address = QHostAddress(ui->txtIp->text());
    port = ui->txtPort->text().toInt();
    if(tcpSocket->state() == QTcpSocket::SocketState::ConnectedState)
    {
        ui->txtIp->setEnabled(true);
        ui->txtPort->setEnabled(true);
        tcpSocket->disconnectFromHost();
        ui->btnDisconnect->setText("连接");
    }
    else
    {
        ui->txtIp->setEnabled(false);
        ui->txtPort->setEnabled(false);
        tcpSocket->connectToHost(address.toString(),port);
        ui->btnDisconnect->setText("断开");
    }
}

使用windeployqt生成程序运行所需依赖文件

确认编译环境:

在这里插入图片描述
在对应编译环境目录下运行 windeployqt 生成运行程序所需的依赖文件:

在这里插入图片描述

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

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

相关文章

分布式RPC框架Dubbo详解

目录 1.架构演进 1.1 单体架构 1.2 垂直架构 1.3 分布式架构 1.4 SOA架构 1.5 微服务架构 2.RPC框架 2.1 RPC基本概念介绍 2.1.1 RPC协议 2.1.2 RPC框架 2.1.3 RPC与HTTP、TCP/ UDP、Socket的区别 2.1.4 RPC的运行流程 2.1.5 为什么需要RPC 2.2 Dubbo 2.2.1 Dub…

Redis的网络模型(未完成)

Redis是单线程还是多线程&#xff1f; 1)如果只是针对于Redis的核心业务部分(命令处理)&#xff0c;答案是单线程 2)如果是说整个redis&#xff0c;那么就是多线程 在Redis的版本迭代过程中&#xff0c;在两个非常重要的时间节点上引入了对多线程的支持: 1)在Redis4.0版本中&am…

redis第二章-第一课-持久化rdb和aof以及混合模式

RDB快照 1.在默认情况下&#xff0c; Redis 将内存数据库快照保存在名字为 dump.rdb 的二进制文件中&#xff0c;默认存储在redis的当前目录下&#xff0c;也就是和redis.conf同级目录下&#xff0c;可以修改位置 2.你可以对 Redis 进行设置&#xff0c; 让它在“ N 秒内数据…

小白怎么入门CTF,看这个就够了(附学习笔记、靶场、工具包下载)

CTF靶场&#xff1a;CTF刷题&#xff0c;在校生备战CTF比赛&#xff0c;信安入门、提升自己、丰富简历之必备&#xff08;一场比赛打出好成绩&#xff0c;可以让你轻松进大厂&#xff0c;如近期的各种CTF杯&#xff09;&#xff0c;在职人员可以工作意外提升信安全技能。 渗透…

00后太卷了,搞的我们这些老油条太难受了......

前几天我们公司一下子也来了几个新人&#xff0c;这些年前人是真能熬啊&#xff0c;本来我们几个老油子都是每天稍微加会班就打算走了&#xff0c;这几个新人一直不走&#xff0c;搞得我们也不好走。 2023年春招结束了&#xff0c;最近内卷严重&#xff0c;各种跳槽裁员&#x…

rk3568 点亮LCD(DP)

rk3568 rk3399 Android11/12 适配 DP DisplayPort&#xff08;简称DP&#xff09;是第一个依赖数据包化数据传输技术的显示通信端口。是一个由PC及芯片制造商联盟开发&#xff0c;视频电子标准协会标准化的数字式视频接口标准。主要用于视频源与显示器等设备的连接&#xff0c…

进程管理(笔记)

如果对内存寻址熟悉的话, 或者认真看过上一节的内容: 内存管理之内存寻址: https://blog.csdn.net/qq_40482358/article/details/130868188. 那么对linux系统中的进程管理应该已经有一个初步的认识了: cr3作为一个控制寄存器, 描述当前进程的页目录的物理内存基地址, 当进程切换…

SpringCloud Ribbon 学习

SpringCloud Ribbon 学习 文章目录 SpringCloud Ribbon 学习1. Ribbon 是什么&#xff1f;2. LB(Load Balance)3 Ribbon 架构图&机制4 Ribbon 常见负载均衡算法5 测试 1. Ribbon 是什么&#xff1f; Spring Cloud Ribbon 是基于 Netflix Ribbon 实现的一套客户端 负载均衡…

Docker容器与虚拟机(VM)大对比

Docker是一个开源应用容器引擎。Docker可以将应用程序与基本架构分开&#xff0c;从而快速交付软件。 传统虚拟机的运行需要占用较高的资源&#xff0c;包括磁盘空间、内存和处理器性能。每个虚拟机都需要完整的操作系统和应用程序副本&#xff0c;这在资源利用和启动时间上存…

好玩!AI文字RPG游戏;播客进入全AI时代?LangChain项目实践手册;OpenAI联创科普GPT | ShowMeAI日报

&#x1f440;日报&周刊合集 | &#x1f3a1;生产力工具与行业应用大全 | &#x1f9e1; 点赞关注评论拜托啦&#xff01; &#x1f916; Microsoft Build 中国黑客松挑战赛&#xff0c;进入AI新纪元 近期&#xff0c;伴随着人工智能的新一轮浪潮&#xff0c;Hackathon (黑…

python+pytest接口自动化之HTTP协议基础

目录 HTTP协议简介 HTTP协议特点 HTTP接口请求方法 HTTP与HTTPS区别 HTTP与TCP/IP区别 HTTP请求过程 总结 HTTP协议简介 HTTP 即 HyperText Transfer Protocol&#xff08;超文本传输协议&#xff09;&#xff0c;是互联网上应用最为广泛的一种网络协议。所有的 WWW 文件…

WePY小程序框架实践指南

在小程序开发中&#xff0c;提高开发效率、优化代码质量和增强用户体验是每位开发者都追求的目标。 下面我们从小程序开发框架来讲讲如何帮助开发提效&#xff0c;其中 WePY 是一个稍微冷门一些的开发框架&#xff0c;基于 Vue.js 的小程序开发的框架&#xff0c;提供了更好的…

Android系统中的Binder通信机制分析(7)- Java 层的 Binder 机制

声明 其实对于Android系统Binder通信的机制早就有分析的想法&#xff0c;记得2019年6、7月份Mr.Deng离职期间约定一起对其进行研究的&#xff0c;但因为我个人问题没能实施这个计划&#xff0c;留下些许遗憾…文中参考了很多书籍及博客内容&#xff0c;可能涉及的比较多先不具…

【网络】无线路由器的AP、Client、WDS、WISP使用功能图解(清晰明了)

1、有线路由器 有线路由器组成:一个有一个 WAN 口和一个 LAN 口的路由器、一个有几个 LAN 口的网络交换机,一个接在 LAN 口的 DHCP 服务器。如下图所示 2、无线路由器:AP模式 在路由器的 LAN 口上,接了一个无线交换机。这个无线交换机的无线插接口,就是这个无线路由器…

es7.x Es常用核心知识快捷版2 各种查询

一 常用查询 1.1 term查询 term关键字查询&#xff0c;精确匹配&#xff0c;不会对查询条件进行分词。 1.2 match查询 匹配查询&#xff0c;会将查询条件进行分词&#xff0c;然后进行查询,多个分词后查询的关系是or elasticsearh中查询类型&#xff0c;term、match、match_…

golang 微服务中的断路器 hystrix 小案例

上次我们分享了 Hystrix 具体流程&#xff0c;作为断路器实现&#xff0c;我们如何将 hystrix 用在我们的项目代码中呢&#xff1f; 我们可以简单的将 hystrix-go 下载下来 go get github.com/afex/hystrix-go/hystrix 代码会放到我们的 GOPATH 中&#xff0c;的 pkg 下面&a…

用vue-full-calendar实现酒店预定管理展示

文章目录 前言一、关于vue-full-calendar二、使用步骤1. 引入库2. 使用库3. 开始编码4. 实际效果图展示5. 点击弹窗展示6. 弹窗展示效果图 总结 前言 近些天有位做酒店业务朋友问到我&#xff0c;有没有前端比较好用的预定日历查看插件&#xff0c;实际上我也没有研究过&#…

【板栗糖GIS】——如何良好的导出并批量管理kindle上的笔记

【板栗糖GIS】——如何良好的导出并批量管理kindle上的笔记 目录 1.将Kindle Mate安装到电脑上 2. 将kindle通过usb线连接到电脑。 3. 打开Kindle Mate软件&#xff0c;按F2自动导入笔记 4. 选择导出方式 5. 笔记修饰 1.将Kindle Mate安装到电脑上 下载地址&#xff1a;…

网络安全保姆级教程,别再说你学不会了

开始&#xff0c;在选择软件系统方面。很多人会纠结于是使用Linux还是Windows或者Mac系统。 虽然Linux系统看起来很酷&#xff0c;但对于新手来说并不是很友好。 同样&#xff0c;Windows系统也可以通过使用虚拟机装靶机进行学习。所以&#xff0c;直接用window&#xff0c;学…

【Windows安全】授权初探:访问控制基础及应用

▒ 目录 ▒ &#x1f6eb; 导读需求开发环境 1️⃣ 常见名词及缩写汇总主体对象权限&#xff08;规则&#xff09; 2️⃣ 常见概念访问控制及安全级别访问令牌&#xff08;Access tokens&#xff09;特权 (Privilege) - 线程相关的安全描述符(Security Descriptors,SD)访问控制…