widget.cpp
#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_startbtn_clicked()
{
//获取ui的端口号
quint16 port = ui->portedt->text().toUInt();
//将服务器设置监听状态
//函数原型:bool QTcpServer::listen(const QHostAddress &address = QHostAddress::Any, quint16 port = 0)
//功能:将服务器设置成监听状态
//参数1:连接的主机地址,QHostAddress::Any,允许任意主机进行连接,当然,也可以指定主机号进行连接
//参数2:连接进来所需端口号,0表示任意端口号进行访问,也可以指定端口号进行访问服务器
//返回值:成功返回true,失败返回false
if (server->listen(QHostAddress::Any, port))
{
QMessageBox::information(this, "", "服务器启动成功");
}else
{
QMessageBox::information(this, "", "服务器启动失败");
}
//此时服务器进入监听,如果客户端发来连接请求,那么服务器自动发射newConnection信号
//我们可以将该信号连接到自定义的槽函数处理新连接的套接字
connect(server, &QTcpServer::newConnection, this, &Widget::newconnect_slot);
}
//处理newConnection信号的槽函数的实现
void Widget::newconnect_slot()
{
qDebug() << "有新用户连接";
//获取新连接的套接字
//函数原型:[virtual] QTcpSocket *QTcpServer::nextPendingConnection()
//功能:获取最新一次连接的客户端套接字
//参数:无
//返回值:最新连接客户端的套接字
QTcpSocket *s = server->nextPendingConnection();
//将新的套接字放入到客户端链表中
socketList.push_back(s);
//此时,客户端和服务器已经建立连接,那么,就可以进行数据的收发了
//如果客户端有数据发送给服务器,那么客户端就会自动触发一个readyRead的信号
//我们将该信号连接到自定义的槽函数中,处理相关逻辑
connect(s, &QTcpSocket::readyRead, this, &Widget::readyRead_slot);
}
//自定义处理readyRead信号的槽函数
void Widget::readyRead_slot()
{
//将无效的客户端移除出链表
for(int i=0; i<socketList.size(); i++)
{
//对第i个客户端的状态进行判断,如果是无连接的 状态,则进行移除
//QAbstractSocket::SocketState QAbstractSocket::state() const
//功能:查看客户端的状态
//参数:无
//返回值:当前客户端的状态
if(socketList.at(i)->state() == 0)
{
//如果当前状态无连接的,则进行移除
socketList.removeAt(i);
}
}
//将所有有效的客户端进行遍历,查看是哪个客户端中有数据待读
for(int i=0; i<socketList.size(); i++)
{
//判断当前客户端是否有待读数据
//qint64 QAbstractSocket::bytesAvailable() const
//功能:返回待读数据的字节数
//参数:无
if(socketList.at(i)->bytesAvailable() != 0)
{
//读取数据
//QByteArray QIODevice::readAll()
//功能:读取出当前客户端中所有信息
//参数:无
//返回值:字节数组
QByteArray msg = socketList.at(i)->readAll();
//将读取的数据展示到自身的ui界面
ui->msgWidget->addItem(QString::fromLocal8Bit(msg));
//将该消息广播给所有客户端
for(int j=0; j<socketList.size(); j++)
{
socketList.at(j)->write(msg);
}
}
}
}
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_NAMESPACE
class Widget : public QWidget
{
Q_OBJECT
public:
Widget(QWidget *parent = nullptr);
~Widget();
private slots:
void on_startbtn_clicked();
void newconnect_slot(); //自定义处理newConnect的槽函数
void readyRead_slot(); //自定义处理readyRead信号的槽函数
private:
Ui::Widget *ui;
//定义服务器指针
QTcpServer *server;
//定义客户端容器
QList<QTcpSocket*> socketList;
};
#endif // WIDGET_H