qt qtcpserver 프로그래밍 입문

4996 단어
코드:
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 )));

}

좋은 웹페이지 즐겨찾기