qt TCP socket通信实例——网络聊天室

qt TCP socket通信实例——网络聊天室

说明:
数据的传输使用json,实现了一些基本的聊天功能,服务端的禁言功能,在线用户的显示功能,我会把源码放在下面,但是要提前说明的是这个网络聊天室有一些很迷惑的bug,而以本人目前的能力没有办法修复,所以请想要直接抄代码的同学谨慎一点
演示:

在这里插入图片描述

上面的ip是我的内网ip,其实填172.0.0.1就可以在任意的测试机器上达到图片上的效果
代码如下
服务端:
//mainwindown.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include<QTcpServer>
#include<QTcpSocket>
#include<QHostAddress>
#include<QDateTime>
#include<QString>
#include<QColor>
#include<QFontDialog>
#include<QLabel>
#include<QPoint>
#include<QFont>//想要实现字体和颜色的传输,但是后来放弃了
#include<QColorDialog>
#include<QFontDialog>
#include<QPushButton>
#include<QJsonValue>
#include<QJsonObject>
#include<QJsonDocument>
#include<QListWidget>

namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = 0);

    QList<QTcpSocket * > socketlist;
    QString name;
    QString message;
    QLabel * status;
    QLabel * perm;
    QTcpServer * server;

    void decode(const QByteArray &);
    void showmessage(const QString & str);
    void ini();
    bool speakable;
    int count;

    QByteArray encode(const QString & name,const QString & message);

    ~MainWindow();
private slots:
    void on_actionopen_triggered();
    void slo_newconnnection();
    void slo_disconnection();
    void slo_revmess();
    void on_sendButton_clicked();

    void on_actionclose_triggered();

    void on_clearbutton_clicked();

    void on_toolButton_clicked();

    void on_toolButton_2_clicked();

    void on_toolButton_3_clicked();

    void on_toolButton_4_clicked();
    void on_actionforbid_triggered();

private:
    Ui::MainWindow *ui;
};

#endif // MAINWINDOW_H

//mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include<qdebug.h>
MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    ini();
}

MainWindow::~MainWindow()
{
    delete ui;
}
void MainWindow::ini()
{
    status=new QLabel(QString::fromUtf8("欢迎"));
    perm= new QLabel(QString::fromUtf8("网络聊天室"));
    ui->statusBar->addWidget(status);
    ui->statusBar->addPermanentWidget(perm);
    ui->actionclose->setEnabled(false);
    ui->mess_rec->setReadOnly(true);
    speakable=true;

    count=0;
    ui->iplist->setRowCount(0);
}

void MainWindow::on_actionopen_triggered()
{
    ui->actionopen->setEnabled(false);
    ui->actionclose->setEnabled(true);
    server=new QTcpServer;
    server->listen(QHostAddress(ui->ipline->text()),ui->portline->text().toShort());
    connect(server,&QTcpServer::newConnection,this,&MainWindow::slo_newconnnection);
}

void MainWindow::showmessage(const QString & str)
{
    QDateTime time=QDateTime::currentDateTime();
    ui->mess_rec->append(time.toString("MM-dd hh:mm:ss")+" "+str);
}

void MainWindow::slo_newconnnection()
{

    QTcpSocket * socket=server->nextPendingConnection();

    connect(socket,&QTcpSocket::readyRead,this,&MainWindow::slo_revmess);
    connect(socket,&QTcpSocket::disconnected,this,&MainWindow::slo_disconnection);


}

void MainWindow::slo_disconnection()
{
    QTcpSocket * socket=qobject_cast<QTcpSocket *>(QObject::sender());
    QString tempname;
    socketlist.removeOne(socket);
    for(int c=0;c< ui->iplist->rowCount();c++)
    {
        if(socket->peerAddress().toString()==ui->iplist->item(c,1)->text())
        {
            QTableWidgetItem * temp1=ui->iplist->item(c,0);
            tempname=temp1->text();
            QTableWidgetItem * temp2=ui->iplist->item(c,1);
            ui->iplist->removeRow(c);
            delete temp1;
            delete temp2;
            break;
        }
    }

    showmessage(tempname+QString::fromUtf8("断开连接"));
    status->setText(QString::asprintf("当前%d人在线",socketlist.count()));
}

void MainWindow::slo_revmess()
{
    int c;
    QTcpSocket * socket=qobject_cast<QTcpSocket *>(QObject::sender());
    decode(socket->readAll());
    showmessage(name+":\n"+message);
    for(auto socket:socketlist)
    {
        socket->write(encode(name,message));
    }
    for(c=0;c< ui->iplist->rowCount();c++)
    {
        if(socket->peerAddress().toString()==ui->iplist->item(c,1)->text())
        {
            if(name!=ui->iplist->item(c,0)->text())
            {
                for(auto socket:socketlist)
                {
                    socket->write(encode(ui->iplist->item(c,0)->text(),QString::fromUtf8("改名为")+name));
                }
                showmessage(ui->iplist->item(c,0)->text()+QString::fromUtf8("改名为")+name);

                ui->iplist->item(c,0)->setText(name);
            }

            break;
        }
    }
    if(c==ui->iplist->rowCount())
    {
       socketlist<<socket;
        QTableWidgetItem * nameitem= new QTableWidgetItem(name);
        QTableWidgetItem * ipitem=new QTableWidgetItem(socket->peerAddress().toString());

        ui->iplist->setRowCount(count+1);
        ui->iplist->setItem(count,0,nameitem);
        ui->iplist->setItem(count,1,ipitem);
        showmessage(QString::fromUtf8("新用户")+name+QString::fromUtf8("连接"));
        for(auto socket:socketlist)
            {
                socket->write(encode(ui->nameline->text(),QString::fromUtf8("欢迎")+name+QString::fromUtf8("的到来")));
            }
        status->setText(QString::asprintf("当前%d人在线",count+1));
        count++;
    }
}

void MainWindow::on_sendButton_clicked()
{
    if(socketlist.isEmpty())
    {
        status->setText(QString::fromUtf8("没有用户连接进来,不要自言自语"));
    }
    else
    {
        for(auto socket:socketlist)
        {
            socket->write(encode(ui->nameline->text(),ui->mess_send->toPlainText().toUtf8()));
        }

        showmessage(ui->nameline->text()+QString::fromUtf8(":\n")+ui->mess_send->toPlainText());
    }
    ui->mess_send->clear();
}

void MainWindow::on_actionclose_triggered()
{
    server->close();
    ui->actionopen->setEnabled(true);
}

void MainWindow::on_clearbutton_clicked()
{
    ui->mess_send->clear();
}

void MainWindow::on_toolButton_clicked()
{
    QFont  font=ui->mess_send->font();
    font.setBold(!font.bold());
    ui->mess_send->setFont(font);
}

void MainWindow::on_toolButton_2_clicked()
{
    QColor  color=ui->mess_send->textColor();
    QColorDialog  dialog;
    dialog.setCurrentColor(color);
    dialog.exec();
    color=dialog.selectedColor();
    ui->mess_send->setTextColor(color);
}

void MainWindow::on_toolButton_3_clicked()
{
    QFont  font =ui->mess_send->font();
    QFontDialog  dialog ;
    dialog.setCurrentFont(font);
    dialog.exec();
    font=  dialog.selectedFont();
    ui->mess_send->setFont(font);
}


void MainWindow::on_toolButton_4_clicked()
{
    QFont  font =ui->mess_send->font();
    font.setUnderline(!font.underline());
    ui->mess_send->setFont(font);
}

void MainWindow::on_actionforbid_triggered()
{
    if(speakable==true)
    {
    showmessage(ui->nameline->text()+QString::fromUtf8("开启了全体禁言"));
    ui->actionforbid->setText(QString::fromUtf8("关闭全体禁言"));
    speakable=false;
    for(auto socket:socketlist)
    {
        socket->write(encode(ui->nameline->text(),QString::fromUtf8("开启了全体禁言")));
    }

    }
    else
    {
        speakable=true;
        showmessage(ui->nameline->text()+QString::fromUtf8("关闭了全体禁言"));
        ui->actionforbid->setText(QString::fromUtf8("开启全体禁言"));
        for(auto socket:socketlist)
        {
            socket->write(encode(ui->nameline->text(),QString::fromUtf8("开启了全体禁言")));
        }

    }
}

QByteArray MainWindow:: encode(const QString & name,const QString & message)
{
    QJsonObject object;
    QJsonDocument document;
    QFont font=ui->mess_send->font();
    QColor color=ui->mess_send->textColor();
    object.insert("name",QJsonValue(name));
    object.insert("message",QJsonValue(message));
    object.insert("speakable",QJsonValue(speakable));
    object.insert("isbold",QJsonValue(font.bold()));
    object.insert("isunderline",QJsonValue(font.underline()));
    object.insert("fontfamily",QJsonValue(font.family()));
    object.insert("fontweight",QJsonValue(font.weight()));
    object.insert("fontpoint",QJsonValue(font.pointSize()));
    object.insert("fontr",QJsonValue(color.red()));
    object.insert("fontg",QJsonValue(color.green()));
    object.insert("fontb",QJsonValue(color.blue()));
    object.insert("fonta",QJsonValue(color.alpha()));
    document.setObject(object);
    return document.toJson();
}
void MainWindow::decode(const QByteArray & raw)
{
    QJsonParseError error;
    QJsonDocument document=QJsonDocument::fromJson(raw,&error);

    if(error.error!=QJsonParseError::NoError)
    {
        qDebug()<<"json parsing error";
        qDebug()<<error.errorString();
    }
    else
    {
        QJsonObject object=document.object();
        QFont font=ui->mess_rec->font();
        QColor color=ui->mess_rec->textColor();
        name=object.value("name").toString();
        message=object.value("message").toString();
        font.setBold(object.value("isbold").toBool());
        font.setUnderline(object.value("isunderline").toBool());
        font.setFamily(object.value("fontfamily").toString());
        font.setWeight(object.value("fontweight").toInt());
        font.setPointSize(object.value("fontpoint").toInt());
        color.setRed( object.value("fontr").toInt());
        color.setGreen( object.value("fontg").toInt());
        color.setBlue( object.value("fontb").toInt());
        color.setAlpha( object.value("fonta").toInt());
        ui->mess_send->setFont(font);
        ui->mess_send->setTextColor(color);
    }
}

客户端
//cilent.h
#ifndef CLIENT_H
#define CLIENT_H

#include <QMainWindow>
#include<QTcpServer>
#include<QTcpSocket>
#include<QHostAddress>
#include<QDateTime>
#include<QString>
#include<QColor>
#include<QFontDialog>
#include<QLabel>
#include<QPoint>
#include<QFont>
#include<QColorDialog>
#include<QFontDialog>
#include<QJsonValue>
#include<QJsonObject>
#include<QJsonDocument>
#include<QListWidget>
#include<QFile>
#include <QByteArray>
namespace Ui {
class client;
}

class client : public QMainWindow
{
    Q_OBJECT

public:
    explicit client(QWidget *parent = 0);

    QLabel * status;
    QLabel * perm;
    QString name;
    QString message;
    void showmessage(const QString &);
    void ini();
    QTcpSocket * socket;
    bool speakable;
    ~client();
    QByteArray  encode(const QString & name,const QString & message);
    void decode(const QByteArray &);
private slots:
     void on_actionconnect_triggered();

     void on_actiondisconnect_triggered();

     void on_sendButton_clicked();
     void slo_messrec();

     void on_clearbutton_clicked();

     void on_toolButton_clicked();

     void on_toolButton_6_clicked();

     void on_toolButton_4_clicked();

     void on_toolButton_5_clicked();

private:
    Ui::client *ui;
};

#endif // CLIENT_H

//cilent.cpp
#include "client.h"
#include "ui_client.h"
client::client(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::client)
{
    ui->setupUi(this);
    ini();
    socket = new QTcpSocket;
}

client::~client()
{
    delete ui;
}
void client::showmessage(const QString & str)
{
    QDateTime time=QDateTime::currentDateTime();
    ui->mess_rec->append(time.toString("MM-dd hh:mm:ss")+" "+str);
}
void client::ini()
{
    status=new QLabel(QString::fromUtf8("欢迎"));
    perm= new QLabel(QString::fromUtf8("网络聊天室"));
    ui->statusBar->addWidget(status);
    ui->statusBar->addPermanentWidget(perm);
    ui->actiondisconnect->setEnabled(false);
    ui->mess_rec->setReadOnly(true);
    speakable=true;
}

void client::on_actionconnect_triggered()
{
    if(!ui->nameedit->text().isEmpty())
    {
        ui->actionconnect->setEnabled(false);
        ui->actiondisconnect->setEnabled(true);
        socket->connectToHost(QHostAddress(ui->ipline->text()),ui->portline->text().toShort());

        if(socket->state()==QTcpSocket::UnconnectedState)
        {
            status->setText(QString::fromUtf8("连接失败"));
            return;
        }
        else
        {
            status->setText(QString::fromUtf8("连接成功"));
        }
        connect(socket,&QTcpSocket::readyRead,this,&client::slo_messrec,Qt::UniqueConnection);
        socket->write(encode(ui->nameedit->text(),QString::fromUtf8("大家好")));
    }
    else
        status->setText("你必须要有一个用户名");
}
void client::slo_messrec()
{
    decode(socket->readAll());
    showmessage(name+":\n"+message);
}

void client::on_actiondisconnect_triggered()
{
    socket->close();
    ui->actionconnect->setEnabled(true);
    ui->actiondisconnect->setEnabled(false);
}

void client::on_sendButton_clicked()
{
    if(speakable)
    {


        socket->write(encode(ui->nameedit->text(),ui->mess_send->toPlainText()));
        status->setText(QString::fromUtf8("发送成功"));
        ui->mess_send->clear();
    }
    else
    {
        status->setText(QString::fromUtf8("你已经被禁言"));
    }
}

void client::on_clearbutton_clicked()
{
    ui->mess_send->clear();
}

void client::on_toolButton_clicked()
{
    QFont  font=ui->mess_send->font();
    font.setBold(!font.bold());
    ui->mess_send->setFont(font);
}

void client::on_toolButton_6_clicked()
{
    QColor  color=ui->mess_send->textColor();
    QColorDialog  dialog;
    dialog.setCurrentColor(color);
    dialog.exec();
    color=dialog.selectedColor();
    ui->mess_send->setTextColor(color);
}

void client::on_toolButton_4_clicked()
{
    QFont  font =ui->mess_send->font();
    QFontDialog  dialog ;
    dialog.setCurrentFont(font);
    dialog.exec();
    font=  dialog.selectedFont();
    ui->mess_send->setFont(font);
}

void client::on_toolButton_5_clicked()
{
    QFont  font =ui->mess_send->font();
    font.setUnderline(!font.underline());
    ui->mess_send->setFont(font);
}
void client::decode(const QByteArray & raw)
{
    QJsonParseError error;
    QJsonDocument document=QJsonDocument::fromJson(raw,&error);

    if(error.error!=QJsonParseError::NoError)
    {
        qDebug()<<"json parsing error";
        if(document.isEmpty())
            qDebug()<<"null";
    }
    else
    {
        QJsonObject object=document.object();
        QFont font=ui->mess_rec->font();
        QColor color=ui->mess_rec->textColor();
        name=object.value("name").toString();
        message=object.value("message").toString();
        font.setBold(object.value("isbold").toBool());
        font.setUnderline(object.value("isunderline").toBool());
        font.setFamily(object.value("fontfamily").toString());
        font.setWeight(object.value("fontweight").toInt());
        font.setPointSize(object.value("fontpoint").toInt());
        color.setRed( object.value("fontr").toInt());
        color.setGreen( object.value("fontg").toInt());
        color.setBlue( object.value("fontb").toInt());
        color.setAlpha( object.value("fonta").toInt());
        speakable=object.value("speakable").toBool();
        ui->mess_send->setFont(font);
        ui->mess_send->setTextColor(color);
    }
}
QByteArray client::encode(const QString & name,const QString & message)
{
    QJsonObject object;
    QJsonDocument document;
    QFont font=ui->mess_send->font();
    QColor color=ui->mess_send->textColor();
    object.insert("name",QJsonValue(name));
    object.insert("message",QJsonValue(message));
    object.insert("speakable",QJsonValue(speakable));
    object.insert("isbold",QJsonValue(font.bold()));
    object.insert("isunderline",QJsonValue(font.underline()));
    object.insert("fontfamily",QJsonValue(font.family()));
    object.insert("fontweight",QJsonValue(font.weight()));
    object.insert("fontpoint",QJsonValue(font.pointSize()));
    object.insert("fontr",QJsonValue(color.red()));
    object.insert("fontg",QJsonValue(color.green()));
    object.insert("fontb",QJsonValue(color.blue()));
    object.insert("fonta",QJsonValue(color.alpha()));
    document.setObject(object);
    return document.toJson();
}

源码度盘链接 提取码335x

  • 7
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
本课程详细、全面地介绍了 Qt 开发中的各个技术细节,并且额外赠送在嵌入式端编写Qt程序的技巧。整个课程涵盖知识点非常多,知识模块囊括 Qt-Core 组件、QWidgets、多媒体、网络、绘图、数据库,超过200个 C++ 类的分析和使用,学完之后将拥有 Qt 图形界面开发的非常坚实的功底。 每个知识点不仅仅会通过视频讲解清楚,并且会配以精心安排的实验和作业,用来保证学习过程中切实掌握核心技术和概念,通过实验来巩固,通过实验来检验,实验与作业的目的是发现问题,发现技术盲点,通过答疑和沟通夯实技术技能。注意:本套视频教程来源于线下的实体班级,因此视频中有少量场景对话和学生问答,对此比较介意的亲们谨慎购买。注意:本套视频教程包含大量课堂源码,包含对应每个知识点的精心编排的作业。由于CSDN官方规定在课程介绍中不能出现作者的联系方式,因此在这里无法直接给出QQ答疑号,视频中的源码、资料和作业文档链接统一在购买后从CSDN平台跟我沟通,我会及时回复跟进。注意:本套视频教程包含全套10套作业题,覆盖所有视频知识点,循序渐进,各个击破,作业总纲如下:下面是部分作业题目展示,每道题都有知识点说明,是检验学习效果的一大利器:(部分作业展示,为了防止盗图盗题对题干做了模糊处理)(部分作业展示,为了防止盗图盗题对题干做了模糊处理)(部分作业展示,为了防止盗图盗题对题干做了模糊处理)(部分作业展示,为了防止盗图盗题对题干做了模糊处理)(部分作业展示,为了防止盗图盗题对题干做了模糊处理)…… ……

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值