1.思维导图
2.手动完成服务器实现
.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_startserver_clicked(); //按钮槽函数
void newconnection_slot(); //客户端连接服务器成功处理槽函数
void readyRead_slot(); //套接字收到客户端的数据后处理槽函数
private:
Ui::Widget *ui;
QTcpServer *server; //服务器
QList<QTcpSocket*> socketlist;//套接字容器
};
#endif // WIDGET_H
.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_startserver_clicked()
{
quint16 port=ui->ld->text().toUInt();
//将服务器设置监听状态
if(server->listen(QHostAddress::Any,port))
{
QMessageBox::information(this,"","服务器启动成功");
}
else
{
QMessageBox::information(this,"","服务器启动失败");
}
//连接服务器的客户端连接成功信号和对应槽函数
connect(server,&QTcpServer::newConnection,this,&Widget::newconnection_slot);
}
//处理客户端连接成功信号
void Widget::newconnection_slot()
{
qDebug()<<"有新客户连接";
//创建新套接字连接最新客户端
QTcpSocket *s=server->nextPendingConnection();
//加入套接字队列
socketlist.push_back(s);
//连接套接字的客户端发送信号和对应槽函数
connect(s,&QTcpSocket::readyRead,this,&Widget::readyRead_slot);
}
//处理套接字收到客户端数据
void Widget::readyRead_slot()
{
//剔除无效客户端
for(int i=0;i<socketlist.count();i++)
{
//socketlist.at(i)->state();
if(socketlist.at(i)->state()==0)
{
socketlist.removeAt(i);
}
}
//选择有数据待读的套接字
for(int i=0;i<socketlist.count();i++)
{
if(socketlist.at(i)->bytesAvailable()!=0)
{
//从套接字获取数据
QByteArray msg=socketlist.at(i)->readAll();
//展示在界面上
ui->listWidget->addItem(QString::fromLocal8Bit(msg));
//广播给所有客户端
for(int j=0; j<socketlist.count();j++)
{
socketlist.at(j)->write(msg);
}
}
}
}