一、手动完成服务器的实现,并注释具体步骤
源码:
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();
void newConnnecttion_slot(); //自定义槽函数,用来处理有客户端发送连接请求后,服务器自动发送的newConnecttion信号
void readyRead_slot(); //自定义槽函数,用来处理客户端要向客户端发送信息时,客户端自动发送的readyRead信号
private slots:
void on_pushButton_clicked();
private:
Ui::Widget *ui;
//定义服务器指针
QTcpServer *server;
//定义存储客户端套接字容器
QList<QTcpSocket*> sockList;
};
#endif // WIDGET_H
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_pushButton_clicked()
{
//将行编辑器的内容赋值到port中
quint16 port = ui->lineEdit->text().toUInt();
//监听
if(server->listen(QHostAddress::Any, port)){
QMessageBox::information(this, "连接提示", "客户端连接成功!");
}else{
QMessageBox::information(this, "连接提示", "客户端连接失败!");
}
//此时服务器已经处于监听状态,如果有客户端发送连接请求,那么该服务器会自动发送newConnnecttion信号
//我们可以将该信号连接到自定义的槽函数中,处理新套接字
connect(server, &QTcpServer::newConnection, this, &Widget::newConnnecttion_slot);
}
void Widget::newConnnecttion_slot()
{
//保存服务器接收到的客户端套接字指针
QTcpSocket *s = server->nextPendingConnection();
//将该套接字指针放到容器中
sockList.push_back(s);
//此时服务器与客户端已建立连接
//如果客户端要向服务器发送信息,那么会发送一个readyRead信号
//此时需要将该信号与自定义槽函数连接,读取客户端数据
connect(s, &QTcpSocket::readyRead, this, &Widget::readyRead_slot);
}
void Widget::readyRead_slot(){
//移除无效客户端
for(int i = 0; i < sockList.count(); i++){ //sockList.count() 表示存储客户端套接字的容器内元素个数
if(sockList.at(i)->state() == 0){ //state表示客户端的状态,是一个枚举值,=0表示该客户端已断开连接
sockList.removeAt(i); //移除该客户端
}
}
//遍历客户端容器,判断是哪个客户端有数据要读
for(int i = 0; i < sockList.count(); i++){
if(sockList.at(i)->bytesAvailable() != 0){ //表示该客户端有数据要读
//读取该客户端发送的全部信息
QByteArray msg = sockList.at(i)->readAll();
//将数据展示到ui界面
ui->listWidget->addItem(QString::fromLocal8Bit(msg));
//将该消息发送给所有客户端
for(int i = 0; i < sockList.count(); i++){
sockList.at(i)->write(msg);
}
}
}
}
main.cpp
#include "widget.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Widget w;
w.show();
return a.exec();
}