QT创建聊天室

本文详细描述了如何在Ubuntu云服务器上部署服务器端应用,使用QT库的网络功能,并与运行在Windows系统的客户端进行通信,包括服务器监听、新连接处理和数据交换的过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一:服务器端部署在ubuntu云服务器上。

二:客户端软件运行在windows系统。

一、服务器端 

1.在项目的.pro文件里添加QT +=network。

dialog.h 

#ifndef DIALOG_H
#define DIALOG_H
#include <QTcpServer>
#include <QTcpSocket>
#include <QObject>
#include <QList>
class dialog:public QObject
{
    Q_OBJECT
public:
    dialog(QObject *parent=NULL);
private:
    QTcpServer *tcpserver;
    QTcpSocket *tcpsocket;
    QList <QTcpSocket*> tcpClientList;
private slots:
    void onNewConnection();
    void slotDataReceived();
};

#endif // DIALOG_H

dialog.cpp

#include "dialog.h"
#include <QByteArray>
//#pragma execution_character_set("utf-8")
#include <QHostInfo>
using namespace std;
dialog::dialog(QObject *parent):QObject (parent)
{
    tcpserver=new QTcpServer;
    QString name=QHostInfo::localHostName();
        QHostInfo ip=QHostInfo::fromName(name);
        QList<QHostAddress> alist=ip.addresses();
        //ip1=QHostAddress::Any;
        //ip=alist.at(0);
    if(tcpserver->listen(alist.at(0),6500))
    {
        qDebug("TCP服务器创建成功");
       // qDebug()<<alist.at(0).toString();
        for (int i=0;i<alist.count();i++) {
            qDebug()<<alist.at(i).toString();
        };
    }
    else
    {
         qDebug("TCP服务器创建失败");
         for (int i=0;i<alist.count();i++) {
             qDebug()<<alist.at(i).toString();
         };

    }
    connect(tcpserver,SIGNAL(newConnection()),this,SLOT(onNewConnection()));
}
void dialog::onNewConnection()
{
    tcpsocket=tcpserver->nextPendingConnection();
    tcpClientList.append(tcpsocket);
    qDebug("连接成功");
    connect(tcpsocket,SIGNAL(readyRead()),
                this,SLOT(slotDataReceived()));
}
void dialog::slotDataReceived()
{
    //遍历所有的客户端
    for(int i=0; i<tcpClientList.count(); i++){
        //检查当前客户端是否有数据到来
        if(tcpClientList.at(i)->bytesAvailable()){
            //接收客户端发送来的消息
            QByteArray readbuf =
                tcpClientList.at(i)->readAll();

    //遍历所有的客户端
    for(int i=0; i<tcpClientList.count(); i++){
            tcpClientList.at(i)->write(readbuf);
    }
    qDebug("send data successfully!");
        }}
}

main.cpp

#include <QCoreApplication>
#include <dialog.h>
int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);
    dialog d;
    return a.exec();
}

二、客户端

 1.在项目的.pro文件里添加QT +=network。

 

dialog.h 

#ifndef DIALOG_H
#define DIALOG_H
#include <QString>
#include <QDialog>
#include <QHostAddress>
#include <QTcpSocket>
#include <QMessageBox>
#pragma execution_character_set("utf-8")
QT_BEGIN_NAMESPACE
namespace Ui { class Dialog; }
QT_END_NAMESPACE

class Dialog : public QDialog
{
    Q_OBJECT

public:
    Dialog(QWidget *parent = nullptr);
    ~Dialog();
private slots:
    //发送消息,按钮的槽函数
    void on_sendButton_clicked();
    //连接服务器,按钮的槽函数
    void on_connectButton_clicked();

    //和服务器连接时调用的槽函数
    void onConnected(void);
    //和服务器断开连接调用的槽函数
    void onDisconnected(void);
    //接收聊天消息的槽函数
    void slotDataReceived(void);
    //网络异常处理的槽函数
    void slotSockError(QAbstractSocket::SocketError);





private:
    bool status;//标记客户端的连接状态,true在线,false离线
    QTcpSocket tcpSocket;//和服务器通信的套接字
    qint16 port;//服务器通信的端口
    QHostAddress serverIP;//服务器通信的IP地址
    QString userName;//聊天室的昵称
private:
    Ui::Dialog *ui;
};
#endif // DIALOG_H

dialog.cpp

#include "dialog.h"
#include "ui_dialog.h"

Dialog::Dialog(QWidget *parent)
    : QDialog(parent)
    , ui(new Ui::Dialog)
{
    ui->setupUi(this);
    status = false;//初始化连接状态
    //和服务器连接时发送connected信号
    connect(&tcpSocket,SIGNAL(connected()),
            this,SLOT(onConnected()));
    //断开连接发送disconnected信号
    connect(&tcpSocket,SIGNAL(disconnected()),
            this,SLOT(onDisconnected()));
    //当服务器发送数据过来时发送readyRead信号
    connect(&tcpSocket,SIGNAL(readyRead()),
            this,SLOT(slotDataReceived()));
    //网络异常,发送error
    connect(&tcpSocket,
        SIGNAL(error(QAbstractSocket::SocketError)),
        this,
        SLOT(slotSockError(QAbstractSocket::SocketError)));

}

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

void Dialog::on_connectButton_clicked()
{
    if(status == false){//当前没有连接,建立连接
        //从界面获取IP、用户名、PORT
        QString ip = ui->serverIpEdit->text();
        if(serverIP.setAddress(ip) == false){
            QMessageBox::information(
                        this,"错误","请输入正确的IP地址");
            return;
        }
        if(ui->userNameEdit->text() == ""){
            QMessageBox::information(
                        this,"错误","请输入用户名");
            return;
        }
        userName = ui->userNameEdit->text();

        if(ui->portEdit->text() == ""){
            QMessageBox::information(
                        this,"错误","请输入正确的端口");
            return;
        }
        port = ui->portEdit->text().toShort();
        //连接服务器
        tcpSocket.connectToHost(ip,port);
        status = true;//标记为在线状态
    }
    else{
        //发送下线消息
        QString msg = userName+":离开聊天室";
        tcpSocket.write(msg.toUtf8());
        //关闭和服务器的连接
        tcpSocket.disconnectFromHost();
        status = false;//标记为离线状态
    }
}
//和服务器连接时调用的槽函数
void Dialog::onConnected(void)
{
    //使能发送消息按钮
    ui->sendButton->setEnabled(true);
    //连接服务器 按钮文本改为 离开服务器
    ui->connectButton->setText(tr("离开服务器"));
    //禁用:ip port 用户名输入
    ui->serverIpEdit->setEnabled(false);
    ui->portEdit->setEnabled(false);
    ui->userNameEdit->setEnabled(false);
    //向服务器发送一条进入聊天室消息
    QString msg = userName+":进入聊天室";
//    tcpSocket.write(msg.toUtf8());
    tcpSocket.write(msg.toUtf8());
}

//和服务器断开连接调用的槽函数
void Dialog::onDisconnected(void)
{
    //禁用发送消息按钮
    ui->sendButton->setEnabled(false);
    //使能ip port 用户 输入
    ui->serverIpEdit->setEnabled(true);
    ui->portEdit->setEnabled(true);
    ui->userNameEdit->setEnabled(true);

    ui->connectButton->setText("连接服务器");
}

//接收聊天消息的槽函数
void Dialog::slotDataReceived(void)
{
    if(tcpSocket.bytesAvailable()){
        QByteArray buf;
        buf.resize(tcpSocket.bytesAvailable());
        tcpSocket.read(buf.data(),buf.size());
        //显示消息到界面
        QString msg = buf.data();
        ui->listWidget->addItem(msg);
    }
}
//网络异常处理的槽函数
void Dialog::slotSockError(
        QAbstractSocket::SocketError){
    QMessageBox::critical(this,"网络异常",
                          tcpSocket.errorString());
}


void Dialog::on_sendButton_clicked()
{
    //获取用户输入的消息
    if(ui->sendEdit->text() == ""){
        return;
    }
    QString msg = userName + ":" + ui->sendEdit->text();
    //发送消息到服务器
    tcpSocket.write(msg.toUtf8());
    //清空消息
    ui->sendEdit->clear();
}

main.cpp

#include "dialog.h"

#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    Dialog w;
    w.show();
    return a.exec();
}

 dialog.ui设计

服务器端不需要UI,客户端的设计只要把dialog.cpp复制到QT,那些有红色下划线的就是按键名字和编辑框名字,注意连接槽。 

serverIpEdit、userNameEdit、portEdit、sendButton、connectButton、listWidget、sendEdit

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值