服务器:
#include "widget.h"
#include "ui_widget.h"
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
//给服务器指针实例化对象
server = new QTcpServer(this);
}
Widget::~Widget()
{
delete ui;
}
//启动服务器按钮对应的槽函数
void Widget::on_pushButton_clicked()
{
//获取ui界面上的端口号
quint16 port = ui->lineEdit->text().toUInt();
//将服务器设置成监听状态
if(!server->listen(QHostAddress::Any, port))
{
QMessageBox::critical(this, "失败", "服务器启动失败");
return;
}
else
{
QMessageBox::information(this, "成功", "服务器启动成功");
}
//此时表明服务器启动成功,并对客户端连接进行监听
//如果有客户端向服务器发射连接请求,那么该服务器就会自动发射一个newConnection的信号
connect(server, &QTcpServer::newConnection, this, &Widget::newConnection_slot);
}
//处理newConnection
void Widget::newConnection_slot()
{
qDebug() << "有新的客户端发来连接请求了";
//获取最新连接的客户端套接字
QTcpSocket *s = server->nextPendingConnection();
//将获取的套接字存放到客户端容器中
clientlist.push_back(s);
connect(s, &QTcpSocket::readyRead, this, &Widget::readyRead_slot);
}
void Widget::readyRead_slot()
{
//删除客户端链表中无效的客户端套接字
for(int i=0; i<clientlist.count(); i++)
{
//判断套接字的状态
if(clientlist[i]->state() == 0) //SocketState state() const
{ //功能:返回客户端套接字的状态
clientlist.removeAt(i);
} //返回值:客户端的状态,如果结果为0,表示未连接
}
//遍历所有客户端,查看是哪个客户端发来数据
for(int i=0; i<clientlist.count(); i++)
{
if(clientlist[i]->bytesAvailable() != 0)
{
//读取当前客户端的相关数据
QByteArray msg = clientlist[i]->readAll();
//将数据展示到ui界面上
ui->listWidget->addItem(QString::fromLocal8Bit(msg));
//将接受的信息,发送给所有客户端
for(int j=0; j<clientlist.count(); j++)
{
clientlist[j]->write(msg);
}
}
}
}
客户端:
#include "widget.h"
#include "ui_widget.h"
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
socket = new QTcpSocket(this);
connect(socket, &QTcpSocket::connected, this, &Widget::connected_slot);
//客户端与服务器连接成功后,服务器向客户端发来数据,那么客户端就会发射一个readyRead信号
connect(socket, &QTcpSocket::readyRead, this, &Widget::readyRead_slot);
connect(socket, &QTcpSocket::disconnected, this, &Widget::disconnected_slot);
}
Widget::~Widget()
{
delete ui;
}
void Widget::on_connectBtn_clicked()
{
if(ui->connectBtn->text() == "连接服务器")
{
//获取ui界面信息
Name = ui->userNameEdit->text();
QString hostName = ui->ipEdit->text();
quint16 port = ui->portEdit->text().toUInt();
//连接到主机
socket->connectToHost(hostName, port);
//如果连接服务器成功,该客户端就会发射一个connected的信号
ui->connectBtn->setText("断开服务器");
}
else if(ui->connectBtn->text() == "断开服务器")
{
QString msg = Name + ":拿手好戏后 离开聊天室";
socket->write(msg.toLocal8Bit());
//断开客户端与服务器的连接
socket->disconnectFromHost();
//当客户端与服务器断开,该客户端就会自动发送一个disconnected的信号
ui->connectBtn->setText("连接服务器");
}
}
//处理conneed信号的槽函数定义
void Widget::connected_slot()
{
QMessageBox::information(this, "成功", "连接服务器成功");
//顺便向服务器发送一条信息,说:***,进入聊天室
QString msg = Name + ":带着power 进入聊天室";
socket->write(msg.toLocal8Bit());
}
void Widget::readyRead_slot()
{
QByteArray msg = socket->readAll();
ui->msgList->addItem(QString::fromLocal8Bit(msg));
}
void Widget::on_sendBtn_clicked()
{
//获取ui界面的编辑的文本
QString m = ui->msgEdit->text();
//整合要发送的信息
QString msg = Name + ":" + m;
//将信息发送给服务器
socket->write(msg.toLocal8Bit());
//发送后清空文本
ui->msgEdit->clear();
}
void Widget::disconnected_slot()
{
QMessageBox::information(this, "退出", "断开服务器");
}
思维导图: