4.11作业

服务器端

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include<QTcpServer> //服务器端类
#include<QMessageBox> //消息对话框
#include<QTcpSocket> //客户端类
#include<QList> //链表容器

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

public slots:
    void newConnection_slot();
    void readyRead_slot();

private:
    Ui::Widget *ui;

    //实例化一个服务器指针
    QTcpServer *server;

    //定义一个存放客户端的容器
    QList<QTcpSocket *> socketList;

};
#endif // WIDGET_H

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

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)

    , server(new QTcpServer(this)) // 给服务器指针实例化空间

{
    ui->setupUi(this);
}

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

//启动服务器按钮对应的槽函数
void Widget::on_startBtn_clicked()
{
    //获取ui界面端口号
    quint16 port = ui->portEdit->text().toUInt(); //将字符串转换成整型

    //让服务器设置监听

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

   //程序运行到这,说明服务器监听成功,有客户端发来连接请求,
   //那么服务器端就会自动发射一个newconnection()信号
   //那么就可以将该信号连接到自定义的槽函数中,处理逻辑代码
   connect(server,&QTcpServer::newConnection,this,&Widget::newConnection_slot);


}

//newConnection信号对应的槽函数
void Widget::newConnection_slot()
{
    //获取最新连接客户端的套接字
   QTcpSocket *s = server->nextPendingConnection();

   //将套接字 放入链表容器中
   socketList.push_back(s);

   //此时,说明服务器与客户端成功建立连接,如果

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

//readyRead()信号对应槽函数
void Widget::readyRead_slot()
{
    //移除无效客户端
    for(int i=0;i<socketList.count();i++)
    {
        //判断客户端与服务器连接的状态
        if(socketList.at(i)->state() == 0)
        {
            //删除
            socketList.removeAt(i);
        }
    }

    //遍历容器,哪个有客户端有数据待读
    for(int i=0;i<socketList.count();i++)
    {
        //返回数据的大小:bytesAvailable()
        if(socketList.at(i)->bytesAvailable()>0)
        {
            //读取数据
           QByteArray msg = socketList.at(i)->readAll();
           //
           ui->listWidget->addItem(QString::fromLocal8Bit(msg));

           //将数据广播给所有客户端
           for(int j=0;j<socketList.count();j++)
           {
               socketList.at(j)->write(msg);
           }
        }
    }
}

客户端

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include<QTcpSocket>




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

    void on_disconnectBtn_clicked();

public slots:
    void connected_slot();
    void readyRead_slot();
    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)
    , socket(new QTcpSocket(this))

{
    ui->setupUi(this);

    //初始化界面
    ui->msgEdit->setEnabled(false);
    ui->sendBtn->setEnabled(false);
    ui->disconnectBtn->setEnabled(false);
    connect(socket,&QTcpSocket::connected,this,&Widget::connected_slot);

}

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

//连接按钮对应的槽函数处理
void Widget::on_connectBtn_clicked()
{
    //获取到ui界面上的ip和端口号
    QString ip = ui->ipEdit->text();

    quint16 port = ui->portEdit->text().toUInt();
    //客户端连接服务器
    socket->connectToHost(ip,port);



}
//connected对应槽函数
void Widget::connected_slot()
{
    //告诉服务器我来了
    //组织语言
    username = ui->usernameEdit->text();
    QString msg = username+":进入聊天室";
    //将数据发送给服务器
    socket->write(msg.toLocal8Bit());

    //程序运行到这意味着服务器与客户端成功建立连接
    ui->msgEdit->setEnabled(true);
    ui->sendBtn->setEnabled(true);
    ui->disconnectBtn->setEnabled(true);

    ui->usernameEdit->setEnabled(false);
    ui->portEdit->setEnabled(false);
    ui->connectBtn->setEnabled(false);

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

}
void Widget::readyRead_slot()

{
    //读取数据
    QByteArray msg = socket->readAll();

    //将读取到的数据放到ui界面上
    ui->listWidget->addItem(QString::fromLocal8Bit(msg));


}



//发送按钮对应的槽函数处理
void Widget::on_sendBtn_clicked()
{
    //获取Ui界面上的内容
    QString msg = ui->msgEdit->text();

    //组织语言
    msg = username + ":" + msg;
    socket->write(msg.toLocal8Bit());

    //清空内容
    ui->msgEdit->clear();

}

//断开与服务器连接的槽函数
void Widget::disconnected_slot()
{
    ui->msgEdit->clear();
    ui->sendBtn->setEnabled(false);
    ui->msgEdit->setEnabled(false);
    ui->disconnectBtn->setEnabled(false);
    ui->connectBtn->setEnabled(false);
}
//按下断开连接按钮的槽函数

void Widget::on_disconnectBtn_clicked()
{
    QString msg = username + "已退出聊天室";
    socket->write(msg.toLocal8Bit());
    socket->disconnectFromHost();
    connect(socket,&QTcpSocket::disconnected,this,&Widget::disconnected_slot);
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【JAVASE】抽象类和接口及其抽象类和接口的区别

✅作者简介&#xff1a;大家好&#xff0c;我是橘橙黄又青&#xff0c;一个想要与大家共同进步的男人&#x1f609;&#x1f609; &#x1f34e;个人主页&#xff1a;再无B&#xff5e;U&#xff5e;G-CSDN博客 目标&#xff1a; 1. 抽象类 2. 接口 3. Object 类 1. &am…

linux中rpm包与deb包的区别及使用

文章目录 1. rpm与deb的区别2. deb软件包的格式和使用2.1 deb软件包命令遵行如下约定2.2 dpkg命令2.3 apt-命令 3. Unix和Linux的区别Reference 1. rpm与deb的区别 有的系统只支持使用rpm包安装&#xff0c;有的只支持deb包安装&#xff0c;混乱安装会导致系统问题。 关于rpm和…

C语言——实践小游戏(贪吃蛇)代码版

大家好久不见&#xff0c;我是残念我回来了&#xff0c;希望在你看完之后&#xff0c;能对你有所帮助&#xff0c;有什么不足请指正&#xff01;共同学习交流 本文由&#xff1a;残念ing原创CSDN首发&#xff0c;如需要转载请通知 个人主页&#xff1a;残念ing-CSDN博客&#x…

Linux网络名称空间的调试方法全面分析

Linux网络名称空间是一种广泛使用的技术&#xff0c;用于隔离网络环境&#xff0c;特别是在容器化和微服务架构中&#x1f4e6;。然而&#xff0c;随着网络名称空间的广泛应用&#xff0c;开发者和系统管理员可能会遇到需要调试网络名称空间配置和性能的情况&#x1f50d;。本文…

智能驾驶的关键技术:自主泊车轨迹规划

智能驾驶的关键技术&#xff1a;自主泊车轨迹规划 搭载先进的车载传感器、控制器、执行器等装置&#xff0c;具备复杂环境感知、智能化决策等功能的车辆&#xff0c;我们称之其为智能车。智能车的车载决策规划模块用于生成车辆的行驶行为&#xff0c;直接体现车辆行驶的智慧水…

【Tars-go】腾讯微服务框架学习使用01--初始化服务

1 初始INIT-Demo运行 按照官网描述 go get 安装框架依赖 # < go 1.16 go get -u github.com/TarsCloud/TarsGo/tars/tools/tarsgo go get -u github.com/TarsCloud/TarsGo/tars/tools/tars2go # > go 1.16 go install github.com/TarsCloud/TarsGo/tars/tools/tarsgolat…

【网安小白成长之路】6.pkachu、sql-lbas、upload-lbas靶场搭建

&#x1f42e;博主syst1m 带你 acquire knowledge&#xff01; ✨博客首页——syst1m的博客&#x1f498; &#x1f51e; 《网安小白成长之路(我要变成大佬&#x1f60e;&#xff01;&#xff01;)》真实小白学习历程&#xff0c;手把手带你一起从入门到入狱&#x1f6ad; &…

python---3--sort、lambdalen(list1)、sorted_numbers = sorted(numbers)、list.sort()

学习目标&#xff1a; lambda len(list1) sorted_numbers sorted(numbers)list.sort() 目录 学习目标&#xff1a; 学习内容&#xff1a; 匿名函数 lambda表达式 lambda [参数]: 函数 不需要return len(list1) sorted_numbers sorted(numbers) list.sort(keyNone, r…

进程通信(管道)

个人主页&#xff1a;Lei宝啊 愿所有美好如期而遇 前言 两个进程直接可以进行数据的直接传递吗&#xff1f;答案显然是不可以。 为什么&#xff1f; 我们简单概括就是进程具有独立性&#xff0c;如果说有两个进程&#xff0c;第一个进程可以访问第二个进程的数据&#xff…

ssm“健康早知道”微信小程序

采用技术 ssm“健康早知道”微信小程序的设计与实现~ 开发语言&#xff1a;Java 数据库&#xff1a;MySQL 技术&#xff1a;SpringMVCMyBatis 工具&#xff1a;IDEA/Ecilpse、Navicat、Maven 需求分析 利用ssm、Java、MyEclipse和mysql数据库等知识点&#xff0c;结合相关设…

【CSDN创作优化2】内嵌图片 `<img>` 标签`height`和`width`属性

【CSDN创作优化2】内嵌图片 标签height和width属性 写在最前面<img> 标签简介控制图像尺寸&#xff1a;height和width属性实例为什么要指定height和width注意事项 使用百分比进行响应式设计小结 &#x1f308;你好呀&#xff01;我是 是Yu欸 &#x1f30c; 2024每日百字…

idea 配置各种背景颜色-护眼绿

idea 配置各种背景颜色 1、打开 IDEA 软件&#xff0c;点击左上角的【File】——>【Settings】 2、点击左侧栏中的【Editor】——>【Color Scheme】选项&#xff0c;点击右侧的【scheme】下拉选择你想要的颜色方案。 3、背景色设置护眼绿或其他特定颜色的背景&#xf…

scratch绘制五边形花朵 2024年3月中国电子学会图形化编程 少儿编程 scratch编程等级考试三级真题和答案解析

目录 scratch绘制五边形花朵 一、题目要求 1、准备工作 2、功能实现 二、案例分析 1、角色分析 2、背景分析 3、前期准备 三、解题思路 1、思路分析 2、详细过程 四、程序编写 五、考点分析 六、推荐资料 1、入门基础 2、蓝桥杯比赛 3、考级资料 4、视频课程…

训练营第二十天(二叉树 part06)

训练营第二十天&#xff08;二叉树 part06&#xff09; 654.最大二叉树 力扣题目地址(opens new window) 题目 给定一个不含重复元素的整数数组。一个以此数组构建的最大二叉树定义如下&#xff1a; 二叉树的根是数组中的最大元素。左子树是通过数组中最大值左边部分构造出…

C++模板初阶(个人笔记)

模板初阶 1.泛型编程2.函数模板2.1函数模板的实例化2.2模板参数的匹配规则 3.类模板3.1类模板的实例化 1.泛型编程 泛型编程&#xff1a;编写与类型无关的通用代码&#xff0c;是代码复用的一种手段。模板是泛型编程的基础。 //函数重载 //交换函数的逻辑是一致的&#xff0c…

Java 类加载过程

Java 类加载过程 类的生命周期类的加载过程加载验证准备解析初始化 类的生命周期 类的生命周期&#xff1a; 加载&#xff08;Loading&#xff09;— 验证&#xff08;Verification&#xff09;— 准备&#xff08;Preparation&#xff09;— 解析&#xff08;Resolution&#…

【ArcGIS微课1000例】0109:ArcGIS计算归一化水体指数(NDWI)

文章目录 一、加载数据二、归一化水体指数介绍三、归一化水体指数计算四、注意事项一、加载数据 加载配套数据0108.rar(本实验的数据与0108的一致)中的Landsat8的8个单波段数据,如下所示: Landsat8波段信息对照表如下表所示: 接下来学习在ArcGIS平台上,基于Landsat8数据…

贪心算法|763.划分字母区间

力扣题目链接 class Solution { public:vector<int> partitionLabels(string S) {int hash[27] {0}; // i为字符&#xff0c;hash[i]为字符出现的最后位置for (int i 0; i < S.size(); i) { // 统计每一个字符最后出现的位置hash[S[i] - a] i;}vector<int> …

前端开发攻略---利用Flexbox和Margin实现智能布局:如何巧妙分配剩余空间,让你的网页设计更上一层楼?

1、演示 2、flex布局 Flex布局是一种用于Web开发的弹性盒子布局模型&#xff0c;它可以让容器内的子元素在空间分配、对齐和排列方面具有更大的灵活性。以下是Flex布局的基本用法&#xff1a; 容器属性&#xff1a; display: flex;&#xff1a;将容器指定为Flex布局。flex-dire…

「每日跟读」英语常用句型公式 第9篇

「每日跟读」英语常用句型公式 第9篇 1. Go-to ___ 第一选择___ What’s your go-to snack when you’re hungry? (你饿的时候第一选择的零食是什么&#xff1f;) Who’s your go-to friend for advice? (你第一选择的朋友是谁来寻求建议&#xff1f;) Which is your go-t…