10.4 小任务

news2024/12/26 23:04:35

目录

QT实现TCP服务器客户端搭建的代码,现象

TCP服务器

.h文件

.cpp文件

现象

TCP客户端

.h文件

.cpp文件

现象


QT实现TCP服务器客户端搭建的代码,现象

TCP服务器

.h文件

#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();   //自定义处理newconnect信号的槽函数声明

    void readyRead_slot();      //自定义处理readyRead信号的槽函数的声明

private:
    Ui::Widget *ui;

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

    //定义客户端容器  是个链表
    QList<QTcpSocket *> clientList;




};
#endif // WIDGET_H

.cpp文件

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

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

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

    connect(server,&QTcpServer::newConnection,this,&Widget::newConnection_slot);

}

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


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

    //监听客户端的连接请求
    //bool listen(const QHostAddress &address = QHostAddress::Any, quint16 port = 0);

    if(!server->listen(QHostAddress::Any,port))
    {
        QMessageBox::information(this,"失败","监听失败");
        return ;
    }else {
        QMessageBox::information(this,"成功","服务器启动成功");
    }

}

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

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

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

    connect(s,&QTcpSocket::readyRead,this,&Widget::readyRead_slot);

}

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

    //遍历客户端链表,将无效的客户端溢出
    for(int i=0;i<clientList.size();i++)
    {
        //判断当前套接字是否是有效连接
        if(0==clientList[i]->state())
        {
            //如果是0,表示该套接字为无效连接
            //将该套接字移除链表
            clientList.removeAt(i);
        }
    }

    //遍历客户端链表,判断是哪个客户端发来的数据
    for(int i=0;i<clientList.size();i++)
    {
        //函数原型
        if(0!=clientList[i]->bytesAvailable())
        {
            //将该套接字中的数据读取出来
            QByteArray msg=clientList[i]->readAll();

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

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


}



现象

TCP客户端

.h文件

#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();

    void connected_slot();   //自定义处理connect信号的槽函数的声明

    void readyRead_slot();     //自定义处理readyRead信号的槽函数的声明

    void on_sendBtn_clicked();

    void on_disconnectBtn_clicked();

    void disconnected_slot();   //自定义处理disconnect信号的槽函数声明

private:
    Ui::Widget *ui;

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

    //定义字符串接受用户
    QString userName;

};
#endif // WIDGET_H

.cpp文件

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

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

    //给客户端指针实例化对象
   socket=new QTcpSocket (this);

   connect(socket,&QTcpSocket::connected,this,&Widget::connected_slot);    //

   //如果服务器向客户端发来消息,那么该客户端就会自动发射一个readyRead信号
   //我们可
   connect(socket,&QTcpSocket::readyRead,this,&Widget::readyRead_slot);

   //断开
   connect(socket,&QTcpSocket::disconnected,this,&Widget::disconnected_slot);

    ui->msgEdit->setEnabled(false);  //设置消息编辑器不可用

}

static int flag=0;

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

//连接服务器按钮对应的槽函数
void Widget::on_connectBtn_clicked()
{
    //判断现在有没有连接上
    if(flag==1)
    {
        //已经连接了不需要再次连接
        QMessageBox::information(this,"提示","已连接状态");
        return;
    }

    //获取ui界面上的相关信息
    userName=ui->userNameEdit->text();   //获取用户名
    QString ip=ui->ipEdit->text();      //主机地址
    quint16 port=ui->portEdit->text().toUInt();   //端口号

    //函数原型 virtual void connectToHost(const QHostAddress &address, quint16 port, OpenMode mode = ReadWrite);
    //功能,将客户端连接到给定的服务器
    //参数1,端口号 参数2,端口号
    socket->connectToHost(ip,port);

    flag=1;

    //此时已经像服务器发送连接请求了 ,如果成功连接服务器,那么该客户端会自动发射一个connected的信号
    ui->msgEdit->setEnabled(true);  //设置消息编辑器可用
    ui->ipEdit->setEnabled(false);   //设置ip编辑器不可用
    ui->portEdit->setEnabled(false);   //设置端口号编辑器不可用
    ui->userNameEdit->setEnabled(false);   //设置用户编辑器不可用

}

//处理connect信号的槽函数的定义
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()
{
    //判断现在有没有连接上
    if(flag==0)
    {
        //现在都没连接上发送给谁?
        QMessageBox::information(this,"提示","现在没有连接的服务器,发送失败");
        return;
    }

    //获取ui界面输入的内容
    QString msg=userName+ ":"+ui->msgEdit->text();

    //发送给服务器
    socket->write(msg.toLocal8Bit());
}

//断开服务器按钮对应的槽函数
void Widget::on_disconnectBtn_clicked()
{
    //判断现在有没有连接上
    if(flag==0)
    {
        //现在都没连接上断开个der
        QMessageBox::information(this,"提示","现在没有连接的服务器,无需断开");
        return;
    }

    //告诉大家我走了
    QString msg=userName +":离开聊天室";
    socket->write(msg.toLocal8Bit());

      ui->msgEdit->setEnabled(false);  //设置消息编辑器不可用
      flag=0;
    //断开连接
    //无参无返回值
    socket->disconnectFromHost();

    //当成功与服务器断开连接后
    //该客户端会自动发射一个disconnected的信号
    //将他绑定到我们自定义的槽函数中,由于该连接只需连接一次即可,放到构造函数中即可
}

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




现象

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

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

相关文章

智能合约漏洞,BEVO 代币损失 4.5 万美元攻击事件分析

智能合约漏洞&#xff0c;BEVO 代币损失 4.5 万美元攻击事件分析 一、事件背景 北京时间 2023 年 1 月 31 日&#xff0c;在 twitter 上看到这样一条消息&#xff1a; BEVO 代币被攻击&#xff0c;总共损失 45000 美元&#xff0c;导致 BEVO 代币的价格下跌了 99%。 有趣的是…

编程新手?跟着这个教程,用Python画出小猪佩奇

小猪佩奇是许多小朋友们的心头好&#xff0c;它的形象可爱、颜色鲜艳。你知道吗&#xff0c;只需要Python中的一个简单模块&#xff0c;我们就可以自己绘制出这个可爱的形象&#xff01;本文将教你如何使用Python的turtle模块&#xff0c;一步步画出小猪佩奇。 1. 准备工作&a…

当我们做后仿时我们究竟在仿些什么(四)

就像人类容易接受自然数&#xff0c;但对于负数缺乏某种直觉上的认识一样&#xff1b;后仿过程中经常出现的 Negative Delay 和 Negative Timing Check 也非常容易使人困惑。 Warning-[SDFCOM_NICD] Negative INTERCONNECT Delay encountered今天这篇首先简要分析这些 Negativ…

创建线程池

如何创建线程池及处理相应任务 目录 如何创建线程池及处理相应任务线程池定义解决的问题(需求)工作原理实现线程池创建示意图重要构造器创建线程池(ExecutorService)线程池任务处理常用API处理Runnable任务处理Callable任务 使用工具类(Executors)创建线程池常用API应用案例 拓…

桌面自动化工具总结

引言:产品经理提出桌面程序需要自动化的测试,避免繁琐的人肉点击。说干就干。 现有自动化工具是五花八门,我找了两个框架。 这两个框架都是基于微软的UIA 框架,链接地址 https://learn.microsoft.com/en-us/windows/win32/winauto/uiauto-providerportal?source=recommen…

以太网的MAC层

以太网的MAC层 一、硬件地址 ​ 局域网中&#xff0c;硬件地址又称物理地址或MAC地址&#xff08;因为用在MAC帧&#xff09;&#xff0c;它是局域网上每一台计算机中固化在适配器的ROM中的地址。 ​ 关于地址问题&#xff0c;有这样的定义&#xff1a;“名字指出我们所要寻…

【Spring】Bean作用域和生命周期

Bean作用域和生命周期 一. Bean 的作用域1. Bean 的 6 种作⽤域&#xff1a;①. singleton②. prototype③. request④. session⑤. application⑥. websocket单例作用域(singleton) VS 全局作⽤域(application) 2. 设置作用域 二. Spring 执行流程和 Bean 的生命周期1. Spring…

MySQL优化、锁、总结常见问题

慢 SQL 如何定位呢&#xff1f; 慢 SQL 的监控主要通过两个途径&#xff1a; 慢查询日志&#xff1a;开启 MySQL 的慢查询日志&#xff0c;再通过一些工具比如 mysqldumpslow 去分析对应的慢查询日志&#xff0c;当然现在一般的云厂商都提供了可视化的平台。服务监控&#xf…

如何实现torch.arange的tensor版本

文章目录 背景实现方案不可行的情况 背景 import torch我们都知道&#xff0c;torch.arange只支持数字&#xff0c;不支持tensor&#xff0c;如下&#xff1a; torch.arange(0,5,1)tensor([0, 1, 2, 3, 4]) 但是如果使用tensor&#xff0c;就会报错&#xff1a; torch.arang…

SpringBoot结合Redisson实现分布式锁

&#x1f9d1;‍&#x1f4bb;作者名称&#xff1a;DaenCode &#x1f3a4;作者简介&#xff1a;啥技术都喜欢捣鼓捣鼓&#xff0c;喜欢分享技术、经验、生活。 &#x1f60e;人生感悟&#xff1a;尝尽人生百味&#xff0c;方知世间冷暖。 &#x1f4d6;所属专栏&#xff1a;Sp…

力扣 -- 474. 一和零(二维费用的背包问题)

解题步骤&#xff1a; 参考代码&#xff1a; 未优化代码&#xff1a; class Solution { public:int findMaxForm(vector<string>& strs, int m, int n) {//开一个三维的dp表vector<vector<vector<int>>> dp(strs.size()1,vector<vector<in…

DevEco Studio如何安装中文插件

首先 官网下载中文插件 由于DevEco是基于IntelliJ IDEA Community的&#xff0c;所有Compatibility选择“IntelliJ IDEA Community”&#xff0c;然后下载一个对应最新的就ok了。 最后打开Plugins页面&#xff0c;点击右上角齿轮 -> Install Plugin from Disk…。选择下载的…

AcWing算法提高课-5.6.1同余方程

宣传一下 算法提高课整理 CSDN个人主页&#xff1a;更好的阅读体验 原题链接 题目描述 求关于 x x x 的同余方程 a x ≡ 1 ( m o d b ) ax ≡ 1 \pmod b ax≡1(modb) 的最小正整数解。 输入格式 输入只有一行&#xff0c;包含两个正整数 a , b a,b a,b&#xff0c;用一…

python模拟表格任意输入位置

在表格里输入数值&#xff0c;要任意位置&#xff0c;我找到了好方法&#xff1a; input输入 1. 行 2. 列输入&#xff1a;1 excel每行输入文字input输入位置 3.2 表示输入位置在&#xff1a;3行个列是要实现一个类似于 Excel 表格的输入功能&#xff0c;并且希望能够指定输入…

怎么通过docker/portainer部署vue项目

这篇文章分享一下今天通过docker打包vue项目&#xff0c;并使用打包的镜像在portainer上部署运行&#xff0c;参考了vue-cli和docker的官方文档。 首先&#xff0c;阅读vue-cli关于docker部署的说明 vue-cli关于docker部署的说明https://cli.vuejs.org/guide/deployment.html#…

智慧工地源代码 SaaS模式云平台

伴随着技术的不断发展&#xff0c;信息化手段、移动技术、智能穿戴及工具在工程施工阶段的应用不断提升&#xff0c;智慧工地概念应运而生&#xff0c;庞大的建设规模催生着智慧工地的探索和研发。 什么是智慧工地&#xff1f; 伴随着技术的不断发展&#xff0c;信息化手段、移…

八、动态规划(Dynamic Programming)

文章目录 一、理论基础二、题目分类&#xff08;一&#xff09;基础题目2.[70.爬楼梯](https://leetcode.cn/problems/climbing-stairs/)&#xff08;1&#xff09;思路&#xff08;2&#xff09;代码&#xff08;3&#xff09;复杂度分析 3.[746. 使用最小花费爬楼梯](https:/…

正点原子嵌入式linux驱动开发——U-boot顶层Makefile详解

在学习uboot源码之前&#xff0c;要先看一下顶层Makefile&#xff0c;分析gcc版本代码的时候一定是先从顶层Makefile开始的&#xff0c;然后再是子Makefile&#xff0c;这样通过层层分析Makefile即可了解整个工程的组织结构。顶层Makefile也就是uboot根目录下的Makefile文件&am…

怪兽智能推出3D数字人虚拟主播,实时动作捕捉赋能直播营销,打造全新营销场景

怪兽智能科技推出了数字人直播新功能——3D数字人虚拟主播&#xff0c;通过实时动作捕捉技术&#xff0c;为直播营销场景注入了全新的活力和创意。这一功能将为企业带来更加生动、鲜活的营销体验&#xff0c;助力品牌在竞争激烈的市场中占据优势。 传统的直播营销方式往往依赖于…

论文笔记:Contrastive Trajectory Similarity Learning withDual-Feature Attention

ICDE 2023 1 intro 1.1 背景 轨迹相似性&#xff0c;可以分为两类 启发式度量 根据手工制定的规则&#xff0c;找到两条轨迹之间基于点的匹配学习式度量 通过计算轨迹嵌入之间的距离来预测相似性值上述两种度量的挑战&#xff1a; 无效性&#xff1a; 具有不同采样率或含有噪…