思维导图
基于QT的网络聊天室
widget.h
#ifndef WIDGET_H
#define WIDGET_H#include <QWidget>
#include<QTcpServer> //服务器类
#include<QTcpSocket> //客户端类
#include<QMessageBox> //对话框类
#include<QList> //链表容器
#include<QDebug> //信息调试类QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACEclass Widget : public QWidget
{Q_OBJECTpublic:Widget(QWidget *parent = nullptr);~Widget();private slots:void on_startBtn_clicked();void newConnection_slot(); //服务器发出的newConnection信号对应的处理槽函数void read_slot(); //服务器将数据发送至客户端界面上的处理槽函数private:Ui::Widget *ui;//声明一个服务器指针QTcpServer *sever;//定义存储客户端容器QList<QTcpSocket*> socket_list;};
#endif // WIDGET_H
widget.cpp
#include "widget.h"
#include "ui_widget.h"Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);//实例化服务器指针sever = new QTcpServer(this);
}Widget::~Widget()
{delete ui;
}//启动按钮对应的槽函数
void Widget::on_startBtn_clicked()
{//获取ui界面上的端口信息qint16 port = ui->portEdit->text().toUInt();if(ui->startBtn->text() == "取消"){QMessageBox::information(this,"","即将关闭客户端");this->close();}//设置监听if(sever->listen(QHostAddress::Any,port)){ //有客户端发起连接请求QMessageBox::information(this,"","服务器已启动");ui->startBtn->setText("取消");}connect(sever,&QTcpServer::newConnection,this,&Widget::newConnection_slot);}//服务器发出的newConnection信号对应的处理槽函数
void Widget::newConnection_slot(){//获取最新连接的客户端套接字//函数原型:virtual QTcpSocket *nextPendingConnection();//功能:获取最新连接客户端的套接字//参数:无//返回值:套接字指针QTcpSocket *s = sever->nextPendingConnection();socket_list.push_back(s); //将s存入客户端容器中//此时,客户端与服务器已经建立起来连接//如果有客户端向服务器发来数据,那么该客户端会自动发射一个readyRead信号//我们可以在该信号对应的槽函数中,读取客户端中的数据connect(s,&QTcpSocket::readyRead,this,&Widget::read_slot);
}void Widget::read_slot()
{//判断当前客户端是否在连接中for (int i = 0;i < socket_list.count();i++) {//socketList.at(i)->state(); //任意一个客户端的状态//函数原型:SocketState state() const;//功能:返回套接字的状态//参数:无//返回值:套接字状态,是个枚举值,如果为0,表示无效连接if(socket_list.at(i)->state() == 0){ //枚举值为0表示不在连接中socket_list.removeAt(i); //从容器中删除}}//判断客户端容器中是否有待读取的数据for (int i = 0;i < socket_list.count();i++) {//判断当前套接字是否有数据待读//函数原型:qint64 bytesAvailable() const override;//功能:求出当前套接字中待读数据的个数//参数:无//返回值:待读数据的个数if(socket_list.at(i)->bytesAvailable() != 0){ //表明有数据待读取//说明当前套接字中有数据//读取当前套接字中的数据//函数原型:QByteArray readAll();//功能:读取套接字中的所有数据//参数:无//返回值:QByteArray读取下来的数据QByteArray msg = socket_list.at(i)->readAll();//将数据展示到ui界面---QString::fromLocal8Bit() <=> inet_ntoa( )ui->listWidget->addItem(QString::fromLocal8Bit(msg));//-->字节序列(采用本地的8位编码)转换为字符序列//将数据展示给用户for (int j = 0;j < socket_list.count();j++) {socket_list.at(j)->write(msg);}}}
}
main.cpp
#include "widget.h"#include <QApplication>int main(int argc, char *argv[])
{QApplication a(argc, argv);Widget w;w.show();return a.exec();
}