QT TCP聊天室

这个博客介绍了如何使用QTcpServer和QTcpSocket在C++中构建一个简单的多人聊天室应用。服务器端负责监听连接、接收和广播消息,客户端则用于连接服务器、发送和接收消息。通过QTcpServer的newConnection和readyRead信号以及QTcpSocket的槽函数,实现了客户端之间的消息传递。
摘要由CSDN通过智能技术生成

服务器

.h

#ifndef CHATSERVER_H
#define CHATSERVER_H

#include <QMainWindow>
#include <QTcpServer>
#include <QTcpSocket>
#include <QList>
#include <QDebug>

QT_BEGIN_NAMESPACE
namespace Ui { class ChatServer; }
QT_END_NAMESPACE

class ChatServer : public QMainWindow
{
    Q_OBJECT

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

    void send(QString mes);

private slots:
    void on_pushButton_clicked();

    void on_newConnection_slot();

    void on_readyRead_slsot();

private:
    Ui::ChatServer *ui;

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

    //定义一个客户端指针,存放连接的客户端
    QList<QTcpSocket *> socketList;

};
#endif // CHATSERVER_H

.cpp

#include "chatserver.h"
#include "ui_chatserver.h"

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

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

}

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

//启动服务器
void ChatServer::on_pushButton_clicked()
{
    quint16 port = quint16(ui->portEdit->text().toInt());

    //将服务器设置为监听状态
    if(server->listen(QHostAddress::Any, port))
    {
        qDebug()<<"服务器创建成功";
    }else{
        qDebug()<<"服务器创建失败";
    }

    //将相应控件设置为不可用
    ui->portEdit->setEnabled(false);
    ui->pushButton->setEnabled(false);

    //有新客户端连接到服务器后,发送一个newConnecttion信号
    connect(server, &QTcpServer::newConnection, this, &ChatServer::on_newConnection_slot);
}

void ChatServer::on_newConnection_slot()
{
    QTcpSocket *socket = server->nextPendingConnection();

    //将套接字放图套接字链表中
    socketList.append(socket);

    connect(socket, &QTcpSocket::readyRead, this, &ChatServer::on_readyRead_slsot);
}

void ChatServer::on_readyRead_slsot()
{
    //判断客户端套接字是否有效,无效则移除
    for(int i=0; i<socketList.count(); i++)
    {
        if(socketList.at(i)->state() == false)
        {
            socketList.removeAt(i);
        }
    }

    //遍历客户链表,判断是哪个客户端发送的消息
    for(quint16 i=0; i<socketList.count(); i++)
    {
        if(socketList.at(i)->bytesAvailable())
        {
            //获取客户端传来的数据
            QString mes = QString::fromLocal8Bit(socketList.at(i)->readAll());

            //将消息展示到list widget上
            ui->listWidget->addItem(mes);

            //把该消息广播出去
            send(mes);
        }
    }
}

//自定义发送消息函数
void ChatServer::send(QString mes)
{
    for(int i=0; i<socketList.count(); i++)
    {
        socketList.at(i)->write(mes.toLocal8Bit());
    }
}

客户端

.h

#ifndef CHATCLIENT_H
#define CHATCLIENT_H

#include <QMainWindow>
#include <QTcpSocket>
#include <QHostAddress>
#include <QKeyEvent>

QT_BEGIN_NAMESPACE
namespace Ui { class chatclient; }
QT_END_NAMESPACE

class chatclient : public QMainWindow
{
    Q_OBJECT

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

private slots:
    void on_connectBtn_clicked();

    void on_connected_slot();

    void on_disconnected_slot();

    void on_readyRead_slot();

    void on_sendBtn_clicked();

protected:

    //键盘事件
    virtual void keyPressEvent(QKeyEvent *event);

private:
    Ui::chatclient *ui;

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

    //定义用户名
    QString userName;

    //定义bool类型数据,表示连接状态
    bool *isOK;


};
#endif // CHATCLIENT_H

.cpp

#include "chatclient.h"
#include "ui_chatclient.h"

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

    //实例化socket
    socket = new QTcpSocket(this);

    //给连接状态初始值
    *isOK = false;

    //将connected信号连接到自定义的槽函数
    connect(socket, &QTcpSocket::connected, this, &chatclient::on_connected_slot);

    //将disconnected信号连接到自定义的槽函数
    connect(socket, &QTcpSocket::disconnected, this, &chatclient::on_disconnected_slot);

    //当客户端接收到服务器发送的消息后,触发一个readyRead信号,才对应的槽函数中处理逻辑
    connect(socket, &QTcpSocket::readyRead, this, &chatclient::on_readyRead_slot);

}

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

//连接服务器
void chatclient::on_connectBtn_clicked()
{
    QString ip = ui->ipEdit->text();
    quint16 port = quint16(ui->portEdit->text().toInt());

    //判断连接状态
    if(*isOK == false)
    {
        //连接服务器
        socket->connectToHost(QHostAddress(ip), port);
        //连接成功,触发一个connected信号,在对应槽函数中处理逻辑

    }else {
        userName = ui->userNameEdit->text();
        QString mes = userName + "离开群聊";

        socket->write(mes.toLocal8Bit());
        //断开服务器
        socket->disconnectFromHost();

    }

}

//connected信号槽函数,连接服务器
void chatclient::on_connected_slot()
{

    //改变将按钮文本
    ui->connectBtn->setText("断开连接");
    *isOK = true;

    userName = ui->userNameEdit->text();
    QString mes = userName + "加入群聊";

    socket->write(mes.toLocal8Bit());   //告诉服务器我来了

    ui->sendBtn->setEnabled(true);
    ui->userNameEdit->setEnabled(false);
    ui->ipEdit->setEnabled(false);
    ui->portEdit->setEnabled(false);
    ui->connectBtn->setStyleSheet(QString("background-color: rgb(255,0,0);border-radius:25px"));

}

//disconnected信号槽函数,断开服务器
void chatclient::on_disconnected_slot()
{
    ui->listWidget->addItem("与服务器断开连接");

    //改变将按钮文本
    ui->connectBtn->setText("连接服务器");
    *isOK = false;

    ui->sendBtn->setEnabled(false);
    ui->userNameEdit->setEnabled(true);
    ui->ipEdit->setEnabled(true);
    ui->portEdit->setEnabled(true);
    ui->connectBtn->setStyleSheet(QString("background-color: rgb(0,170,255);border-radius:25px"));

}

//readyRead信号槽函数,接收消息
void chatclient::on_readyRead_slot()
{
    //获取套接字中的数据
    QString mes = QString::fromLocal8Bit(socket->readAll());

    //将数据显示在list widget中
    ui->listWidget->addItem(mes);
}

void chatclient::on_sendBtn_clicked()
{
    userName = ui->userNameEdit->text();
    QString mes = userName + " : " + ui->mesEdit->text();

    //将数据发送给服务器
    socket->write(mes.toLocal8Bit());

    ui->mesEdit->clear();
}

void chatclient::keyPressEvent(QKeyEvent *event)
{
    if(event->key() == Qt::Key_Enter || event->key() == Qt::Key_Return);
    {
        on_sendBtn_clicked();
    }
}

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值