什么是多线程并发服务器?在QT里如何使用多线程并发服务器呢?
多线程并发服务器是一种网络服务器设计,它能够同时处理多个客户端的请求。在多线程服务器中,主线程负责监听和接受来自客户端的连接请求,每当有一个新的连接请求到来时,服务器就会创建一个新的线程来处理该连接。这样,每个客户端都有一个专门的线程来为之服务,从而实现并发处理多个客户端请求的目的。
下面是如何在QT里使用多线程并发服务器的流程。
可以先看这个图理解一下。
重写incomingConnection()函数
首先在myserver.h里创建一个Myserver类继承QTcpServer,重写 incomingConnection();
并创建一个自定义信号。
myserver.h
#ifndef MYSERVER_H
#define MYSERVER_H
#include<QTcpServer>
class Myserver:public QTcpServer
{
Q_OBJECT
public:
Myserver(QObject *parent = 0);
//重写,传递套接字描述(sd标志)
void incomingConnection(qintptr socketDescriptor);
~Myserver();
signals: //信号函数不需要实现
void sig_sendsd(qintptr sd);
};
#endif // MYSERVER_H
在myserver.c里实现重写的incomingConnection()函数,当有客户端连接的时,会发送包含socket套接字描述符的信号sig_sendsd(socketDescriptor)(上面创建的信号)到主线程。(套接字描述符socketDescriptor很重要,在子线程里用来创建socket对象跟客户端进行通信)。
#include "myserver.h"
Myserver::Myserver(QObject *parent):QTcpServer(parent)
{
}
void Myserver::incomingConnection(qintptr socketDescriptor)
{
//发送自定义信号给主线程(sd标志)
emit sig_sendsd(socketDescriptor);
}
Myserver::~Myserver()
{
}
创建子线程类
在socketthread.h里创建一个叫socketthread的子线程类用于处理每个客户端发来的信息。
#ifndef SOCKETTHREAD_H
#define SOCKETTHREAD_H
#include<QThread>
#include<QTcpSocket>
class SocketThread:public QThread
{
Q_OBJECT
public:
SocketThread(qintptr sd);
void run(); //重写run函数,执行线程
~SocketThread();
private slots:
void slot_read();
void slot_disconnect();
private:
qintptr sd;
QTcpSocket *socket;
};
#endif // SOCKETTHREAD_H
在socketthread.c中run()函数中处理客户端发来的信息,以及发送信息到客户端。
#include "socketthread.h"
SocketThread::SocketThread(qintptr sd):sd(sd)
{
}
void SocketThread::run()
{
socket=new QTcpSocket;
socket->setSocketDescriptor(sd);
connect(socket,SIGNAL(readyRead()),this,SLOT(slot_read()));
connect(socket,SIGNAL(disconnected()),this,SLOT(slot_disconnect()));
}
void SocketThread::slot_read()
{
isRead=true;
qDebug()<<"客服端来消息了";
}
void SocketThread::slot_disconnect()
{
qDebug()<<"客户端已断开";
isRun=false;
}
SocketThread::~SocketThread()
{
qDebug()<<"子线程结束";
}
主线程(重点)
在主线程里创建myserver类对象,监听客户端,等待客户端连接。当有客户端连接时,myserver类对象会发出自定义信号sig_sendsd(qintptr),通过connect()函数,执行槽函数slot_recv_sd()。在槽函数里创建子线程类对象,在子线程类对象里创建socket套接字(上图),跟客户端通信。
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
initIp();
server=new Myserver(this);
server->listen(QHostAddress::Any,12345); //any所有地址 12345port
//当有新的客户端连接,server对象会发出自定义信号
connect(server,SIGNAL(sig_sendsd(qintptr)),this,SLOT(slot_recv_sd(qintptr)));
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::initIp() //获取本地ip地址
{
QString ip;
QString hostName = QHostInfo::localHostName();
QHostInfo info = QHostInfo::fromName(hostName);
QList<QHostAddress> list=info.addresses();
for(int i=0;i<list.size();i++)
{
//获取协议类型
if(list[i].protocol()==QAbstractSocket::IPv4Protocol)
{
ip+="*";
ip+=list[i].toString();
}
}
ui->label_ip->setText(ip);
}
void MainWindow::slot_recv_sd(qintptr sd)
{
//创建子线程
st=new SocketThread(sd);
st->start();
}
最后的最后,感谢大家的支持,请求各路英雄豪杰多多打赏,多多关注,多多点赞,我是只发布高质量文章的 better-code 。