自己根据搜索的一些内容,写的一个简单的 Qt 多线程的例子,以备后用。
服务器端代码:
#ifndef __server_h__
#define __server_h__
#include <QTcpServer>
#include <QList>
#include <QMutex>
class ServerThread;
class ServerSocket : public QTcpServer
{
Q_OBJECT
public:
ServerSocket( quint16 port, QObject *parent = NULL );
~ServerSocket();
bool start ();
protected:
void incomingConnection ( int sockfd );
private slots:
void thrdExiting ( quint32 thrdfd );
private:
quint16 _port;
QMutex *_mutex;
QList<ServerThread*> _threads;
static quint32 _thrd_fd;
};
#endif // __server_h__
#include <QHostAddress>
#include <assert.h>
#include "server.h"
#include "thread.h"
quint32 ServerSocket::_thrd_fd = 0;
ServerSocket::ServerSocket( quint16 port, QObject *parent /* = NULL */ )
: QTcpServer( parent )
, _port( port )
{
_threads.empty();
_mutex = new QMutex();
assert( _mutex != NULL );
}
ServerSocket::~ServerSocket()
{
_mutex->lock();
_threads.clear();
_mutex->unlock();
delete _mutex;
_mutex = NULL;
}
bool ServerSocket::start()
{
if( !listen(QHostAddress::Any, _port) ) {
printf( "ServerSocket ---- listen failed at port %d !\n", _port );
return false;
}
else
return true;
}
void ServerSocket::incomingConnection( int sockfd )
{
printf( "ServerSocket ---- incoming connection %d !\n", sockfd );
ServerThread *thrd = new ServerThread( ++_thrd_fd, sockfd );
connect( thrd, SIGNAL(exiting(quint32)), this, SLOT(thrdExiting(quint32)) );
_mutex->lock();
_threads.push_back( thrd );
_mutex->unlock();
thrd->start();
}
void ServerSocket::thrdExiting( quint32 thrdfd )
{
printf( "ServerSocket ---- thread %02d is exiting !\n", thrdfd );
_mutex->lock();
int count = _threads.count();
for( int i = 0; i < count; i++ ) {
if( _threads.at(i)->getThrdfd() == thrdfd ) {
_threads.removeAt( i );
break;
}
}
_mutex->unlock();
}
#ifndef __thread_h__
#define __thread_h__
#include <QThread>
class ConnectSocket;
class ServerThread : public QThread
{
Q_OBJECT
public:
ServerThread( quint32 thrdfd, int sockfd, QObject *parent = NULL );
~ServerThread();
quint32 getThrdfd () const { return _thrd_fd; }
protected:
void run ();
signals:
void exiting ( quint32 thrdfd );
private slots:
void sockDisconnected();
private:
bool _disconnected;
quint32 _thrd_fd;
int _sock_fd;
ConnectSocket *_sock;
};
#endif // __thread_h__
#include <assert.h>
#include "thread.h"
#include "connect.h"
ServerThread::ServerThread( quint32 thrdfd, int sockfd, QObject *parent /* = NULL */ )
: QThread( parent )
, _disconnected( true )
, _thrd_fd( thrdfd )
, _sock_fd( sockfd )
{
_sock = new ConnectSocket();
_sock->setSocketDescriptor( sockfd );
_disconnected = false;
connect( _sock, SIGNAL(disconnected()), _sock, SLOT(deleteLater()) );
connect( _sock, SIGNAL(disconnected()), this, SLOT(sockDisconnected()) );
connect( this, SIGNAL(finished()), this, SLOT(deleteLater()) );
}
ServerThread::~ServerThread()
{
}
void ServerThread::run()
{
printf( "Thread %02d: thread start running !\n", _thrd_fd );
exec();
}
void ServerThread::sockDisconnected()
{
printf( "Thread %02d: connect socket %d disconnected !\n", _thrd_fd, _sock_fd );
emit exiting( _thrd_fd );
exit();
}
#ifndef __connect_h__
#define __connect_h__
#include <QTcpSocket>
class ConnectSocket : public QTcpSocket
{
Q_OBJECT
public:
ConnectSocket( QObject *parent = NULL );
signals:
void closing ( int sockfd );
protected:
void sendData ( const char *data, qint32 len );
void requestDateHandler ();
void requestTimeHandler ();
void requestExitHandler ();
private slots:
void receiveData ();
};
#endif // __connect_h__
#include <time.h>
#include "connect.h"
#include "../common.h"
ConnectSocket::ConnectSocket( QObject *parent /* = NULL */ )
: QTcpSocket( parent )
{
connect( this, SIGNAL(readyRead()), this, SLOT(receiveData()) );
connect( this, SIGNAL(disconnected()), this, SLOT(deleteLater()) );
}
void ConnectSocket::receiveData()
{
if( bytesAvailable() < MESSAGE_LEN )
return;
MESSAGE msg = { MT_NULL, 0 };
readData( (char*)&msg, MESSAGE_LEN );
switch( msg._msgtype ) {
case MT_REQUEST_DATE:
requestDateHandler();
break;
case MT_REQUEST_TIME:
requestTimeHandler();
break;
case MT_REQUEST_EXIT:
requestExitHandler();
break;
default:
printf( "ConnectSocket: receive something unknown !\n" );
return;
}
}
void ConnectSocket::sendData( const char *data, qint32 len )
{
if( NULL == data || len <= 0 )
return;
qint32 len_sended = 0;
while( len > 0 ) {
qint32 len_send = writeData( data + len_sended, len );
if( len_send <= 0 ) {
printf( "ConnectSocket: send data failed !\n" );
emit closing( socketDescriptor() );
close();
}
len_sended += len_send;
len -= len_send;
}
waitForBytesWritten();
}
void ConnectSocket::requestDateHandler()
{
printf( "ConnectSocket: receive date request !\n" );
time_t tt;
time( &tt );
tm* ptm = localtime( &tt );
MESSAGE msg = { MT_NULL, 0 };
msg._msgtype = MT_RESPONSE_DATE;
sprintf( msg._msgbuff, "%d-%02d-%02d", 1900 + ptm->tm_year, ptm->tm_mon + 1, ptm->tm_mday );
sendData( (char*)&msg, MESSAGE_LEN );
printf( "ConnectSocket: send '%s' !\n", msg._msgbuff );
}
void ConnectSocket::requestTimeHandler()
{
printf( "ConnectSocket: receive time request !\n" );
time_t tt;
time( &tt );
tm* ptm = localtime( &tt );
MESSAGE msg = { MT_NULL, 0 };
msg._msgtype = MT_RESPONSE_TIME;
sprintf( msg._msgbuff, "%02d:%02d:%02d", ptm->tm_hour, ptm->tm_min, ptm->tm_sec );
sendData( (char*)&msg, MESSAGE_LEN );
printf( "ConnectSocket: send '%s' !\n", msg._msgbuff );
}
void ConnectSocket::requestExitHandler()
{
printf( "ConnectSocket: receive exit request !\n" );
MESSAGE msg = { MT_NULL, 0 };
msg._msgtype = MT_RESPONSE_EXIT;
sendData( (char*)&msg, MESSAGE_LEN );
emit closing( socketDescriptor() );
close();
}
#include <QtCore/QCoreApplication>
#include "server.h"
#include "../common.h"
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
ServerSocket server( DEFAULT_PORT );
if( !server.start() ) {
printf( "start server failed !\n" );
return 0;
}
return a.exec();
}
客户端代码:
#ifndef __client_h__
#define __client_h__
#include <QTcpSocket>
#include "../common.h"
class ClientSocket : public QTcpSocket
{
Q_OBJECT
public:
ClientSocket( QObject *parent = NULL );
bool connectToServer ( const char *ip, quint16 port );
void sendRequest ( MsgType type );
void sendData ( const char *data, qint32 len );
private slots:
void receiveData ();
};
#endif // __client_h__
#include <QHostAddress>
#include "client.h"
ClientSocket::ClientSocket( QObject *parent /* = NULL */ )
: QTcpSocket( parent )
{
connect( this, SIGNAL(readyRead()), this, SLOT(receiveData()) );
}
bool ClientSocket::connectToServer( const char *ip, quint16 port )
{
QString strip( ip );
QHostAddress addr;
addr.setAddress( strip );
connectToHost( addr, port );
return waitForConnected();
}
void ClientSocket::receiveData()
{
if( bytesAvailable() < MESSAGE_LEN )
return;
MESSAGE msg = { MT_NULL, 0 };
readData( (char*)&msg, MESSAGE_LEN );
switch( msg._msgtype ) {
case MT_RESPONSE_DATE:
printf( "receive date: %s !\n", msg._msgbuff );
break;
case MT_RESPONSE_TIME:
printf( "receive time: %s !\n", msg._msgbuff );
break;
case MT_RESPONSE_EXIT:
printf( "receive response for exit !\n" );
disconnectFromHost();
close();
break;
default:
printf( "receive something unknown: %s !\n", msg._msgbuff );
break;
}
}
void ClientSocket::sendData( const char *data, qint32 len )
{
if( NULL == data || 0 == len )
return;
qint32 len_sended = 0;
while( len > 0 ) {
qint32 len_send = writeData( data + len_sended, len );
if( len_send <= 0 ) {
printf( "send data failed !\n" );
disconnectFromHost();
close();
return;
}
len_sended += len_send;
len -= len_send;
}
waitForBytesWritten();
waitForReadyRead();
}
void ClientSocket::sendRequest( MsgType type )
{
MESSAGE msg = { type, 0 };
sendData( (char*)&msg, MESSAGE_LEN );
}
#include <QtCore/QCoreApplication>
#include "client.h"
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
ClientSocket client;
if( !client.connectToServer(DEFAULT_IP, DEFAULT_PORT) ) {
printf( "connect to server failed !\n" );
return 0;
}
char request[128] = { 0 };
printf( "please input request('date','time','exit'): \n" );
gets( request );
while( 1 ) {
if( 0 == strcmp(request, "date") )
client.sendRequest( MT_REQUEST_DATE );
else if( 0 == strcmp(request, "time") )
client.sendRequest( MT_REQUEST_TIME );
else if( 0 == strcmp(request, "exit") ) {
client.sendRequest( MT_REQUEST_EXIT );
break;
}
else
printf( "invalid request !\n" );
memset( request, 0, sizeof(char) * 128 );
gets( request );
}
return a.exec();
}
用到的头文件:
#ifndef __common_h__
#define __common_h__
#define MAX_BUFFERSIZE 1024
#define DEFAULT_IP "127.0.0.1"
#define DEFAULT_PORT 5555
#define MESSAGE_LEN sizeof(MESSAGE)
typedef enum {
MT_NULL = 0x00,
MT_REQUEST_DATE = 0x11,
MT_REQUEST_TIME = 0x22,
MT_REQUEST_EXIT = 0x33,
MT_RESPONSE_DATE = 0x44,
MT_RESPONSE_TIME = 0x55,
MT_RESPONSE_EXIT = 0x66
} MsgType;
typedef struct _message_t {
MsgType _msgtype;
char _msgbuff[MAX_BUFFERSIZE];
} MESSAGE, *PMESSAGE;
#endif // __common_h__
效果: