Qt学习之路——QTcpSocket using multiple thread

September 11th, 2013 by JasonLe's Tech Leave a reply »

之前在暑假我学习了QThead类,只要我们继承这个类,就可以轻松地创建多线程函数。
首先我们先回顾一下QThread的用法:
线程执行函数要重写run(),在run()中写下要单独执行的函数段。然后需要开启线程的时候,就直接创建这个thread对象,然后start()即可。

下面我们来说明如何使用thread开发多线程的TCPserver,其实区别于单线程的Server,大的方向就是将业务耗时逻辑块放在run()中,比如初始化QTcpSocket,因为我们要区别每一个用户的ID,所以我们修改继承的MyThread函数加一个参数int ID,并将这个ID赋值给Thread的成员变量 socketDescription。然后在run()中加入connect() 与SLOT函数 readRead()与 disconnect() 最后因为是server,所以要进行循环等待,加入exec()这函数就和qt GUI main()中的差不多,窗口不断进行消息监听,处理分发消息。

void MyThread::run()
{
    //thread start here
    qDebug()<< socketDescription << "Starting thread";
    socket = new QTcpSocket();
    if(!socket->setSocketDescriptor((this->socketDescription)))
    {
        emit error(socket->error());
        return;
    }
    connect(socket,SIGNAL(readyRead()),this,SLOT(readRead()),Qt::DirectConnection);
     connect(socket,SIGNAL(disconnected()),this,SLOT(disconnect()),Qt::DirectConnection);

     qDebug() << socketDescription << " Client connected......";

     exec();
}
void MyThread::readRead()
{
    QByteArray Data = socket->readAll();

    qDebug()<< socketDescription << "Data in: "<<Data;

    //socket->write(Data);
}//这个SLOT函数是自己定义的,我们可以自定义获取Data数据以后的操作,我目前是吧Data数据打印出来了
------------------------------------------------------------------------------------------------

MyServer::MyServer(QObject *parent) :
    QTcpServer(parent)
{
}
void MyServer::StartServer()
{
    if( !this->listen(QHostAddress::Any,1234))
//因为这个函数,我继承了QTcpServer所以,我可以直接调用listen监听函数
    {
        qDebug()<<"Can't!";
    }
    else
    {
        qDebug()<< "Listening........";
    }
}
void MyServer::incomingConnection(int socketDescriptor)
{
    qDebug()<< socketDescriptor << "Connecting.....";
    MyThread *thread = new MyThread(socketDescriptor,this);
    connect(thread,SIGNAL(finished()),thread,SLOT(deleteLater()));
    thread->start();
}//这个函数是个纯虚函数,我们需要实现他,他指定每个connection来的时候要做的操作

下面附这个函数详细的API:
void QTcpServer::incomingConnection ( int socketDescriptor ) [virtual protected]
This virtual function is called by QTcpServer when a new connection is available. The socketDescriptor argument is the native socket descriptor for the accepted connection.

The base implementation creates a QTcpSocket, sets the socket descriptor and then stores the QTcpSocket in an internal list of pending connections. Finally newConnection() is emitted.

Reimplement this function to alter the server’s behavior when a connection is available.
Note: If you want to handle an incoming connection as a new QTcpSocket object in another thread you have to pass the socketDescriptor to the other thread and create the QTcpSocket object there and use its setSocketDescriptor() method.

可见这个函数要赋予每个thread ID
就像 MyThread *thread = new MyThread(socketDescriptor,this);一样。
之前我开发server应用测试的时候都要开发配套的client,现在我们可以使用telnet方便的测试数据。

2013-09-12 11:03:43的屏幕截图

To be continue………………….