Qt搭建多线程Server

起因是MySQL在Android上没有驱动。也就是说,移动端想要访问远程数据库,必须通过一台(或多台)PC进行中转。

中转PC作为Server,接受来自移动端Socket访问数据库的要求,Server访问数据库,取得数据,通过Socket发送给移动端。

Qt写个C/S其实很简单,网上各种教程,硬伤:Server!是!单!线!程!

假设有10000个移动端访问中转Server,那么如果Server是单线程,那么这10000个移动端是排队通信,排队访问数据库,肯定完蛋!

所以Server必须使用多线程。

Qt的多线程是个经常让新手搞错的东西,很多文章中看起来是多线程,实际上根本就是单线程。

默认的C/S连接方式(acceptConnection)不支持多线程也是硬伤!

于是搞了好久,总算搞定了多线程Server。

①首先写Server类,派生自QTcpServer, 只要重载 incomingConnection 这个虚函数就行了。

无须像单线程那样  connect(&server,SIGNAL(newConnection()),this,SLOT(acceptConnection()));

void Server::incomingConnection (qintptr socketDescriptor)
{
    SocketThread *thread = new SocketThread(socketDescriptor,this);
    Processor *cpu=new Processor(thread->socket);
    connect(thread->socket,SIGNAL(readyRead()),cpu,SLOT(work()));
    connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater()));
    cpu->moveToThread (thread);
    thread->start();
}

在这个函数里有几个陌生的玩意。

SocketThread类 派生自QThread,子线程不解释。

Processor类 派生自 QObject,这个类是重点。

Qt多线程的最大问题在于,除了子线程的run函数是跑在子线程里,线程其它函数(包括信号/槽)都是跑在主线程里。

我们的Server肯定要处理Client的请求,也就是Socket的数据请求,在Qt里,这步被封装在Socket的readyRead信号里。

就算你在run函数里绑了readyRead信号,最后信号还是会在主线程里触发。

解决方案是单独写个处理类,这里就是Processor类,将子线程moveThread到这个对象中,这样这个对象的所有函数都是在子线程里执行了,work函数用于Server接受请求以及返回数据库数据。

这是Qt 4.7之后,官方的推荐写法,因为N多人的多线程写的根本就是错的,官方实在忍不了了。

②再看 SocketThread类

class SocketThread : public QThread
{
    Q_OBJECT
public:
    SocketThread(int socketDescriptor,QObject* parent);
    int socketDescriptor;
    QTcpSocket *socket;
    void run();
};

SocketThread::SocketThread(int id,QObject *parent):QThread()
{
    socketDescriptor=id;
    socket=new QTcpSocket;
}
void SocketThread::run ()
{
    socket->setSocketDescriptor(socketDescriptor);
    QThread::run ();
}

Thread

构造函数不用多说,传入系统为Server分配的Socket的识别id。

关键就是QThread的虚函数run。首先设置Server的Socket识别id。

记得调用 QThread::run ();  否则这个run函数并没有完全执行。

③再看Processor类

void Processor::work ()
{
    //qDebug()<<"当前线程: "<<QThread::currentThreadId ()<<endl;
    buff=m_socket->readAll ();
    m_socket->write (buff);
    //qDebug()<<buff<<endl;
}

Processor

成员就一个指针m_socket,保存子线程的socket地址。

以及一个QByteArray作为缓冲区buff。

readAll读取Client的Socket,write写回Client的Sokcet。

无聊的话可以把注释拿掉,看看work函数的工作线程是否与主线程不同。

④Client端

void Client::send ()
{
    socket->connectToHost(QHostAddress(address->text ()),7399);
    QString x="2333,要完蛋了 "+QString::number (cnt++);
    socket->write(x.toStdString ().c_str ());
}
void Client::get ()
{
    QString data=socket->readAll();
    qDebug()<<"接收端:"<<data<<endl;
    socket->disconnectFromHost ();
}

这里使用的策略如下:

每发一个请求,连一次Server,收到Server的回复后,断开连接,防止占用Sever资源。

get函数作为Client的readyRead的槽函数就行了。

时间: 2024-10-12 17:12:56

Qt搭建多线程Server的相关文章

基于QT的多线程服务器

// thread.cpp #include "thread.h" Thread::Thread(int socketDescriptor, QObject *parent) : QThread(parent) { m_socketDescriptor = socketDescriptor; } Thread::~Thread() { } void Thread::run() { m_tcpSocket = new QTcpSocket; if (!m_tcpSocket->se

qt调用sql server存储过程并获取output参数

最近新做的一个项目需要使用qt连接另一台机器上的sql server,虽然网上已有类似文章,但还是有些其中很少提及的问题,故在这里汇总下: qt连接sql server可以参考这篇文章,如果是连接另一台机器的sql server就不用执行第一步“开启ODBC驱动”了 http://www.cnblogs.com/shaolw/p/3411285.html 另外指定数据库用户名和密码可以使用Uid和Pwd,即原文dsn参数可以这样写: QString dsn = QString("Driver={

用VLC搭建流媒体server

VLC开元项目相当强大,我们既能够将其作为播放核心用于二次开发,又能够将其作为高性能的流媒体server.今篇博客主要讲用VLC搭建流媒体server. VLC搭建流媒体server步骤非常easy:选择输入数据.选择输出格式.选择编码器.选择流通量.输入数据来源非常多,能够是本地文件,能够是网络流,能够是音频.甚至图片.编码器选择主要是选择音频编码器.视频编码器用以确定声音输出质量和图像质量.输出格式较多,能够是本地文件,能够是网络流,也能够是组播:流通量眼下保留.实际没有多少用处. 以下我用

从0开始搭建SQL Server AlwaysOn 第一篇(配置域控)

从0开始搭建SQL Server AlwaysOn 第一篇(配置域控) 网上的 AlwaysOn可以说是非常的多,也可以说是非常的千篇一律,而且很多都是搭建非常顺利的,没有坑的,难道搭建 AlwaysOn真的可以这麽顺利吗?????? 由于公司使用的是最新的Windows Server 2012 R2,网上用的都是Windows Server 2008 R2 ,2012 R2和2008 R2在故障转移集群界面菜单和AD 服务管理工具 已经有较大变化,有一些步骤跟Windows Server 20

在Windows Server 2012 R2中搭建SQL Server 2012故障转移集群

需要说明的是我们搭建的SQL Server故障转移集群(SQL Server Failover Cluster)是可用性集群,而不是负载均衡集群,其目的是为了保证服务的连续性和可用性,而不是为了提高服务的性能. SQL Server始终在负载均衡集群方面都缺少自己的产品,多由第三方厂家提供,但SQL Server故障转移集群却由来已久,在SQL Server 2012还提供了一个可用性组(AlwaysOn High Availability Groups)的新特性,我们知道微软的故障转移集群(W

第三篇——第二部分——第二文 计划搭建SQL Server镜像

原文:第三篇--第二部分--第二文 计划搭建SQL Server镜像 本文紧跟上一章:SQL Server镜像简介 本文出处:http://blog.csdn.net/dba_huangzj/article/details/27203053 俗话说:工欲善其事必先利其器.计划好如何部署和使用镜像,可以减少很多不必要的风险.本文将按照三步骤的形式展示,但是要注意这不是唯一的标准,具体情况具体分析. 第一步:了解环境 在搭建SQL Server镜像时,必须先了解你所要部署的环境,才能决定镜像的配置项

搭建Git Server

windows上如何搭建Git Server Git在版本控制方面,相比与SVN有更多的灵活性,对于开源的项目,我们可以托管到Github上面,非常方便,但是闭源的项目就会收取昂贵的费用.那么私有项目,如何用Git进行代码版本控制呢?我们可以自己构建Git服务器.一般来说,在Linux上搭建Git的教程比较多,但是如何在Windows Server平台下搭建Git服务器呢? 对于很多.NET用户来说,代码编写的工具是Visual Studio,该工具是不支持SSH协议的,通过搜索和对比,发现Gi

Linux 搭建SVN server

一. SVN 简单介绍 Subversion(SVN) 是一个开源的版本号控制系統, 也就是说 Subversion 管理着随时间改变的数据. 这些数据放置在一个中央资料档案库 (repository) 中. 这个档案库非常像一个普通的文件server, 只是它会记住每一次文件的变动. 这样你就能够把档案恢复到旧的版本号, 或是浏览文件的变动历史. SVN中的一些概念 : (1). repository(源码库) 源码统一存放的地方 (2). Checkout (提取) 当你手上没有源码的时候,

从0开始搭建SQL Server AlwaysOn 第二篇(配置故障转移集群)

从0开始搭建SQL Server AlwaysOn 第二篇(配置故障转移集群) 第一篇http://www.cnblogs.com/lyhabc/p/4678330.html 第二篇http://www.cnblogs.com/lyhabc/p/4682028.html 这一篇是从0开始搭建SQL Server AlwaysOn 的第二篇,主要讲述如何搭建故障转移集群,因为AlwaysOn是基于Windows的故障转移集群的 在讲解步骤之前需要了解一下故障转移集群仲裁配置 下面图片来自<Wind