qt qtcpserver编程入门

代码 :

  1 连接成功后每个连接创建一个处理对象 cclientSession, 

  2 所有cclientSession对象的slot 都在另外一个线程中处理,即处理方式为创建一个线程处理所有客户端连接

  3 大文件传输需要自己用协议分片

#ifndef QNETCONTRLSERVER_H
#define QNETCONTRLSERVER_H

#include <QObject>
#include <QTcpServer>
#include <QTcpSocket>
#include <QThread>
#include <QDebug>


//通信模式 [命令id(4byte)+数据长度(4bytes)+数据(n bytes)]

#define CMD_ID_ALLINFO 1


class CClientSession:public QObject
{
	Q_OBJECT
public:
	CClientSession(QObject* parent = NULL);
	~CClientSession();
public slots:
	void onNewDescriptor(qintptr desc);
	void onSocketErr(QAbstractSocket::SocketError err);
	void onReadDataReady();
	void onResponse(QByteArray sndData);
	//void onWriteDataReady();
signals:
	void newDescriptor(qintptr handle);
	void cmdPacket(CClientSession* client,int id, QByteArray data);
	void cmdResponse(QByteArray sndData);

protected:
	void decodePacket();
private:
	QTcpSocket* m_tcpClient;
	QByteArray m_cmdPacketTemp;
};


class QNetContrlServer : public QTcpServer
{
	Q_OBJECT

public:
	QNetContrlServer(QObject *parent = NULL);
	virtual ~QNetContrlServer();

public slots:
	//void onNewConnection(qintptr descriptor);
protected:
	virtual void incomingConnection(qintptr handle);
	


private:
	QThread*    m_workThread;      
	
};

#include "qnetcontrlserver.h"
#include "mainwindow.h"

CClientSession::CClientSession(QObject* parent):QObject(parent)
{
	connect(this,SIGNAL(newDescriptor(qintptr)),this,SLOT(onNewDescriptor(qintptr)));
	connect(this,SIGNAL(cmdResponse(QByteArray )),this,SLOT(onResponse(QByteArray)));
}

CClientSession::~CClientSession()
{

}

void CClientSession::onSocketErr(QAbstractSocket::SocketError err)
{
	qDebug()<<"onSocketErr: "<<QThread::currentThreadId() << " socket error: "<<err; 
	m_tcpClient->disconnectFromHost();
}

void CClientSession::onNewDescriptor(qintptr desc)
{
	qDebug()<<"onNewDescriptor: "<<QThread::currentThreadId() << "new descriptor: "<<desc;; 
	m_tcpClient = new QTcpSocket();
	if (!m_tcpClient->setSocketDescriptor(desc))
	{
		return;
	}
	connect(m_tcpClient,SIGNAL(error(QAbstractSocket::SocketError)),this,SLOT(onSocketErr(QAbstractSocket::SocketError)));
	connect(m_tcpClient,SIGNAL(disconnected()),m_tcpClient,SLOT(deleteLater()));
	connect(m_tcpClient,SIGNAL(readyRead()),this,SLOT(onReadDataReady()));
}

void CClientSession::onReadDataReady()
{
	qDebug()<<"onReadDataReady: "<<QThread::currentThreadId(); 
	qint64 bytes = m_tcpClient->bytesAvailable();
	if (bytes > 0)
	{
		QByteArray buffer = m_tcpClient->read(bytes);
		qDebug()<<buffer.toHex();
		m_cmdPacketTemp.append(buffer);
		decodePacket();
	}
	
}

void CClientSession::decodePacket()
{
	while(m_cmdPacketTemp.size() >= 8) //允许客户端一次发送多个命令
	{
		qint32* ptr = (int*)m_cmdPacketTemp.data();
		int cmdId = *ptr++;
		int cmdSize = *ptr;
		if (m_cmdPacketTemp.size() -8 >= cmdSize  )
		{
			QByteArray data ;
			data.append(m_cmdPacketTemp.data()+8,cmdSize);
			emit cmdPacket(this,cmdId,data);
			m_cmdPacketTemp.remove(0,cmdSize+8);

			qDebug()<<"command id: "<<cmdId<<" data size: "<<cmdSize <<"data: "<< data.toHex();
		}
		else
		{
			break;
		}
	}
	return;
}

void CClientSession::onResponse(QByteArray sndData)
{
	if(sndData.size() > 0)
	{
		qint64 sndSize = m_tcpClient->write(sndData);
		if(!m_tcpClient->waitForBytesWritten()) //大文件传输请自定义协议分片传输,以免阻塞线程
		{
			m_tcpClient->disconnectFromHost();
		}
	}
	
	//delete sndData;
}



//////////////////////////////////////////////////////////////////////////
//QNetContrlServer
//////////////////////////////////////////////////////////////////////////
QNetContrlServer::QNetContrlServer(QObject *parent)
	: QTcpServer(parent)
{
	qRegisterMetaType<QAbstractSocket::SocketError>("SocketError");
	qRegisterMetaType<qintptr>("qintptr");
	m_workThread = new QThread();
	connect(m_workThread,SIGNAL(finished()),m_workThread,SLOT(deleteLater()));
	m_workThread->start();
	if(!listen(QHostAddress::Any,999))
	{

	}

}

QNetContrlServer::~QNetContrlServer()
{

}

void QNetContrlServer::incomingConnection(qintptr descriptor)
{

	qDebug()<<"incomingConnection: "<<QThread::currentThreadId() << "new descriptor: "<<descriptor;
	CClientSession* session = new CClientSession();
	//connect(session,SIGNAL(newDescriptor(qintptr)),session,SLOT(onNewDescriptor(qintptr)));
	session->moveToThread(m_workThread);
	emit session->newDescriptor(descriptor);
	//session->onNewDescriptor(descriptor);
	MainWindow* qMainWin = (MainWindow*)this->parent();
	connect(session,SIGNAL(cmdPacket(CClientSession* ,int , QByteArray )),qMainWin,SLOT(onCmdHandle(CClientSession* ,int , QByteArray )));

}



你可能感兴趣的:(qt qtcpserver编程入门)