2023/10/4 QT实现TCP服务器客户端搭建

news2024/9/20 14:36:49

服务器端:

头文件

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include <QTcpServer>
#include <QTcpSocket>
#include <QList>
#include <QMessageBox>
#include <QDebug>

QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE

class Widget : public QWidget
{
    Q_OBJECT

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

private slots:
    void on_startbtn_clicked();

    void newConnection_slot();

    void readyRead_slot();



private:
    Ui::Widget *ui;

    //定义服务器指针
    QTcpServer *server;

    //定义客户端容器
    QList<QTcpSocket *> clientlist;
};
#endif // WIDGET_H

源文件

#include "widget.h"
#include "ui_widget.h"


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

    //1.实力化一个服务器
    server = new QTcpServer(this);

    //此时服务器已经成功进入监听状态,如果客户端向服务器发来连接请求
    //那么服务器就会自动发射一个newconnection信号,可以在该信号连接到对应的槽函数作出相应处理
    //3.由于只需要连接一次即可,所以可以将该连接放在构造函数中完成
    connect(server,&QTcpServer::newConnection,this,&Widget::newConnection_slot);


}

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

//启动服务器按钮对应的槽函数
void Widget::on_startbtn_clicked()
{
    //获取ui界面上的端口号
    quint16 port = ui->portedit->text().toInt();

    //2.监听客户端的连接请求
    if(!server->listen(QHostAddress::Any,port))
    {
        QMessageBox::information(this,"失败","监听失败");
        return ;
    }
    else
    {
        QMessageBox::information(this,"成功","服务器启动成功");
    }

}

//自定义处理newconnection信号的槽函数实现
void Widget::newConnection_slot()
{
    qDebug()<<"您有新的客户端发来连接请求了";

    //4.获取最新连接的客户端套接字
    QTcpSocket *s = server->nextPendingConnection();

    //将该套接字放入客户端链表中
    clientlist.push_back(s);

    //如果客户端发来数据,对应的客户端套接字就会自动发射一个readyRead信号
    //4.可以将该信号连接到自定义的槽函数中,处理对应的逻辑
    connect(s,&QTcpSocket::readyRead,this,&Widget::readyRead_slot);
}

//readyRead信号对应槽函数的实现
void Widget::readyRead_slot()
{
    qDebug()<<"有新的客户端消息发来";

    //遍历客户端链表,将无效的客户端移除

    for(int i=0;i<clientlist.size();i++)
    {
        if(clientlist[i]->state()==0)
        {
            //将该套接字移除客户端容器
            clientlist.removeAt(i);
        }
    }

    //遍历客户端链表,判断是那个客户端发来的数据
    for(int i=0;i<clientlist.size();i++)
    {
        //bytesAvalilable函数,功能:求当前客户端套接字中待读数据的字节数
        //返回值:字节数,如果是0,表示无数据待读
        if(clientlist[i]->bytesAvailable()!=0)
        {
            //将待读的数据读取出来
            QByteArray msg = clientlist[i]->readAll();
            //将数据展示到ui界面上
            ui->msgwidget->addItem(QString::fromLocal8Bit(msg));


            //将接收到的数据据,转发给所有客户端
            for(int j=0;j<clientlist.size();j++)
            {
                clientlist[j]->write(msg);
            }
        }
    }

}

ui界面

客户端:

头文件:

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include <QTcpSocket>    //客户端类
#include <QMessageBox>
QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE

class Widget : public QWidget
{
    Q_OBJECT

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

private slots:
    void on_connectbtn_clicked();
    //自定义处理conneced信号的槽函数
    void connected_slot();
    void readyRead_slot();
    void on_sendbtn_clicked();

    void on_disconnectbtn_clicked();
    void disconnected_slot();
private:
    Ui::Widget *ui;

    //定义客户端指针
    QTcpSocket *socket;

    //定义字符串接收用户名
    QString userName;
};
#endif // WIDGET_H

源文件

#include "widget.h"
#include "ui_widget.h"

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

    //给客户端指针实例化对象
    socket = new QTcpSocket(this);
    //此时,已经向服务器发送连接请求了,如果成功连接服务器,那么该客户端就会自动发射一个connected的信号
    //我们可以将该信号连接到自定义的槽函数中处理逻辑
    //由于只需要连接一次,所有将连接写在构造函数中
    connect(socket,&QTcpSocket::connected,this,&Widget::connected_slot);

    //如果服务器向客户端发来消息,那么客户端就会自动发射一个readyRead信号
    //我们可以将该进行连接到自定义的槽函数中处理相关逻辑
    connect(socket,&QTcpSocket::readyRead,this,&Widget::readyRead_slot);

    //当成功与服务器断开连接后,该客户端会自动发射一个disconned的信号
    //

    connect(socket,&QTcpSocket::disconnected,this,&Widget::disconnected_slot);
}

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

//连接服务器按钮定义的槽函数
void Widget::on_connectbtn_clicked()
{
    //获取ui界面上的相关信息
    userName =ui->username_edit->text(); //获取用户名
    QString ip =ui->ip_edit->text();     //主机地址
    quint16 port =ui->port_edit->text().toUInt(); //端口号
    //将客户端连接到给定的服务器
    socket->connectToHost(ip,port);



}
//处理conneced信号的槽函数的定义
void Widget::connected_slot()
{
    QMessageBox::information(this,"成功","您已经成功进入聊天室");
    //向服务器发送一条数据:***进入聊天室
    QString msg = userName + "进入聊天室";

    socket->write(msg.toLocal8Bit()); //将数据写给服务器
}

//处理readyRead信号的槽函数的定义
void Widget::readyRead_slot()
{
    //读取套接字中的信息
    QByteArray msg = socket->readAll();

    //将数据展示到ui界面
    ui->msgWidget->addItem(QString::fromLocal8Bit(msg));
}

//发送按钮对应的槽函数
void Widget::on_sendbtn_clicked()
{
    //获取ui界面输入的内容
    QString msg = userName+":"+ui->edit1->text();

    //发送给服务器
    socket->write(msg.toLocal8Bit());
}
//断开服务器按钮对应的槽函数
void Widget::on_disconnectbtn_clicked()
{
    //告诉大家我走了
    QString msg =userName +":离开聊天室";
    socket->write(msg.toLocal8Bit());

    //断开连接
    socket->disconnectFromHost();

}

//disconnected信号对应槽函数的定义
void Widget::disconnected_slot()
{
    QMessageBox::information(this,"退出","退出成功");
}

ui界面

效果图

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

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

相关文章

便携式脑卒中检测仪是不是离现实不远了?

摘要&#xff1a;本文介绍一个轻量级人工智能的应用--基于tinyML的便携式低成本脑部微波成像系统。参考资料为DOI&#xff1a; 10.1109/ISCAS46773.2023.10181746 医疗资源从来都是稀缺资源。 我们都经历过在医院CT和核磁共振室外排队的情况。即使您万分紧急&#xff0c;也只能…

实验3.2 分期付款计算器

目录 实验目的‪‬‪‬‪‬‪‬‪‬‮‬‭‬‪‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‭‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‪‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‪‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‪‬ 实验内容‪‬‪‬‪‬‪‬‪‬‮‬‭‬‪‬‪‬‪‬…

【算法与数据结构】归并排序的代码实现(详细图解)以及master公式的讲解

目录 1、归并排序 1.1、算法描述 1.2、图解说明 2、代码实现 3、master公式 3.1、公式以及结论 3.2、适用于某些特殊的递归 3.3、计算归并排序的时间复杂度 1、归并排序 归并排序是建立在归并操作上的一种有效的排序算法。该算法是采用递归或者说是分治法&#xff08;Di…

基于SpringBoot的桂林旅游景点导游平台

目录 前言 一、技术栈 二、系统功能介绍 用户信息管理 景点类型管理 景点信息管理 线路推荐管理 用户注册 线路推荐 论坛交流 三、核心代码 1、登录模块 2、文件上传模块 3、代码封装 前言 随着信息技术在管理上越来越深入而广泛的应用&#xff0c;管理信息系统的实…

Unity基于种子与地块概率的开放世界2D地图生成

public class BuildingGen : MonoBehaviour {public int[] Building;//存储要生成的地块代码public int[] Probability;//存储概率public double seed;public int width 100;public int height 100;public float noiseScale 0.1f; //噪声缩放倍数private int[,] frequencyM…

基于Java的驾校收支管理可视化平台设计与实现(源码+lw+部署文档+讲解等)

文章目录 前言具体实现截图论文参考详细视频演示为什么选择我自己的网站自己的小程序&#xff08;小蔡coding&#xff09;有保障的售后福利 代码参考源码获取 前言 &#x1f497;博主介绍&#xff1a;✌全网粉丝10W,CSDN特邀作者、博客专家、CSDN新星计划导师、全栈领域优质创作…

揭秘亚马逊、ebay自养号测评底层环境防关联技术

今天珑哥讲的是纯人工的自养号方式&#xff0c;已经在做过的人应该都懂&#xff0c;实现自养号所使用的IP和浏览器都有哪些 &#xff1f;都会有哪些问题。 一&#xff1a;市面上的IP有哪些&#xff1f;会遇到的问题&#xff1f; 922、luminati、googelfi、TM流量卡、Rola&…

基于Matlab求解高教社杯数学建模竞赛(cumcm2010A题)-储油罐的变位识别与罐容表标定(附上源码+数据+题目)

文章目录 题目解题源码数据下载 题目 通常加油站都有若干个储存燃油的地下储油罐&#xff0c;并且一般都有与之配套的“油位计量管理系统”&#xff0c;采用流量计和油位计来测量进/出油量与罐内油位高度等数据&#xff0c;通过预先标定的罐容表&#xff08;即罐内油位高度与储…

CentOS 7 停止维护后如何平替你的生产系统?

Author&#xff1a;rab 目录 前言一、Debian 家族1.1 Debian1.2 Ubuntu 二、RHEL 家族2.1 Red Hat Enterprise Linux2.2 Fedora2.3 CentOS2.4 Rocky Linux2.5 AlmaLinux 三、如何选择&#xff1f;思考&#xff1f; 前言 CentOS 8 系统 2021 年 12 月 31 日已停止维护服务&…

NPDP产品经理知识(产品创新种的市场调研)

1. 复习产品设计与开发工具 创意生成&#xff1a; scamper也叫蹦蹦法 心智图就是思维导图&#xff1a;mindmaping 原型法--故事板&#xff1a;创意生成的时候做的 人种学--民族志 六顶思考帽&#xff1a;白色红色黑色蓝色。。。 概念设计&#xff1a; AOMI&#xff1a;卡…

BIRCH算法全解析:从原理到实战

目录 一、引言什么是BIRCH算法BIRCH算法的应用场景文章目标和结构概述 二、BIRCH算法基础CF&#xff08;Clustering Feature&#xff09;树的概念数据点簇簇的合并和分裂 BIRCH的时间复杂度和空间复杂度BIRCH vs K-means和其他聚类算法 三、BIRCH算法的技术细节CF树的构建节点和…

潮流来袭!中国首届虚拟艺术巡展NFS将在广州YCC!天宜盛大开启!

中国首届虚拟艺术巡展 NFT Showcase (NFS) 即将来袭&#xff0c;本活动由 Web3 营销公司 Beep Crypto 精心策划&#xff0c;将于 10 月 5 日至 10 月 17 日在广州潮流策展空间 YCC!天宜举行。 活动的主题围绕虚拟时尚展开&#xff0c;汇聚了一系列令人激动的展品&#xff0c;涵…

【Java】抽象类

目录 概述&#xff1a; 示例代码&#xff1a; 抽象类特点 示例代码&#xff1a; 概述&#xff1a; 在Java中&#xff0c;一个没有 方法体 的方法应该定义为 抽象方法&#xff0c;而类中如果有 抽象方法&#xff0c;该类必须定义为抽象类。 抽象类和抽象方法用 abstract 关键…

基于Java的志愿者活动宣传管理系统设计与实现(源码+lw+部署文档+讲解等)

文章目录 前言具体实现截图论文参考详细视频演示为什么选择我自己的网站自己的小程序&#xff08;小蔡coding&#xff09;有保障的售后福利 代码参考源码获取 前言 &#x1f497;博主介绍&#xff1a;✌全网粉丝10W,CSDN特邀作者、博客专家、CSDN新星计划导师、全栈领域优质创作…

再来介绍另一个binlog文件解析的第三方工具my2sql

看腻了文字就来听听视频演示吧&#xff1a;https://www.bilibili.com/video/BV1rp4y1w74B/ github项目&#xff1a;https://github.com/liuhr/my2sql gitee链接&#xff1a;https://gitee.com/mirrors/my2sql my2sql go版MySQL binlog解析工具&#xff0c;通过解析MySQL bin…

vertx的学习总结7

这里我就简单的聊几句&#xff0c;如何用vertx web来搞一个web项目的 1、首先先引入几个依赖&#xff0c;这里我就用maven了&#xff0c;这个是kotlinvertx web <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apac…

Linux基本指令介绍系列第四篇

文章目录 前言一、Linux基本指令介绍1、more指令2、less指令3、head指令4、tail指令5、bc指令6、管道文件介绍7、与时间相关的指令 总结 前言 本文介绍Linux使用时的部分指令&#xff0c;读者如果想了解更多基本指令的使用&#xff0c;可以关注博主的后续的文章。 博主使用的实…

基于Java的在线听书网站设计与实现(源码+lw+部署文档+讲解等)

文章目录 前言具体实现截图论文参考详细视频演示为什么选择我自己的网站自己的小程序&#xff08;小蔡coding&#xff09;有保障的售后福利 代码参考源码获取 前言 &#x1f497;博主介绍&#xff1a;✌全网粉丝10W,CSDN特邀作者、博客专家、CSDN新星计划导师、全栈领域优质创作…

阿里云服务器搭建网站(图文新手教程)

使用阿里云服务器快速搭建网站教程&#xff0c;先为云服务器安装宝塔面板&#xff0c;然后在宝塔面板上新建站点&#xff0c;阿里云服务器网以搭建WordPress网站博客为例&#xff0c;来详细说下从阿里云服务器CPU内存配置选择、Web环境、域名解析到网站上线全流程&#xff1a; …

【Zookeeper专题】Zookeeper特性与节点数据类型详解

目录 前言前置知识课程内容一、Zookeeper介绍二、Zookeeper快速开始2.1 Zookeeper安装2.2 客户端命令行操作2.3 GUI工具 三、Zookeeper数据结构3.1 ZNode节点分类3.2 ZNode状态信息3.3 监听机制详解3.3.1 永久性Watch 3.4 节点ZNode特性总结3.5 应用场景详解3.5.1 统一命名服务…