头文件
#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();
QTcpServer *server; //实例化服务器指针
QList<QTcpSocket*> socketList; //客户端容器
private slots:
void on_sever_btn_clicked(); //按钮槽函数
void newConnection_slot();//服务器发出信号连接的槽函数
void readyRead_slot();//客户端发射的readyRead信号连接的槽函数
private:
Ui::Widget *ui;
};
#endif // WIDGET_H
源文件
#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_sever_btn_clicked()
{
//监听状态
// 函数原型 uint toUInt(bool *ok=nullptr, int base=10) const;
quint16 port = ui->port_edit->text().toUInt();
// 函数原型 bool listen(const QHostAddress &address = QHostAddress::Any, quint16 port = 0);
if(server->listen(QHostAddress::Any, port)){
QMessageBox::information(this,"提示","服务器启动成功");
}else{
QMessageBox::information(this,"提示","服务器启动失败");
}
//到此说明已经进入监听状态,连接信号与槽函数
//客户端发请求时,服务器自动触发newConnection信号,连接此信号到槽函数
connect(server, &QTcpServer::newConnection, this, &Widget::newConnection_slot);
}
//服务器触发newConnection信号连接的槽函数
void Widget::newConnection_slot()
{
qDebug() <<"有新客户端连接。。。";
//调用nextPaddingConnection函数获取最新连接客户的套接字
//并将改套接字放入队列中
// 函数原型 virtual QTcpSocket *nextPendingConnection();
QTcpSocket *p_skt = server->nextPendingConnection(); //获得套接字
socketList.push_back(p_skt); //放入容器
//此时客户端已经与服务器建立连接
//如果有客户端向服务器发来数据,客户端就会自动发射一个readyRead信号
//可以在该信号对应的槽函数获取客户端的信息
connect(p_skt, &QTcpSocket::readyRead, this, &Widget::readyRead_slot); //客户端信号与槽函数连接
}
//客户端发射的readyRead信号连接的槽函数
void Widget::readyRead_slot()
{
//移除无效客户端
// 函数原型 SocketState state() const;
// 返回值 UnconnectedState, 枚举值 0
int i = 0;
int j = 0;
for(i = 0;i <socketList.count(); i++){
if(!socketList.at(i)->state()){
socketList.removeAt(i);// 移除
}
}
//寻找有效客户端,如果有数据就读出来
// 函数原型 qint64 bytesAvailable() const override;
//返回值是待读取的数据的个数
//函数原型 QByteArrarg readAll()
//返回值是QByteArray类型的数据
for(i = 0;i <socketList.count(); i++){
if(socketList.at(i)->bytesAvailable()){
//获取数据
QByteArray msg = socketList.at(i)->readAll();
//将数据展示到ui界面
ui->text_list->addItem(QString::fromLocal8Bit(msg));
//数据发给其他客户端
for(j = 0; j < socketList.count(); j++){
socketList.at(j)->write(msg);
}
}
}
}