// widget.h
#include <QWidget>
#include <QUdpSocket>
QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE
class Widget : public QWidget
{
Q_OBJECT
public:
Widget(QWidget *parent,QString name);
~Widget();
void closeEvent(QCloseEvent *);
private:
Ui::Widget *ui;
signals:
void closeWidget(); // 关闭窗口发送信号
public:
enum MsgType {Msg,UsrEnter,UsrLeft};
void sndMsg(MsgType type); // 广播UDP消息
void usrEnter(QString userName); // 处理新用户加入
void usrLeft(QString userName); // 处理用户离开
QString getUsrName(); // 获取用户名
QString getMsg(); // 获取聊天信息
private:
QUdpSocket* udpSocket; // Udp套接字
qint16 port; // 端口
QString uName; // 用户名
void recvMsg(); // 接收Udp消息
};
// widget.cpp
#include "widget.h"
#include "ui_widget.h"
#include <QDataStream>
#include <QMessageBox>
#include <QDateTime>
Widget::Widget(QWidget *parent,QString name)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
// 初始化操作
udpSocket = new QUdpSocket(this); // 套接字
uName = name; // 用户名
port = 9999; // 端口号
/*
* ShareAddress模式, 允许不同的服务连接到相同的地址和端口,常用于多客户端监听同一个服务器端口
* ReuseAddressHint模式, 断线重新连接服务器
*/
udpSocket->bind(port,QUdpSocket::ShareAddress|QUdpSocket::ReuseAddressHint); // 绑定端口号
//sndMsg(UsrEnter); // 发送新用户进入
// 点击发送按钮发送消息
connect(ui->Btn_Send,&QPushButton::clicked,[=](){
sndMsg(Msg);
});
// 监听别人发送的数据
connect(udpSocket,&QUdpSocket::readyRead,this,&Widget::recvMsg);
}
Widget::~Widget()
{
delete ui;
}
void Widget::closeEvent(QCloseEvent*)
{
emit closeWidget();
}
void Widget::sndMsg(Widget::MsgType type)
{
// 发送的消息分为3种类型
// 发送的数据分3段处理. 第一段,类型; 第二段,用户名; 第三段,具体内容
QByteArray array;
QDataStream stream(&array,QIODevice::WriteOnly);
stream << type << getUsrName(); // 类型 和 用户名, 添加到流中
switch (type) {
case Msg: // 普通消息发送
if(ui->msgTxtEdit->toPlainText() == "")
{ // 如果用户没有输入内容,不发消息
QMessageBox::warning(this,"警告","发送内容不能为空");
return;
}
stream << getMsg(); // 具体内容, 添加到流中
break;
case UsrEnter:
break;
case UsrLeft:
break;
default:
break;
}
// 书写报文
udpSocket->writeDatagram(array,QHostAddress::Broadcast,port);
}
QString Widget::getUsrName()
{
return uName;
}
QString Widget::getMsg()
{
QString str = ui->msgTxtEdit->toHtml();
ui->msgTxtEdit->clear(); // 清空输入框
ui->msgTxtEdit->setFocus();
return str;
}
void Widget::recvMsg()
{
// 获取报文长度
qint64 size = udpSocket->pendingDatagramSize();
// 读取报文
QByteArray array = QByteArray(size,0);
udpSocket->readDatagram(array.data(),size);
// 解析数据
QDataStream stream(&array,QIODevice::ReadOnly); // 从array中读取数据到stream中
// 定义接收三段数据的三个变量
int msgType;
QString usrName;
QString msg;
stream >> msgType; // 从stream中取出 类型
// 获取当前时间
QString time = QDateTime::currentDateTime().toString("yyyy-MM-dd hh-mm-ss");
switch (msgType) {
case Msg:
stream >> usrName >> msg; // 从stream中取出 用户名 和 具体内容
// 追加聊天记录
ui->msgBrowser->setTextColor(Qt::blue); // 设置聊天框文本颜色
ui->msgBrowser->append("[" + usrName + "]" + time);
ui->msgBrowser->append(msg);
break;
case UsrEnter:
break;
case UsrLeft:
break;
default:
break;
}
}