Qt项目网络聊天室设计
时间:2022-07-23
本文章向大家介绍Qt项目网络聊天室设计,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
网络聊天室
Qt网络聊天室服务端
网络聊天室程序
- 基于TCP的可靠连接
(QTcpServer、QTcpSocket)
- 一个服务器,多个客户端
3. 服务器接收到某个客户端的请求以及发送信息,经服务器发给其它客户端 最终实现一个共享聊天内容的聊天室!
QTcpServer
提供一个TCP基础服务类 继承自QObject,这个类用来接收到来的TCP连接,可以指定TCP端口或者用QTcpServer自己挑选一个端口,可以监听一个指定的地址或者所有的机器地址。
QTcpServer的信号:
newConnection()//有新连接连接时触发该信号
配置
pro文件添加
QT += network
获取当前设备所有ip地址
枚举设备所有ip地址
QList<QHostAddress> ipList = QNetworkInterface::allAddresses();
QStringList addressStrList;
addressStrList.clear();
for(int index = 0;index<ipList.size();index++)
{
if(ipList.at(index).isNull()) continue; //如果地址为空,则去掉
QAbstractSocket::NetworkLayerProtocol protocol = ipList.at(index).protocol();
if(protocol != QAbstractSocket::IPv4Protocol) continue; //只取IPV4的地址
addressStrList.append(ipList.at(index).toString());
}
ui->comboBox_Address->addItems(addressStrList);
listen() close()
调用
listen()
来监听所有的连接 调用close()
来关闭套接字,停止对连接的监听。
如果监听有错误,serverError()
返回错误的类型。调用errorString()
来把错误打印出来
bool isListening() const
当服务端正在监听连接时候返回真,否则返回假
QString serverAddressStr = ui->comboBox_Address->currentText(); //获取服务器ip地址
quint16 port = ui->lineEdit_port->text().toInt(); //获取服务器端口
QHostAddress serverAddress = QHostAddress(serverAddressStr); //初始化协议族
if(mServer->isListening())
{
//在监听状态 取消监听
mServer->close();
}
else
{
//不在监听状态 开始监听
if(mServer->listen(serverAddress, port))
{
//监听成功
qDebug() << "Listen Ok!!";
}
else
{
//监听失败
QMessageBox::warning(this, "Tcp Server Listen Error", mServer->errorString());
}
}
当监听连接时候,可以调用serverAddress()
和serverPort()
来返回服务端的地址和端口。
newConnection()
每当一个newConnection新的客户端连接到服务端就会
发射信号newConnection()
调用nextPendingConnection()
来接受待处理的连接。返回一个连接的QTcpSocket()
,我们可以用这个返回的套接字和客户端进行连接
private slots:
void newConnectionSlot(); //新连接
//处理新连接客户端
connect(mServer, SIGNAL(newConnection()),this, SLOT(newConnectionSlot()));
void Widget::newConnectionSlot()
{
mClient = mServer->nextPendingConnection();
connect(mClient, SIGNAL(readyRead()),this, SLOT(readyReadSlot()));//接收消息
connect(mClient, SIGNAL(disconnected()),this, SLOT(disconnectedSlot()));//断开连接
}
SINGL
readyRead()
客户端有数据发送至服务端时触发该信号
connect(mClient, SIGNAL(readyRead()),this, SLOT(readyReadSlot())); //接收消息
isReadable
是否可读
readAll
读取客户端发送过来的全部信息
if(mClient->isReadable())
{
QByteArray recvArray = mClient->readAll();
}
disconnected()
当客户端断开连接时触发该信号
connect(mClient, SIGNAL(disconnected()),this, SLOT(disconnectedSlot())); //断开连接
UI设计
服务端UI设计
TcpServer项目训练
widget.h
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
#include <QNetworkInterface>
#include <QAbstractSocket>
#include <QTcpServer>
#include <QTcpSocket>
#include <QMessageBox>
#include <QDateTime>
namespace Ui {
class Widget;
}
class Widget : public QWidget
{
Q_OBJECT
public:
explicit Widget(QWidget *parent = nullptr);
~Widget();
private slots:
void on_pushButton_listen_clicked();//开始监听
void newConnectionSlot(); //新连接
void disconnectedSlot(); //断开连接
void readyReadSlot(); //接收消息的槽函数
void on_pushButton_send_clicked(); //发送消息
private:
void enumIpAddress(); //枚举当前设备所有端口
private:
Ui::Widget *ui;
QTcpServer *mServer; //服务器
QTcpSocket *mClient = nullptr; //客户端
QList<QTcpSocket *>mClientList; //客户端链表
};
#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);
mServer = new QTcpServer;
enumIpAddress();
//处理新连接客户端
connect(mServer, SIGNAL(newConnection()),this, SLOT(newConnectionSlot()));
}
Widget::~Widget()
{
delete ui;
}
void Widget::enumIpAddress()
{
QList<QHostAddress> ipList = QNetworkInterface::allAddresses();
QStringList addressStrList;
addressStrList.clear();
for(int index = 0;index<ipList.size();index++)
{
if(ipList.at(index).isNull()) continue; //如果地址为空,则去掉
QAbstractSocket::NetworkLayerProtocol protocol = ipList.at(index).protocol();
if(protocol != QAbstractSocket::IPv4Protocol) continue; //只取IPV4的地址
addressStrList.append(ipList.at(index).toString());
}
ui->comboBox_Address->addItems(addressStrList);
}
void Widget::on_pushButton_listen_clicked()
{
QString serverAddressStr = ui->comboBox_Address->currentText(); //获取服务器ip地址
quint16 port = ui->lineEdit_port->text().toInt(); //获取服务器端口
QHostAddress serverAddress = QHostAddress(serverAddressStr); //初始化协议族
if(mServer->isListening())
{
//在监听状态 取消监听
mServer->close();
ui->pushButton_listen->setText("监听");
}
else
{
//不在监听状态 开始监听
if(mServer->listen(serverAddress, port))
{
//监听成功
qDebug() << "Listen Ok!!";
ui->pushButton_listen->setText("停止监听");
}
else
{
//监听失败
QMessageBox::warning(this, "Tcp Server Listen Error", mServer->errorString());
}
}
}
void Widget::newConnectionSlot()
{
QString clientInfo;
mClient = mServer->nextPendingConnection();
mClientList.append(mClient);
//窥视Client 信息
clientInfo = mClient->peerAddress().toString() + ":"+ QString::number(mClient->peerPort());
ui->listWidget_client->addItem(clientInfo);
connect(mClient, SIGNAL(readyRead()),this, SLOT(readyReadSlot())); //接收消息
connect(mClient, SIGNAL(disconnected()),this, SLOT(disconnectedSlot())); //断开连接
}
void Widget::readyReadSlot()
{
QByteArray recvArray;
QTcpSocket* current = nullptr;
if(!mClientList.isEmpty())
{
//接收客户端数据
for(int index = 0;index < mClientList.count();index ++)
{
current = mClientList.at(index);
if(current->isReadable())
{
recvArray = current->readAll();
if(recvArray.isEmpty()) continue;
QString str = QString(QDateTime::currentDateTime().toString("yyyy.MM.dd hh:mm:ss ddd")) +
":Recvn" + str.fromLocal8Bit(recvArray.data()); //本地GBK转Unicode 解决乱码
ui->textBrowser_recv->append(str);
break;
}
}
//转发给其他客户端
for(int index = 0;index < mClientList.count();index ++)
{
QTcpSocket* temp = mClientList.at(index);
if(current == temp) continue;
if(temp->isWritable())
{
temp->write(recvArray);
}
}
}
}
void Widget::disconnectedSlot()
{
QMessageBox::information(this, "client close Signal", "client over");
}
void Widget::on_pushButton_send_clicked()
{
QString sendString = ui->plainTextEdit_send->toPlainText();
QByteArray sendArr = sendString.toLocal8Bit();
//群发给所有客户端连接
if(!mClientList.isEmpty())
{
for(int index = 0;index < mClientList.count();index ++)
{
QTcpSocket* temp = mClientList.at(index);
if(temp->isWritable())
{
temp->write(sendArr);
}
}
}
QString str = QString(QDateTime::currentDateTime().toString("yyyy.MM.dd hh:mm:ss ddd"))
+ ":Sendn" + sendString;
ui->textBrowser_recv->append(str); //本地GBK转Unicode 解决乱码
}
- Silverlight体积优化
- 江湖秘笈:说烦了破解、渗透等,不如大家一起聊聊硬盘加密?
- Nodejs学习笔记(十三)— PM2
- 十分钟带你了解服务化框架
- 十分钟带你了解服务化框架
- WCF技术剖析之十七:消息(Message)详解(上篇)
- 微信年底重磅更新,这次小程序才是重头戏!
- 《EnterLib PIAB深入剖析》系列博文汇总
- Nodejs学习笔记(八)--- Node.js + Express 实现上传文件功能(felixge/node-formidable)
- 大牛教你使用7种卷积神经网络进行物体检测!
- Enterprise Library深入解析与灵活应用(3):倘若将Unity、PIAB、Exception Handling引入MVP模式.. .. ..
- 别对我说谎!你的小九九我都知道
- Spring集成RabbitMQ-使用RabbitMQ更方便
- Nodejs学习笔记(三)--- 模块
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- No qualifying bean of type 'org.springframework.transaction.PlatformTransactionManager' available:
- typescript中的class和interface
- SSH随笔
- Python爬虫+Flask,带你创建车标学习网站
- Go 堆栈的理解
- Kubernetes 与虚拟化和容器化的关系
- Golang 读、写文件
- 这次妥妥地拿下散列表---基础、如何设计以及扩展使用(LRU)
- 必看的Linux服务器高并发调优实战
- Vue3.0来了
- Golang 正则表达式(regexp)
- CentOS7基于ss5搭建Socks5代理服务器
- Go热门开源项目大全
- Python钉钉报警及Zabbix集成钉钉报警
- 无锁队列的实现