Qt多线程初步尝试

         自己根据搜索的一些内容,写的一个简单的 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__


效果:

评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值