qt qtcpserver编程入门

来源:互联网 发布:2016年5月非农数据 编辑:程序博客网 时间:2024/05/17 03:22

代码 :

  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 1class CClientSession:public QObject{Q_OBJECTpublic: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_OBJECTpublic: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 )));}



0 0
原创粉丝点击