目录
1.在widget中声明自定义TcpServer类的成员变量
2.在TcpServer的构造函数中对于我们声明的m_widget进行初始化,m_widget我们用于后续的显示消息等,说白了就是主界面的更新显示等
1.TcpSocket.h 先忽略掉信号与槽函数,关注构造函数与qintptr类型的 m_sockDesc
1.主要关注run函数,其中run函数是继承QThread中的虚函数,需要我们进行重写
在初学Qt 中Tcp服务器与客户端的时候,发现每次服务器只能和最后一个连接的客户端进行通信,因为没有用到多线程以及TcpServer中虚函数incomingConnection(),当新的客户端连接的时候,会自动调用incomingConnection函数,在里面产生新的线程来处理通信。
以下来讲讲这个简易的多线程Tcp服务器的实现
一.UI界面的设计
其中包括2个Label,一个LineEdit,两个pushbutton,上面是一个TextBrowser用于服务器显示通信记录,下面一个TextEdit用于发送信息。这样一个简单的界面就搭建完成了~~~
二.服务器的启动
首先我们肯定需要实现点击启动服务器按钮来启动服务器
1.在界面中右击启动按钮 ----> 转到槽
2.实现逻辑,这里直接放代码,其中serverisworking 是我在widget.h 中声明的一个bool类型,用于判断服务器是否启动,同时更改按钮的文本显示内容,以及弹出对话框提示。
//点击开始启动服务器
void Widget::on_pushButton_StartServer_clicked()
{
//如果服务器没有启动
if (!this->serverisworking) {
if(this->m_tcpserver->listen(QHostAddress::Any,ui->lineEdit_Port->text().toUShort())){
QMessageBox::information(this,"成功!","启动成功!");
ui->pushButton_StartServer->setText("关闭服务器");
this->serverisworking = true;
}
else {
QMessageBox::critical(this,"失败!","服务器启动失败请检查设置!");
}
}
//如果服务器正在启动
else if(this->serverisworking) {
m_tcpserver->close();
if(!m_tcpserver->isListening()){
ui->pushButton_StartServer->setText("启动服务器");
this->serverisworking = false;
QMessageBox::information(this,"提示","关闭成功!");
}
else {
QMessageBox::critical(this,"错误","关闭失败,请重试!");
return;
}
}
}
三.实现自定义的TcpServer类
1.首先我们搞清楚,这个类是负责干嘛的?这个类我们要继承QTcpServer,重写虚函数incomingConnetion
2.这是头文件,如果有报错,注意看使用#pragma once没有,因为可能涉及到头文件重复包含
//tcpserver.h
#pragma once
#ifndef TCPSERVER_H
#define TCPSERVER_H
#include <QObject>
#include<QTcpServer>
#include <widget.h>
#include"serverthread.h"
class TcpServer : public QTcpServer
{
Q_OBJECT
public:
explicit TcpServer(QObject *parent = nullptr);
private:
//重写虚函数
void incomingConnection(qintptr sockDesc);
private:
//用来保存连接进来的套接字,存到ComboBox中
QList<qintptr> m_socketList;
//再包含一个widget对象
Widget *m_widget;
};
#endif // TCPSERVER_H
1.在widget中声明自定义TcpServer类的成员变量
//widget.h
#pragma once
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
#include<QMessageBox>
#include"tcpserver.h"
namespace Ui {
class Widget;
}
class TcpServer;
class Widget : public QWidget
{
Q_OBJECT
public:
explicit Widget(QWidget *parent = nullptr);
~Widget();
public:
//当有新连接的时候在页面上显示
void showNewConnection(qintptr sockDesc);
//断开时显示
void showDisconnection(qintptr sockDesc);
//当服务器发送消息后,通知窗口更新消息
void UpdateServerMsg(qintptr Desc,const QByteArray &msg);
private slots:
//按钮被触发
void on_pushButton_StartServer_clicked();
void on_pushButton_Trans_clicked();
public slots:
//当服务器收到客户端发送的消息后,更新消息
void RecvMsg(QString Desc,const QByteArray &msg);
signals :
void sendData(qintptr Desc ,const QByteArray &msg);
private:
Ui::Widget *ui;
TcpServer *m_tcpserver;
bool serverisworking;
};
#endif // WIDGET_H
其他的我们先不去讨论,这里我们就声明一个TcpServer类型的m_tcpserver 以及一个bool类型的serverisworking用来判断服务器是否在工作
2.在TcpServer的构造函数中对于我们声明的m_widget进行初始化,m_widget我们用于后续的显示消息等,说白了就是主界面的更新显示等
TcpServer::TcpServer(QObject *parent) : QTcpServer(parent)
{
m_widget = dynamic_cast&