国庆作业day10.4

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

服务器

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();
    //监听客户端的链接请求
    if(!server->listen(QHostAddress::Any,port))
    {
        QMessageBox::information(this,"失败","监听失败");
        return;
    }else
    {
        QMessageBox::information(this,"成功","服务器启动成功");
    }
    //由于只需要链接一次即可将该链接放在构造函数中
    //函数原型

}
//自定义newConnection信号的槽函数的实现
void Widget::newConnection_slot()
{
    qDebug()<<"您有新的客户端发来链接请求了";
    //获取最新链接的客户端套接字
    QTcpSocket *s= server->nextPendingConnection();
    //将该套接字,放入客户端链表中
    clientList.push_back(s);
    //至此,多个客户端已经跟服务器建立链接,并放入客户端容器中了
    //此时,如果有客户端向服务器发来数
    //我们可以将该信号链接自定义的槽函数中,处理相关逻辑
    connect(s,&QTcpSocket::readyRead,this,&Widget::readyRead_solt);
}
//readyRead对应槽函数
void Widget::readyRead_solt()
{
    qDebug()<<"有新的客户端发来消息了";
    //遍历客户端链表,将无效的客户端移除
    for(int i=0;i<clientList.size();i++)
    {
        //判断当前套接字是否是有效连接
        //函数原型:SockentState state() const;
        //返回0是无效连接
       if( clientList[i]->state()==0)
       {
           //将该无效套接字移除
           clientList.removeAt(i);
       }

    }
    //遍历客户端链表查询是哪个客户端发来的信息
    for(int i=0;i<clientList.size();i++)
    {
        //函数原型
        //功能:求当前客户端套接字中待读数据的字节数
        //返回值0说明无数据可读
        if(clientList[i]->bytesAvailable()!=0)
        {
            //将该套接字中的数据读取出来
            QByteArray msg=clientList[i]->readAll();
            ui->msgWidget->addItem(QString::fromLocal8Bit(msg));
            for(int j=0;j<clientList.size();j++)
            {
                clientList[j]->write(msg);
            }
        }
    }
}
cpp 复制代码
#ifndef WIDGET_H
#define WIDGET_H
#include<QTcpServer>//服务器头文件
#include <QWidget>
#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();//自定义处理newconnet槽函数的申明
    void readyRead_solt();

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);
    //给客户端指针实例化对象
    socket =new QTcpSocket(this);
    connect(socket,&QTcpSocket::connected,this,&Widget::connect_slot);
    connect(socket,&QTcpSocket::readyRead,this,&Widget::readyRead_slot);
}

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

//连接服务器按钮对应的槽函数
void Widget::on_connectBtn_clicked()
{
    //将客户端连接到给定的服务器
    //1.服务器的主机地址,2端口号
    userName=ui->usernameEdit->text();//用户名
    QString ip=ui->ipEdit->text();//ip
    quint16 port=ui->portEdit->text().toUInt();//端口号
    socket->connectToHost(ip,port);
}
//
void Widget::connect_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->msgEdit->text();
    socket->write(msg.toLocal8Bit());
    ui->msgEdit->clear();
}
//断开服务器按钮
void Widget::on_disconnectBtn_clicked()
{
    QString msg=userName+":离开聊天室";
    socket->write(msg.toLocal8Bit());
    //断开连接
    //函数原型:virtual void disconnectFromHost()
    //connect(socket,&QTcpSocket::disconnected,this,&Widget::disconnected_slot);
    socket->disconnectFromHost();
}
void  Widget::disconnected_slot()
{
    QMessageBox::information(this,"提示","退出成功");
}
cpp 复制代码
#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 connect_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
相关推荐
hssfscv17 小时前
QT的学习笔记4——QMainWindow、资源文件以及主要控件的介绍
笔记·qt·学习
luoyayun36119 小时前
Qt + FFmpeg 音频工具:重采样实现
qt·ffmpeg·重采样
小短腿的代码世界2 天前
Qt Bluetooth源码深度解析:从HCI协议到跨平台API的完整架构
开发语言·qt·架构
小短腿的代码世界2 天前
Qt WebEngine多进程架构与IPC通信:从Chromium多进程到Qt信号槽融合
qt·架构·系统架构
尘中远2 天前
【Qwt 7.0 系列】快速入门与核心新特性概览 —— 更现代的 Qt 数据可视化库
qt·数据可视化·绘图·qwt·科学绘图
初阳7852 天前
【Qt】系统相关(3)——多线程
qt
初阳7852 天前
【Qt】系统相关(2)——文件
开发语言·qt
尘中远2 天前
【Qwt 7.0 系列】坐标轴与刻度系统 —— 刻度引擎、网格、图例与刻度朝内
qt·数据可视化·qcustomplot·qwt·工业软件·科学绘图
sycmancia3 天前
Qt——多线程间的互斥
开发语言·qt
尘中远3 天前
【Qwt 7.0 系列】常用图表类型实战 —— 柱状图、散点图、箱线图与直方图
qt·qwt·工业软件·科学绘图