mirror of
https://gitee.com/drabel/LibQQt.git
synced 2025-01-04 10:18:44 +08:00
update tcp and udp module
This commit is contained in:
parent
d2bccb8ccb
commit
641cd05b08
@ -25,10 +25,10 @@ QQtClient2Protocol* QQtClient2ConnectionInstance ( QObject* parent )
|
||||
|
||||
QStringList ip;
|
||||
ip << "192.168.0.101";
|
||||
s0->SetServerIPAddress ( ip );
|
||||
s0->SetServerPort ( 8500 );
|
||||
s0->setServerIPAddress ( ip );
|
||||
s0->setServerPort ( 8500 );
|
||||
|
||||
s0->SendConnectMessage();
|
||||
s0->sendConnectToHost();
|
||||
}
|
||||
|
||||
return p0;
|
||||
|
@ -21,10 +21,10 @@ QQtClientProtocol* QQtClientConnectionInstance ( QObject* parent )
|
||||
s0->installProtocol ( p0 );
|
||||
QStringList ip;
|
||||
ip << "192.168.0.100";
|
||||
s0->SetServerIPAddress ( ip );
|
||||
s0->SetServerPort ( 8001 );
|
||||
s0->setServerIPAddress ( ip );
|
||||
s0->setServerPort ( 8001 );
|
||||
|
||||
s0->SendConnectMessage();
|
||||
s0->sendConnectToHost();
|
||||
|
||||
}
|
||||
|
||||
|
@ -13,8 +13,8 @@ QQtTcpClient* QQTUpgradeClientInstance ( QObject* parent )
|
||||
ip << "222.175.114.244" << "124.133.1.54";
|
||||
//"www.QQToo.com"
|
||||
cli = new QQtTcpClient ( parent );
|
||||
cli->SetServerIPAddress ( ip );
|
||||
cli->SetServerPort ( 8089 );
|
||||
cli->setServerIPAddress ( ip );
|
||||
cli->setServerPort ( 8089 );
|
||||
}
|
||||
|
||||
return cli;
|
||||
@ -29,8 +29,8 @@ QQtTcpClient* QQTCloudClientInstance ( QObject* parent )
|
||||
QStringList ip;
|
||||
ip << "222.175.114.244" << "124.133.1.54";
|
||||
cli = new QQtTcpClient ( parent );
|
||||
cli->SetServerIPAddress ( ip );
|
||||
cli->SetServerPort ( 7079 );
|
||||
cli->setServerIPAddress ( ip );
|
||||
cli->setServerPort ( 7079 );
|
||||
}
|
||||
|
||||
return cli;
|
||||
|
@ -109,7 +109,7 @@ QQTSHARED_EXPORT void QQtSleep ( int millsecond );
|
||||
#define pline() qDebug() << __FILE__ << __LINE__/*QString("%1").arg(__LINE__, 3, 10)*/ << __func__
|
||||
#define perr(req, rsl) if(req == rsl) pline() << hex << rsl
|
||||
#define ptime() pline() << QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss zzz")
|
||||
#define pmeta() pline() << metaObject()->className()
|
||||
#define pmeta(inst) pline() << inst->metaObject()->className()
|
||||
//-----------------------
|
||||
#define packline() pline() << qDebug().nospace()
|
||||
|
||||
|
@ -1,216 +0,0 @@
|
||||
#include "qqthgbluetoothclient.h"
|
||||
#include <qqtcore.h>
|
||||
|
||||
QQtHgBluetoothClient::QQtHgBluetoothClient ( QBluetoothServiceInfo::Protocol socketType, QObject* parent ) :
|
||||
QBluetoothSocket ( socketType, parent )
|
||||
{
|
||||
initSocket();
|
||||
}
|
||||
|
||||
QQtHgBluetoothClient::QQtHgBluetoothClient ( QObject* parent ) : QBluetoothSocket ( parent )
|
||||
{
|
||||
initSocket();
|
||||
}
|
||||
|
||||
void QQtHgBluetoothClient::initSocket()
|
||||
{
|
||||
connect ( this, SIGNAL ( stateChanged ( QBluetoothSocket::SocketState ) ),
|
||||
this, SLOT ( socketStateChanged ( QBluetoothSocket::SocketState ) ) );
|
||||
// connected
|
||||
connect ( this, SIGNAL ( connected() ),
|
||||
this, SLOT ( socketConnected() ) );
|
||||
// disconnected
|
||||
connect ( this, SIGNAL ( disconnected() ),
|
||||
this, SLOT ( socketDisconnect() ) );
|
||||
// error
|
||||
connect ( this, SIGNAL ( error ( QBluetoothSocket::SocketError ) ),
|
||||
this, SLOT ( socketErrorOccured ( QBluetoothSocket::SocketError ) ) );
|
||||
|
||||
connect ( this, SIGNAL ( readyRead() ),
|
||||
this, SLOT ( readyReadData() ) );
|
||||
|
||||
connect ( this, SIGNAL ( bytesWritten ( qint64 ) ),
|
||||
this, SLOT ( updateProgress ( qint64 ) ) );
|
||||
|
||||
connect ( this, SIGNAL ( bytesWritten ( qint64 ) ),
|
||||
this, SIGNAL ( signalUpdateProgress ( qint64 ) ) );
|
||||
|
||||
m_PORT = 0;
|
||||
m_protocol = nullptr;
|
||||
}
|
||||
|
||||
void QQtHgBluetoothClient::installProtocol ( QQtHgProtocol* stack )
|
||||
{
|
||||
if ( m_protocol )
|
||||
return;
|
||||
|
||||
m_protocol = stack;
|
||||
connect ( m_protocol, SIGNAL ( write ( const QByteArray& ) ),
|
||||
this, SLOT ( write ( const QByteArray& ) ) );
|
||||
}
|
||||
|
||||
void QQtHgBluetoothClient::uninstallProtocol ( QQtHgProtocol* stack )
|
||||
{
|
||||
Q_UNUSED ( stack )
|
||||
|
||||
if ( !m_protocol )
|
||||
return;
|
||||
|
||||
disconnect ( m_protocol, SIGNAL ( write ( const QByteArray& ) ),
|
||||
this, SLOT ( write ( const QByteArray& ) ) );
|
||||
m_protocol = NULL;
|
||||
}
|
||||
|
||||
QQtHgProtocol* QQtHgBluetoothClient::installedProtocol()
|
||||
{
|
||||
return m_protocol;
|
||||
}
|
||||
|
||||
void QQtHgBluetoothClient::sendConnectMessage()
|
||||
{
|
||||
pline() << isOpen() << state();
|
||||
|
||||
if ( !isOpen() )
|
||||
{
|
||||
connectToSingelHost();
|
||||
return;
|
||||
}
|
||||
|
||||
if ( state() == ServiceLookupState ||
|
||||
state() == ConnectingState )
|
||||
{
|
||||
emit signalConnecting();
|
||||
return;
|
||||
}
|
||||
|
||||
if ( state() == ConnectedState )
|
||||
emit signalConnectSucc();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
int QQtHgBluetoothClient::sendDisConnectFromHost()
|
||||
{
|
||||
pline() << isOpen() << state();
|
||||
|
||||
if ( isOpen() )
|
||||
{
|
||||
#if defined(__WIN32__) || defined (__WIN64__)
|
||||
;
|
||||
#else
|
||||
shutdown ( this->socketDescriptor(), SHUT_RDWR );
|
||||
#endif
|
||||
disconnectFromService();
|
||||
close();
|
||||
emit signalDisConnectSucc();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief QQtHgBluetoothClient::socketStateChanged
|
||||
* @param eSocketState
|
||||
* 状态函数
|
||||
*/
|
||||
void QQtHgBluetoothClient::socketStateChanged ( QBluetoothSocket::SocketState eSocketState )
|
||||
{
|
||||
pline() << eSocketState;
|
||||
|
||||
switch ( eSocketState )
|
||||
{
|
||||
case ServiceLookupState:
|
||||
case ConnectingState:
|
||||
break;
|
||||
|
||||
case ConnectedState:
|
||||
break;
|
||||
|
||||
case ClosingState:
|
||||
break;
|
||||
|
||||
case UnconnectedState:
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief QQtHgBluetoothClient::socketErrorOccured
|
||||
* @param e
|
||||
* 状态函数
|
||||
*/
|
||||
void QQtHgBluetoothClient::socketErrorOccured ( QBluetoothSocket::SocketError e )
|
||||
{
|
||||
/*
|
||||
* 在错误状态下重新连接其他热点,直到确定连接类型,写入配置文件
|
||||
*/
|
||||
pline() << e << errorString();
|
||||
|
||||
switch ( e )
|
||||
{
|
||||
case HostNotFoundError:
|
||||
default:
|
||||
emit signalConnectFail();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief QQtHgBluetoothClient::socketConnected
|
||||
* 功能接口
|
||||
*/
|
||||
void QQtHgBluetoothClient::socketConnected()
|
||||
{
|
||||
pline() << peerName() << peerAddress().toString() << peerPort();
|
||||
/*
|
||||
* 这个步骤,socket重建,资源重新开始
|
||||
*/
|
||||
emit signalConnectSucc();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief QQtHgBluetoothClient::socketDisconnect
|
||||
* 功能接口
|
||||
*/
|
||||
void QQtHgBluetoothClient::socketDisconnect()
|
||||
{
|
||||
pline();
|
||||
}
|
||||
|
||||
void QQtHgBluetoothClient::updateProgress ( qint64 bytes )
|
||||
{
|
||||
Q_UNUSED ( bytes )
|
||||
//pline() << bytes;
|
||||
}
|
||||
|
||||
void QQtHgBluetoothClient::connectToSingelHost()
|
||||
{
|
||||
if ( !m_uuid.isNull() )
|
||||
{
|
||||
connectToService ( m_serverIP, m_uuid );
|
||||
pline() << peerName() << m_uuid;
|
||||
}
|
||||
else if ( m_serviceInfo.isValid() )
|
||||
{
|
||||
connectToService ( m_serviceInfo );
|
||||
pline() << m_serviceInfo;
|
||||
}
|
||||
else if ( m_PORT != 0 )
|
||||
{
|
||||
connectToService ( m_serverIP, m_PORT );
|
||||
pline() << peerName() << m_PORT;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void QQtHgBluetoothClient::readyReadData()
|
||||
{
|
||||
QByteArray bytes;
|
||||
bytes = readAll();
|
||||
m_protocol->translator ( bytes );
|
||||
}
|
@ -1,72 +0,0 @@
|
||||
#ifndef QQTHGBLUETOOTHCLIENT_H
|
||||
#define QQTHGBLUETOOTHCLIENT_H
|
||||
|
||||
#include <qbluetoothsocket.h>
|
||||
#include "qqthgprotocol.h"
|
||||
#include "qqt-local.h"
|
||||
|
||||
class QQTSHARED_EXPORT QQtHgBluetoothClient : public QBluetoothSocket
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit QQtHgBluetoothClient ( QBluetoothServiceInfo::Protocol socketType = QBluetoothServiceInfo::RfcommProtocol,
|
||||
QObject* parent = nullptr );
|
||||
explicit QQtHgBluetoothClient ( QObject* parent = nullptr );
|
||||
|
||||
/**
|
||||
* @brief setServiceInfo
|
||||
* 设置目标蓝牙地址
|
||||
*/
|
||||
void setServiceInfo ( const QBluetoothServiceInfo& serviceinfo ) { m_serviceInfo = serviceinfo; }
|
||||
void setServiceAddress ( const QBluetoothAddress& address ) { m_serverIP = address; }
|
||||
/**
|
||||
* @brief setServicePort
|
||||
* @param p
|
||||
* 设置目标蓝牙端口 和UUID选择一个就可以
|
||||
*/
|
||||
void setServicePort ( quint16 p = 8888 ) { m_PORT = p; }
|
||||
void setServiceUUid ( const QBluetoothUuid& uuid ) { m_uuid = uuid; }
|
||||
|
||||
void installProtocol ( QQtHgProtocol* stack );
|
||||
void uninstallProtocol ( QQtHgProtocol* stack );
|
||||
QQtHgProtocol* installedProtocol();
|
||||
|
||||
void sendConnectMessage();
|
||||
int sendDisConnectFromHost();
|
||||
|
||||
signals:
|
||||
|
||||
public slots:
|
||||
|
||||
signals:
|
||||
void signalConnecting();
|
||||
void signalConnectSucc();
|
||||
void signalConnectFail();//
|
||||
void signalDisConnectSucc();//maybe
|
||||
void signalDisConnectFail();//
|
||||
void signalUpdateProgress ( qint64 value );
|
||||
|
||||
|
||||
private slots:
|
||||
void socketStateChanged ( QBluetoothSocket::SocketState );
|
||||
void socketErrorOccured ( QBluetoothSocket::SocketError );
|
||||
void socketConnected();
|
||||
void socketDisconnect();
|
||||
void updateProgress ( qint64 );
|
||||
|
||||
protected slots:
|
||||
void readyReadData();
|
||||
|
||||
private:
|
||||
void connectToSingelHost();
|
||||
void initSocket();
|
||||
|
||||
QQtHgProtocol* m_protocol;
|
||||
|
||||
QBluetoothServiceInfo m_serviceInfo;
|
||||
QBluetoothAddress m_serverIP;
|
||||
quint16 m_PORT;
|
||||
QBluetoothUuid m_uuid;
|
||||
};
|
||||
|
||||
#endif // QQTHGBLUETOOTHCLIENT_H
|
@ -1,50 +0,0 @@
|
||||
#include "qqthgbluetoothserver.h"
|
||||
#include "qqthgbluetoothclient.h"
|
||||
|
||||
QQtHgBluetoothServer::QQtHgBluetoothServer ( QBluetoothServiceInfo::Protocol serverType,
|
||||
QObject* parent ) : QBluetoothServer ( serverType, parent )
|
||||
{
|
||||
connect ( this, SIGNAL ( newConnection() ),
|
||||
this, SLOT ( comingNewConnection() ) );
|
||||
}
|
||||
|
||||
QQtHgBluetoothServer::~QQtHgBluetoothServer()
|
||||
{
|
||||
close();
|
||||
}
|
||||
|
||||
|
||||
void QQtHgBluetoothServer::comingNewConnection()
|
||||
{
|
||||
if ( !hasPendingConnections() )
|
||||
return;
|
||||
|
||||
QBluetoothSocket* comingSocket = nextPendingConnection();
|
||||
QQtHgBluetoothClient* clientSocket = new QQtHgBluetoothClient ( this );
|
||||
connect ( clientSocket, SIGNAL ( disconnected() ), clientSocket, SLOT ( deleteLater() ) );
|
||||
clientSocket->installProtocol ( m_protocol );
|
||||
clientSocket->setSocketDescriptor ( comingSocket->socketDescriptor(), QBluetoothServiceInfo::RfcommProtocol );
|
||||
}
|
||||
|
||||
void QQtHgBluetoothServer::installProtocol ( QQtHgProtocol* stack )
|
||||
{
|
||||
if ( m_protocol )
|
||||
return;
|
||||
|
||||
m_protocol = stack;
|
||||
}
|
||||
|
||||
void QQtHgBluetoothServer::uninstallProtocol ( QQtHgProtocol* stack )
|
||||
{
|
||||
Q_UNUSED ( stack )
|
||||
|
||||
if ( !m_protocol )
|
||||
return;
|
||||
|
||||
m_protocol = NULL;
|
||||
}
|
||||
|
||||
QQtHgProtocol* QQtHgBluetoothServer::installedProtocol()
|
||||
{
|
||||
return m_protocol;
|
||||
}
|
@ -1,32 +0,0 @@
|
||||
#ifndef QQTHGBLUETOOTHSERVER_H
|
||||
#define QQTHGBLUETOOTHSERVER_H
|
||||
|
||||
#include <QBluetoothServer>
|
||||
#include "qqthgprotocol.h"
|
||||
#include <qqt-local.h>
|
||||
|
||||
class QQTSHARED_EXPORT QQtHgBluetoothServer : public QBluetoothServer
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit QQtHgBluetoothServer ( QBluetoothServiceInfo::Protocol serverType, QObject* parent = nullptr );
|
||||
~QQtHgBluetoothServer();
|
||||
|
||||
void installProtocol ( QQtHgProtocol* stack );
|
||||
void uninstallProtocol ( QQtHgProtocol* stack );
|
||||
QQtHgProtocol* installedProtocol();
|
||||
|
||||
signals:
|
||||
|
||||
public slots:
|
||||
|
||||
signals:
|
||||
|
||||
private slots:
|
||||
void comingNewConnection();
|
||||
|
||||
private:
|
||||
QQtHgProtocol* m_protocol;
|
||||
};
|
||||
|
||||
#endif // QQTHGBLUETOOTHSERVER_H
|
@ -1,27 +0,0 @@
|
||||
#include "qqthgprotocol.h"
|
||||
|
||||
QQtHgProtocol::QQtHgProtocol ( QObject* parent ) : QObject ( parent )
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
QQtHgProtocol::~QQtHgProtocol()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void QQtHgProtocol::createClientBuffer ( const QAbstractSocket* client )
|
||||
{
|
||||
if ( mClientBuffer.contains ( client ) )
|
||||
return;
|
||||
|
||||
mClientBuffer.insert ( client, QByteArray() );
|
||||
}
|
||||
|
||||
void QQtHgProtocol::deleteClientBuffer ( const QAbstractSocket* client )
|
||||
{
|
||||
if ( !mClientBuffer.contains ( client ) )
|
||||
return;
|
||||
|
||||
mClientBuffer.remove ( client );
|
||||
}
|
@ -1,111 +0,0 @@
|
||||
#ifndef QQTHGPROTOCOL_H
|
||||
#define QQTHGPROTOCOL_H
|
||||
|
||||
#include <QObject>
|
||||
#include <qqt-local.h>
|
||||
#include "qqtcore.h"
|
||||
#include "qqtmessage.h"
|
||||
|
||||
/**
|
||||
* @brief The QQtHgProtocol class
|
||||
* very good ideology and impliment
|
||||
*/
|
||||
class QQTSHARED_EXPORT QQtHgProtocol : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit QQtHgProtocol ( QObject* parent = 0 );
|
||||
virtual ~QQtHgProtocol();
|
||||
|
||||
signals:
|
||||
/**
|
||||
* @brief notifyToHgProtocolManager
|
||||
* 为服务器功能的ProtocolManager添加的,用户不必管理,必要时调用。
|
||||
*
|
||||
* 用户继承下去的协议里,在dispatcher的recv函数里,如果必要把收到的信息传递给上层,
|
||||
* 那么通过emit notifyToProtocolManager,传递给ProtocolManager
|
||||
* BusinessLevel对这些接收到的信息感兴趣,
|
||||
* 那么通过连接ProtocolManager的notifyToBusinessLevel对拿到的信息进行处理,会包括协议句柄,使用户方便写回客户。
|
||||
* 用户在子类主动调用
|
||||
* @param client
|
||||
* @param self
|
||||
* @param message
|
||||
*/
|
||||
void notifyToHgProtocolManager ( const QAbstractSocket* client, const QQtHgProtocol* self, const QQtMessage* message );
|
||||
|
||||
Q_SIGNALS:
|
||||
/**
|
||||
* 群发
|
||||
* 这个write会发给所有的client instance
|
||||
*/
|
||||
qint64 write ( const QByteArray& );
|
||||
/**
|
||||
* 单发
|
||||
*/
|
||||
qint64 writeToClient ( const QAbstractSocket* client, const QByteArray& );
|
||||
/**
|
||||
* @brief notifyForDispatcher
|
||||
* 这是个上报报文的信号,在每次dispatcher的时候会自动调用。
|
||||
* 上报的一段字节序,正好一段报文。
|
||||
* @param client
|
||||
* @param bytes
|
||||
*/
|
||||
void notifyForDispatcher ( const QAbstractSocket* client, const QByteArray& bytes );
|
||||
/*
|
||||
* 以下函数,用户必须继承下去,重写,need override
|
||||
*/
|
||||
protected:
|
||||
/**
|
||||
* @brief 最小包长
|
||||
* @return
|
||||
*/
|
||||
inline virtual quint16 minlength() {
|
||||
return 0x00;
|
||||
}
|
||||
/**
|
||||
* @brief 最大包长
|
||||
* @return
|
||||
*/
|
||||
inline virtual quint16 maxlength() {
|
||||
return 0x07FF;
|
||||
}
|
||||
/**
|
||||
* @brief 语法解析器 从流中解析报文长度
|
||||
* 不同用户的协议,这个,这一个协议,切分方式是一样的。
|
||||
* @param 接收到的数据段
|
||||
* @return 按照协议解析到的数据长度 可用,继续接收,丢弃,粘包。
|
||||
*/
|
||||
inline virtual quint16 splitter ( const QByteArray& bytes ) { return 0; }
|
||||
/**
|
||||
* @brief 语义解析器
|
||||
* 不同用户的信息,在这里会被区分开。
|
||||
* @param 数据包
|
||||
* @return
|
||||
*/
|
||||
inline virtual void dispatcher ( const QAbstractSocket* client, const QByteArray& bytes ) { return; }
|
||||
|
||||
/*以下和用户无关*/
|
||||
public:
|
||||
/**
|
||||
* @brief 协议处理器
|
||||
* 这个处理器是给HgSocket用的,不是给客户用的。
|
||||
* ProtocolManager,安装了这个协议,需要用户句柄。
|
||||
* virtual是为QQt内部的协议提供的。
|
||||
* @param Qt通讯口readAll()读到的bytes
|
||||
* @return
|
||||
*/
|
||||
virtual void translator ( const QAbstractSocket* client, const QByteArray& bytes ) { return; }
|
||||
/**
|
||||
* 用于给Client提供独立的IOBuffer。
|
||||
* 用于流式传输协议,
|
||||
* 数据报式传输协议不需要。
|
||||
* 给HgSocket用,用户无关
|
||||
*/
|
||||
void createClientBuffer ( const QAbstractSocket* client );
|
||||
void deleteClientBuffer ( const QAbstractSocket* client );
|
||||
QMap<QAbstractSocket*, QByteArray>& clientBuffer() { return mClientBuffer; }
|
||||
private:
|
||||
QMap<QAbstractSocket*, QByteArray> mClientBuffer;
|
||||
};
|
||||
|
||||
#endif // QQTHGPROTOCOL_H
|
@ -1,39 +0,0 @@
|
||||
#include "qqthgprotocolmanager.h"
|
||||
|
||||
QQtHgProtocolManager::QQtHgProtocolManager ( QObject* parent ) : QObject ( parent )
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
QQtHgProtocolManager::~QQtHgProtocolManager()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void QQtHgProtocolManager::installProtocol ( QQtHgProtocol* stack )
|
||||
{
|
||||
if ( mProtoList.contains ( stack ) )
|
||||
return;
|
||||
|
||||
mProtoList.push_back ( stack );
|
||||
connect ( stack, SIGNAL ( notifyToHgProtocolManager ( const QAbstractSocket*, const QQtHgProtocol*,
|
||||
const QQtMessage* ) ),
|
||||
this, SIGNAL ( notifyToBusinessLevel ( const QAbstractSocket*, const QQtHgProtocol*, const QQtMessage* ) ) );
|
||||
}
|
||||
|
||||
void QQtHgProtocolManager::uninstallProtocol ( QQtHgProtocol* stack )
|
||||
{
|
||||
if ( !mProtoList.contains ( stack ) )
|
||||
return;
|
||||
|
||||
mProtoList.removeOne ( stack );
|
||||
disconnect ( stack, SIGNAL ( notifyToHgProtocolManager ( const QAbstractSocket*, const QQtHgProtocol*,
|
||||
const QQtMessage* ) ),
|
||||
this, SIGNAL ( notifyToBusinessLevel ( const QAbstractSocket*, const QQtHgProtocol*, const QQtMessage* ) ) );
|
||||
}
|
||||
|
||||
QList<QQtHgProtocol*>& QQtHgProtocolManager::installedProtocol()
|
||||
{
|
||||
return mProtoList;
|
||||
}
|
||||
|
@ -1,87 +0,0 @@
|
||||
#ifndef QQTHGPROTOCOLMANAGER_H
|
||||
#define QQTHGPROTOCOLMANAGER_H
|
||||
|
||||
#include <QObject>
|
||||
#include "qqtmessage.h"
|
||||
#include "qqthgprotocol.h"
|
||||
#include <qqtobjectmanager.h>
|
||||
|
||||
#include "qqtcore.h"
|
||||
#include <qqt-local.h>
|
||||
|
||||
/**
|
||||
* @brief The QQtHgProtocolManager class
|
||||
* very good ideology and impliment
|
||||
* 用于管理多个Protocol实例
|
||||
* 用户实现的协议注册到这里,当协议当中有消息需要告知业务层,从这里告知。
|
||||
*
|
||||
* 注释:
|
||||
* 讲解notify过程,
|
||||
* QQtSocketServer,管理QQtSocketClient句柄
|
||||
* QQtHgProtocolManager,管理QQtHgProtocol句柄
|
||||
* cli -> proto, dispatcher, recvFunc, notifyToProtocolManager,
|
||||
* protoManager -> businessLevel, 完全信号传递。
|
||||
*
|
||||
* 关于识别Protocl,
|
||||
* 这个Manager可以安装多个Protocol,并且用于多个客户端
|
||||
* Multi-protocol,Multi-client。
|
||||
* Multi-message。
|
||||
*
|
||||
* 注意:
|
||||
* 多客户端,单协议,比较多见。
|
||||
* 单客户端,多协议,不多见。
|
||||
* 单客户端,单协议,最多使用。
|
||||
* 多客户端,多协议,很晕眩。
|
||||
*
|
||||
* 这个类的信号主要用于,业务层感兴趣的信息发送到上层。
|
||||
*/
|
||||
class QQTSHARED_EXPORT QQtHgProtocolManager : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit QQtHgProtocolManager ( QObject* parent = 0 );
|
||||
virtual ~QQtHgProtocolManager();
|
||||
|
||||
//这里列举的函数是给BusinessLevel用的,Protocol里面不要用
|
||||
//findProtocolInstanceByXXX(...);
|
||||
//findClientInfoByProtocolInstance(Protocol);
|
||||
//sendMessageToProtocolInstance(Protocol, Message);
|
||||
//sendMessageToAllProtocolInstance(...);
|
||||
|
||||
signals:
|
||||
/**
|
||||
* @brief notifyToUser
|
||||
* 这个信号是给用户的,用户可以接收下来,转换为自己的协议使用。注释:如果必要。一般在协议里就处理完了。
|
||||
* 用户使用这个ProtocolManager,Protocol需要提交给用户处理的命令,提交到这里,在这里提交给用户。
|
||||
* ProtocolManager -> BusinessLevel
|
||||
* 某个用户 安装的某个协议 发来某个消息
|
||||
* @param client
|
||||
* @param protocol
|
||||
* @param message
|
||||
*/
|
||||
void notifyToBusinessLevel ( const QAbstractSocket* client, const QQtHgProtocol* protocol, const QQtMessage* message );
|
||||
/**
|
||||
* @brief sendMessageToClient
|
||||
* 这个信号是给用户的,
|
||||
* 发送给某个用户,按照某个协议,发送的消息。
|
||||
* @param client
|
||||
* @param protocol
|
||||
* @param message
|
||||
*/
|
||||
void sendMessageToClientSocket ( const QAbstractSocket* client, const QQtHgProtocol* protocol,
|
||||
const QQtMessage* message );
|
||||
|
||||
public:
|
||||
/**
|
||||
* 允许安装多个协议
|
||||
* client需要解析的协议都在这里,一个client会进入这里的每一个协议。
|
||||
*/
|
||||
void installProtocol ( QQtHgProtocol* stack );
|
||||
void uninstallProtocol ( QQtHgProtocol* stack );
|
||||
QList<QQtHgProtocol*>& installedProtocol();
|
||||
|
||||
private:
|
||||
QList<QQtHgProtocol*> mProtoList;
|
||||
};
|
||||
|
||||
#endif // QQTHGPROTOCOLMANAGER_H
|
@ -1,258 +0,0 @@
|
||||
#include "qqthgtcpclient.h"
|
||||
|
||||
#include <QTcpSocket>
|
||||
#include <QHostInfo>
|
||||
|
||||
#include "qqtcore.h"
|
||||
|
||||
QQtHgTcpClient::QQtHgTcpClient ( QObject* parent ) :
|
||||
QTcpSocket ( parent )
|
||||
{
|
||||
connect ( this, SIGNAL ( stateChanged ( QAbstractSocket::SocketState ) ), this,
|
||||
SLOT ( socketStateChanged ( QAbstractSocket::SocketState ) ) );
|
||||
// connected
|
||||
connect ( this, SIGNAL ( connected() ), this, SLOT ( socketConnected() ) );
|
||||
// disconnected
|
||||
connect ( this, SIGNAL ( disconnected() ), this, SLOT ( socketDisconnect() ) );
|
||||
// domain
|
||||
connect ( this, SIGNAL ( hostFound() ), this, SLOT ( domainHostFound() ) );
|
||||
// error
|
||||
connect ( this, SIGNAL ( error ( QAbstractSocket::SocketError ) ), this,
|
||||
SLOT ( socketErrorOccured ( QAbstractSocket::SocketError ) ) );
|
||||
|
||||
connect ( this, SIGNAL ( readyRead() ), this, SLOT ( readyReadData() ) );
|
||||
|
||||
connect ( this, SIGNAL ( bytesWritten ( qint64 ) ), this, SLOT ( updateProgress ( qint64 ) ) );
|
||||
|
||||
connect ( this, SIGNAL ( bytesWritten ( qint64 ) ), this, SIGNAL ( signalUpdateProgress ( qint64 ) ) );
|
||||
|
||||
/*
|
||||
* 心情很好,但是给自己带来麻烦顾虑,也不能给系统节约多少什么资源, Qt::QueuedConnection);
|
||||
*/
|
||||
|
||||
setSocketOption ( QAbstractSocket::LowDelayOption, 0 );
|
||||
setSocketOption ( QAbstractSocket::KeepAliveOption, 0 );
|
||||
setReadBufferSize ( _TCP_RECVBUFF_SIZE );
|
||||
|
||||
m_PORT = 0;
|
||||
/*
|
||||
* 启动连接
|
||||
*/
|
||||
eConType = 0;
|
||||
m_protocolManager = NULL;
|
||||
}
|
||||
|
||||
QQtHgTcpClient::~QQtHgTcpClient()
|
||||
{
|
||||
}
|
||||
|
||||
void QQtHgTcpClient::installProtocolManager ( QQtHgProtocolManager* stackGroup )
|
||||
{
|
||||
if ( m_protocolManager )
|
||||
return;
|
||||
|
||||
m_protocolManager = stackGroup;
|
||||
|
||||
QListIterator<QQtHgProtocol*> itor ( m_protocolManager->installedProtocol() );
|
||||
while ( itor.hasNext() )
|
||||
{
|
||||
//安装一个一个的句柄
|
||||
QQtHgProtocol* stack = itor.next();
|
||||
connect ( stack, SIGNAL ( write ( const QByteArray& ) ),
|
||||
this, SLOT ( slotWriteData ( const QByteArray& ) ) );
|
||||
stack->createClientBuffer ( this );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void QQtHgTcpClient::uninstallProtocolManager ( QQtHgProtocolManager* stackGroup )
|
||||
{
|
||||
Q_UNUSED ( stackGroup )
|
||||
|
||||
if ( !m_protocolManager )
|
||||
return;
|
||||
|
||||
QListIterator<QQtHgProtocol*> itor ( m_protocolManager->installedProtocol() );
|
||||
while ( itor.hasNext() )
|
||||
{
|
||||
//安装一个一个的句柄
|
||||
QQtHgProtocol* stack = itor.next();
|
||||
disconnect ( stack, SIGNAL ( write ( const QByteArray& ) ),
|
||||
this, SLOT ( slotWriteData ( const QByteArray& ) ) );
|
||||
stack->deleteClientBuffer ( this );
|
||||
}
|
||||
|
||||
m_protocolManager = NULL;
|
||||
}
|
||||
|
||||
QQtHgProtocolManager* QQtHgTcpClient::installedProtocolManager()
|
||||
{
|
||||
return m_protocolManager;
|
||||
}
|
||||
|
||||
void QQtHgTcpClient::SendConnectMessage()
|
||||
{
|
||||
pline() << isValid() << isOpen() << state();
|
||||
|
||||
if ( !isValid() && !isOpen() )
|
||||
{
|
||||
connectToSingelHost();
|
||||
return;
|
||||
}
|
||||
|
||||
if ( state() == HostLookupState ||
|
||||
state() == ConnectingState )
|
||||
{
|
||||
emit signalConnecting();
|
||||
return;
|
||||
}
|
||||
|
||||
if ( state() == ConnectedState )
|
||||
emit signalConnectSucc();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
int QQtHgTcpClient::SendDisConnectFromHost()
|
||||
{
|
||||
pline() << isValid() << isOpen() << state();
|
||||
|
||||
if ( isValid() || isOpen() )
|
||||
{
|
||||
#if defined(__WIN32__) || defined (__WIN64__)
|
||||
;
|
||||
#else
|
||||
shutdown ( this->socketDescriptor(), SHUT_RDWR );
|
||||
#endif
|
||||
disconnectFromHost();
|
||||
waitForDisconnected();
|
||||
close();
|
||||
emit signalDisConnectSucc();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void QQtHgTcpClient::domainHostFound()
|
||||
{
|
||||
pline();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief QQtHgTcpClient::socketStateChanged
|
||||
* @param eSocketState
|
||||
* 状态函数
|
||||
*/
|
||||
void QQtHgTcpClient::socketStateChanged ( QAbstractSocket::SocketState eSocketState )
|
||||
{
|
||||
pline() << eSocketState;
|
||||
|
||||
switch ( eSocketState )
|
||||
{
|
||||
case QAbstractSocket::HostLookupState:
|
||||
case QAbstractSocket::ConnectingState:
|
||||
break;
|
||||
|
||||
case QAbstractSocket::ConnectedState:
|
||||
break;
|
||||
|
||||
case QAbstractSocket::ClosingState:
|
||||
break;
|
||||
|
||||
case QAbstractSocket::UnconnectedState:
|
||||
eConType++;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief QQtHgTcpClient::socketErrorOccured
|
||||
* @param e
|
||||
* 状态函数
|
||||
*/
|
||||
void QQtHgTcpClient::socketErrorOccured ( QAbstractSocket::SocketError e )
|
||||
{
|
||||
/*
|
||||
* 在错误状态下重新连接其他热点,直到确定连接类型,写入配置文件
|
||||
*/
|
||||
pline() << e;
|
||||
|
||||
switch ( e )
|
||||
{
|
||||
case QAbstractSocket::RemoteHostClosedError:
|
||||
break;
|
||||
|
||||
case QAbstractSocket::HostNotFoundError:
|
||||
default:
|
||||
emit signalConnectFail();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief QQtHgTcpClient::socketConnected
|
||||
* 功能接口
|
||||
*/
|
||||
void QQtHgTcpClient::socketConnected()
|
||||
{
|
||||
pline() << peerName() << peerAddress().toString() << peerPort();
|
||||
/*
|
||||
* 这个步骤,socket重建,资源重新开始
|
||||
*/
|
||||
emit signalConnectSucc();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief QQtHgTcpClient::socketDisconnect
|
||||
* 功能接口
|
||||
*/
|
||||
void QQtHgTcpClient::socketDisconnect()
|
||||
{
|
||||
pline();
|
||||
}
|
||||
|
||||
void QQtHgTcpClient::updateProgress ( qint64 bytes )
|
||||
{
|
||||
Q_UNUSED ( bytes )
|
||||
//pline() << bytes;
|
||||
}
|
||||
|
||||
void QQtHgTcpClient::connectToSingelHost()
|
||||
{
|
||||
int contype = eConType % m_serverIP.size();
|
||||
QString ip = m_serverIP.at ( contype );
|
||||
connectToHost ( QHostAddress ( ip ), m_PORT );
|
||||
|
||||
pline() << peerName() << m_PORT;
|
||||
}
|
||||
|
||||
|
||||
void QQtHgTcpClient::readyReadData()
|
||||
{
|
||||
//self, protocol, message
|
||||
if ( !m_protocolManager )
|
||||
{
|
||||
pline() << "please install protocol manager for your client.";
|
||||
deleteLater();
|
||||
return;
|
||||
}
|
||||
|
||||
QByteArray bytes;
|
||||
bytes = readAll();
|
||||
|
||||
QListIterator<QQtHgProtocol*> itor ( m_protocolManager->installedProtocol() );
|
||||
while ( itor.hasNext() )
|
||||
{
|
||||
QQtHgProtocol* protocol = itor.next();
|
||||
protocol->translator ( this, bytes );
|
||||
}
|
||||
}
|
||||
|
||||
void QQtHgTcpClient::slotWriteData ( const QByteArray& data )
|
||||
{
|
||||
write ( data );
|
||||
}
|
@ -1,85 +0,0 @@
|
||||
/**************************************************
|
||||
* QQtHgTcpClient
|
||||
* 在一个工程当中仅仅存在一个实例,通过调用QQtHgTcpClient实现。
|
||||
**************************************************/
|
||||
#ifndef QQTHGTCPCLIENT_H
|
||||
#define QQTHGTCPCLIENT_H
|
||||
|
||||
#include <QTcpSocket>
|
||||
#include "QStringList"
|
||||
#include "qqthgprotocolmanager.h"
|
||||
|
||||
#include "qqt-local.h"
|
||||
#include "qqtcore.h"
|
||||
|
||||
#define QQT_TCP_SOCKET 0
|
||||
#define QQT_SOCKET 1
|
||||
#define QQT_THREAD 0
|
||||
#define _TCP_BLOCKDATA_SIZE 0x400
|
||||
#define _TCP_RECVBUFF_SIZE 0x800
|
||||
|
||||
/**
|
||||
* @brief 客户端决定和协议的交互关系;只跟协议打交道;
|
||||
* 处理粘包,数少包。
|
||||
* 通过安装协议,支持客户通信
|
||||
* 打开,
|
||||
* 发送,接收,splitter,dispatcher
|
||||
* 关闭。
|
||||
*/
|
||||
class QQTSHARED_EXPORT QQtHgTcpClient : public QTcpSocket
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit QQtHgTcpClient ( QObject* parent = 0 );
|
||||
virtual ~QQtHgTcpClient();
|
||||
|
||||
void SetServerIPAddress ( QStringList ip ) { m_serverIP = ip; }
|
||||
void SetServerPort ( quint32 p = 7079 ) { m_PORT = p; }
|
||||
|
||||
void installProtocolManager ( QQtHgProtocolManager* stackGroup );
|
||||
void uninstallProtocolManager ( QQtHgProtocolManager* stackGroup );
|
||||
QQtHgProtocolManager* installedProtocolManager();
|
||||
|
||||
void SendConnectMessage();
|
||||
int SendDisConnectFromHost();
|
||||
|
||||
signals:
|
||||
void signalConnecting();
|
||||
void signalConnectSucc();
|
||||
void signalConnectFail();//
|
||||
void signalDisConnectSucc();//maybe
|
||||
void signalDisConnectFail();//
|
||||
void signalUpdateProgress ( qint64 value );
|
||||
|
||||
|
||||
private slots:
|
||||
void domainHostFound();
|
||||
void socketStateChanged ( QAbstractSocket::SocketState );
|
||||
void socketErrorOccured ( QAbstractSocket::SocketError );
|
||||
void socketConnected();
|
||||
void socketDisconnect();
|
||||
void updateProgress ( qint64 );
|
||||
|
||||
protected slots:
|
||||
void readyReadData();
|
||||
void slotWriteData ( const QByteArray& );
|
||||
|
||||
private:
|
||||
void connectToSingelHost();
|
||||
|
||||
/*
|
||||
* TODO:如果文件传输影响到了UI线程,那么需要将QTcpSocket局部变量化
|
||||
* 阻塞UI不必考虑此处
|
||||
* 非阻塞UI,UI却工作很慢,考虑此处。
|
||||
*/
|
||||
//QTcpSocket* m_sock;
|
||||
|
||||
private:
|
||||
QQtHgProtocolManager* m_protocolManager;
|
||||
quint32 eConType;
|
||||
QStringList m_serverIP;
|
||||
quint32 m_PORT;
|
||||
};
|
||||
|
||||
|
||||
#endif // QQTHGTCPCLIENT_H
|
@ -1,70 +0,0 @@
|
||||
#include "qqthgtcpprotocol.h"
|
||||
|
||||
QQtHgTcpProtocol::QQtHgTcpProtocol ( QObject* parent ) : QQtHgProtocol ( parent )
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
QQtHgTcpProtocol::~QQtHgTcpProtocol()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
void QQtHgTcpProtocol::translator ( const QAbstractSocket* client, QByteArray& bytes )
|
||||
{
|
||||
// queued conn and queued package;
|
||||
// direct conn and direct package;
|
||||
QByteArray& sqbaBlockOnNet = clientBuffer() [client];
|
||||
sqbaBlockOnNet += bytes;
|
||||
//qint64 aaa = bytesAvailable();
|
||||
//pline() << aaa;
|
||||
|
||||
do
|
||||
{
|
||||
quint16 nBlockLen = this->splitter ( sqbaBlockOnNet );
|
||||
|
||||
pmeta() << sqbaBlockOnNet.size() << "..." << nBlockLen;
|
||||
|
||||
if ( sqbaBlockOnNet.length() < nBlockLen || nBlockLen < minlength() )
|
||||
{
|
||||
/*
|
||||
* 收到数据不足或者解析包长小于最小包长
|
||||
*/
|
||||
return;
|
||||
}
|
||||
else if ( nBlockLen > maxlength() )
|
||||
{
|
||||
/*
|
||||
* 数据包长超过了最大长度
|
||||
*/
|
||||
sqbaBlockOnNet.clear();
|
||||
pmeta() << "forbidden package" << sqbaBlockOnNet.length() << nBlockLen;
|
||||
return;
|
||||
}
|
||||
else if ( sqbaBlockOnNet.length() > nBlockLen )
|
||||
{
|
||||
/*
|
||||
* 粘包
|
||||
* 还没有处理完毕,数据已经接收到,异步信号处理出现这种异常
|
||||
* 疑问:如果异步调用这个函数绘出现什么问题?正常情况,同步获取数据,异步处理;检测异步获取并且处理会有什么状况
|
||||
*/
|
||||
pmeta() << "stick package" << sqbaBlockOnNet.length() << nBlockLen;
|
||||
QByteArray netData;
|
||||
netData.resize ( nBlockLen );
|
||||
sqbaBlockOnNet >> netData;
|
||||
dispatcher ( client, netData );
|
||||
emit notifyForDispatcher ( client, netData );
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* 正常分发
|
||||
*/
|
||||
dispatcher ( client, sqbaBlockOnNet );
|
||||
emit notifyForDispatcher ( client, sqbaBlockOnNet );
|
||||
break;
|
||||
} while ( 1 );
|
||||
|
||||
sqbaBlockOnNet.clear();
|
||||
}
|
@ -1,32 +0,0 @@
|
||||
#ifndef QQTHGTCPPROTOCOL_H
|
||||
#define QQTHGTCPPROTOCOL_H
|
||||
|
||||
#include <QObject>
|
||||
#include <qqt-local.h>
|
||||
#include "qqtcore.h"
|
||||
#include "qqthgprotocol.h"
|
||||
|
||||
/**
|
||||
* @brief The QQtHgTcpProtocol class
|
||||
* very good ideology and impliment
|
||||
*/
|
||||
class QQTSHARED_EXPORT QQtHgTcpProtocol : public QQtHgProtocol
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit QQtHgTcpProtocol ( QObject* parent = 0 );
|
||||
virtual ~QQtHgTcpProtocol();
|
||||
|
||||
/*以下和用户无关*/
|
||||
public:
|
||||
/**
|
||||
* @brief 协议处理器
|
||||
* 这个处理器是给HgSocket用的,不是给客户用的。
|
||||
* ProtocolManager,安装了这个协议,需要用户句柄。
|
||||
* @param Qt通讯口readAll()读到的bytes
|
||||
* @return
|
||||
*/
|
||||
void translator ( const QAbstractSocket* client, QByteArray& bytes );
|
||||
};
|
||||
|
||||
#endif // QQTHGTCPPROTOCOL_H
|
@ -1,63 +0,0 @@
|
||||
#include "qqthgtcpserver.h"
|
||||
|
||||
QQtHgTcpServer::QQtHgTcpServer ( QObject* parent ) :
|
||||
QTcpServer ( parent )
|
||||
{
|
||||
}
|
||||
|
||||
QQtHgTcpServer::~QQtHgTcpServer()
|
||||
{
|
||||
if ( isListening() )
|
||||
close();
|
||||
}
|
||||
|
||||
void QQtHgTcpServer::incomingConnection ( qintptr handle )
|
||||
{
|
||||
QQtHgTcpClient* clientSocket = new QQtHgTcpClient ( this );
|
||||
clientSocket->setSocketDescriptor ( handle );
|
||||
connect ( clientSocket, SIGNAL ( disconnected() ), this, SLOT ( clientSocketDisConnected() ) );
|
||||
if ( !m_protocolManager )
|
||||
{
|
||||
pline() << "please install protocol manager for your server.";
|
||||
clientSocket->deleteLater();
|
||||
return;
|
||||
}
|
||||
clientSocket->installProtocolManager ( m_protocolManager );
|
||||
}
|
||||
|
||||
void QQtHgTcpServer::clientSocketDisConnected()
|
||||
{
|
||||
QObject* obj = sender();
|
||||
QQtHgTcpClient* clientSocket = ( QQtHgTcpClient* ) obj;
|
||||
if ( !m_protocolManager )
|
||||
{
|
||||
pline() << "please install protocol manager for your server.";
|
||||
clientSocket->deleteLater();
|
||||
return;
|
||||
}
|
||||
clientSocket->uninstallProtocolManager ( m_protocolManager );
|
||||
clientSocket->deleteLater();
|
||||
}
|
||||
|
||||
void QQtHgTcpServer::installProtocolManager ( QQtHgProtocolManager* stackGroup )
|
||||
{
|
||||
if ( m_protocolManager )
|
||||
return;
|
||||
|
||||
m_protocolManager = stackGroup;
|
||||
}
|
||||
|
||||
void QQtHgTcpServer::uninstallProtocolManager ( QQtHgProtocolManager* stackGroup )
|
||||
{
|
||||
Q_UNUSED ( stackGroup )
|
||||
|
||||
if ( !m_protocolManager )
|
||||
return;
|
||||
|
||||
m_protocolManager = NULL;
|
||||
}
|
||||
|
||||
QQtHgProtocolManager* QQtHgTcpServer::installedProtocolManager()
|
||||
{
|
||||
return m_protocolManager;
|
||||
}
|
@ -1,44 +0,0 @@
|
||||
#ifndef QQTHGTCPSERVER_H
|
||||
#define QQTHGTCPSERVER_H
|
||||
|
||||
#include <QTcpServer>
|
||||
#include "qqthgprotocolmanager.h"
|
||||
#include "qqthgtcpclient.h"
|
||||
#include "qqt-local.h"
|
||||
#include "qqtcore.h"
|
||||
|
||||
/**
|
||||
* @brief The QQtHgTcpServer class
|
||||
* 这个类相当于QQtHgTcpClient管理器,相当于Socket管理器,它包含很多Socket。
|
||||
*
|
||||
* 概述:
|
||||
* 在这里安装HgProtocolManager以后,用户可以通过PM来进行通信。如果有必要的话。如果没有必要通知用户,在用户的Protocol里面实现通信就可以足够了。
|
||||
* 如果这个程序主要任务就是当作服务器节点,那么就把命令传给业务层好了,如果仅仅是包含一个服务器模块,那么不必要把客户端命令非要传给上层。
|
||||
*
|
||||
* 安装一个HgProtocolManager,包含很多的HgProtocol
|
||||
*/
|
||||
class QQTSHARED_EXPORT QQtHgTcpServer : public QTcpServer
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit QQtHgTcpServer ( QObject* parent = 0 );
|
||||
~QQtHgTcpServer();
|
||||
|
||||
void installProtocolManager ( QQtHgProtocolManager* stackGroup );
|
||||
void uninstallProtocolManager ( QQtHgProtocolManager* stackGroup );
|
||||
QQtHgProtocolManager* installedProtocolManager();
|
||||
|
||||
signals:
|
||||
|
||||
// QTcpServer interface
|
||||
protected:
|
||||
virtual void incomingConnection ( qintptr handle ) override;
|
||||
|
||||
private slots:
|
||||
void clientSocketDisConnected();
|
||||
private:
|
||||
QQtHgProtocolManager* m_protocolManager;
|
||||
};
|
||||
|
||||
|
||||
#endif // QQTHGTCPSERVER_H
|
@ -1,219 +0,0 @@
|
||||
#include "qqthgudpclient.h"
|
||||
|
||||
QQtHgUdpClient::QQtHgUdpClient ( QObject* parent ) : QUdpSocket ( parent )
|
||||
{
|
||||
connect ( this, SIGNAL ( stateChanged ( QAbstractSocket::SocketState ) ), this,
|
||||
SLOT ( socketStateChanged ( QAbstractSocket::SocketState ) ) );
|
||||
// connected
|
||||
connect ( this, SIGNAL ( connected() ), this, SLOT ( socketConnected() ) );
|
||||
// disconnected
|
||||
connect ( this, SIGNAL ( disconnected() ), this, SLOT ( socketDisconnect() ) );
|
||||
// domain
|
||||
connect ( this, SIGNAL ( hostFound() ), this, SLOT ( domainHostFound() ) );
|
||||
// error
|
||||
connect ( this, SIGNAL ( error ( QAbstractSocket::SocketError ) ), this,
|
||||
SLOT ( socketErrorOccured ( QAbstractSocket::SocketError ) ) );
|
||||
|
||||
connect ( this, SIGNAL ( readyRead() ), this, SLOT ( readyReadData() ) );
|
||||
|
||||
connect ( this, SIGNAL ( bytesWritten ( qint64 ) ), this, SLOT ( updateProgress ( qint64 ) ) );
|
||||
|
||||
connect ( this, SIGNAL ( bytesWritten ( qint64 ) ), this, SIGNAL ( signalUpdateProgress ( qint64 ) ) );
|
||||
|
||||
m_protocolManager = NULL;
|
||||
}
|
||||
|
||||
void QQtHgUdpClient::installProtocolManager ( QQtHgProtocolManager* stackGroup )
|
||||
{
|
||||
if ( m_protocolManager )
|
||||
return;
|
||||
|
||||
m_protocolManager = stackGroup;
|
||||
|
||||
QListIterator<QQtHgProtocol*> itor ( m_protocolManager->installedProtocol() );
|
||||
while ( itor.hasNext() )
|
||||
{
|
||||
//安装一个一个的句柄
|
||||
QQtHgProtocol* stack = itor.next();
|
||||
connect ( stack, SIGNAL ( write ( const QByteArray& ) ),
|
||||
this, SLOT ( writeData ( const QByteArray& ) ) );
|
||||
stack->createClientBuffer ( this );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void QQtHgUdpClient::uninstallProtocolManager ( QQtHgProtocolManager* stackGroup )
|
||||
{
|
||||
Q_UNUSED ( stackGroup )
|
||||
|
||||
if ( !m_protocolManager )
|
||||
return;
|
||||
|
||||
QListIterator<QQtHgProtocol*> itor ( m_protocolManager->installedProtocol() );
|
||||
while ( itor.hasNext() )
|
||||
{
|
||||
//安装一个一个的句柄
|
||||
QQtHgProtocol* stack = itor.next();
|
||||
disconnect ( stack, SIGNAL ( write ( const QByteArray& ) ),
|
||||
this, SLOT ( writeData ( const QByteArray& ) ) );
|
||||
stack->deleteClientBuffer ( this );
|
||||
}
|
||||
|
||||
m_protocolManager = NULL;
|
||||
}
|
||||
|
||||
QQtHgProtocolManager* QQtHgUdpClient::installedProtocolManager()
|
||||
{
|
||||
return m_protocolManager;
|
||||
}
|
||||
|
||||
void QQtHgUdpClient::domainHostFound()
|
||||
{
|
||||
pline();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief QQtHgUdpClient::socketStateChanged
|
||||
* @param eSocketState
|
||||
* 状态函数
|
||||
*/
|
||||
void QQtHgUdpClient::socketStateChanged ( QAbstractSocket::SocketState eSocketState )
|
||||
{
|
||||
pline() << eSocketState;
|
||||
|
||||
switch ( eSocketState )
|
||||
{
|
||||
case QAbstractSocket::HostLookupState:
|
||||
case QAbstractSocket::ConnectingState:
|
||||
break;
|
||||
|
||||
case QAbstractSocket::ConnectedState:
|
||||
break;
|
||||
|
||||
case QAbstractSocket::ClosingState:
|
||||
break;
|
||||
|
||||
case QAbstractSocket::UnconnectedState:
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief QQtHgUdpClient::socketErrorOccured
|
||||
* @param e
|
||||
* 状态函数
|
||||
*/
|
||||
void QQtHgUdpClient::socketErrorOccured ( QAbstractSocket::SocketError e )
|
||||
{
|
||||
/*
|
||||
* 在错误状态下重新连接其他热点,直到确定连接类型,写入配置文件
|
||||
*/
|
||||
pline() << e;
|
||||
|
||||
switch ( e )
|
||||
{
|
||||
case QAbstractSocket::RemoteHostClosedError:
|
||||
break;
|
||||
|
||||
case QAbstractSocket::HostNotFoundError:
|
||||
default:
|
||||
emit signalConnectFail();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief QQtHgUdpClient::socketConnected
|
||||
* 功能接口
|
||||
*/
|
||||
void QQtHgUdpClient::socketConnected()
|
||||
{
|
||||
pline() << peerName() << peerAddress().toString() << peerPort();
|
||||
/*
|
||||
* 这个步骤,socket重建,资源重新开始
|
||||
*/
|
||||
emit signalConnectSucc();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief QQtHgUdpClient::socketDisconnect
|
||||
* 功能接口
|
||||
*/
|
||||
void QQtHgUdpClient::socketDisconnect()
|
||||
{
|
||||
pline();
|
||||
}
|
||||
|
||||
void QQtHgUdpClient::updateProgress ( qint64 bytes )
|
||||
{
|
||||
Q_UNUSED ( bytes )
|
||||
//pline() << bytes;
|
||||
}
|
||||
|
||||
qint64 QQtHgUdpClient::slotWriteDatagram ( const QByteArray& datagram, const QHostAddress& host, quint16 port )
|
||||
{
|
||||
return writeDatagram ( datagram, host, port );
|
||||
}
|
||||
|
||||
void QQtHgUdpClient::readyReadData()
|
||||
{
|
||||
if ( !m_protocolManager )
|
||||
{
|
||||
pline() << "please install protocol manager for your client.";
|
||||
deleteLater();
|
||||
return;
|
||||
}
|
||||
|
||||
/*为什么用while?*/ //Qt4 没有那么高级的一次性读取的接口?有
|
||||
while ( hasPendingDatagrams() )
|
||||
{
|
||||
QByteArray bytes;
|
||||
qint64 maxlen = 0;
|
||||
QHostAddress host;
|
||||
quint16 port;
|
||||
|
||||
|
||||
#if QT_VERSION > QT_VERSION_DATAGRAM
|
||||
/*能够一次收够一条报文?测试的能。*/
|
||||
QNetworkDatagram datagram = receiveDatagram();
|
||||
/*由于添加了兼容Qt4的代码,以上注释起来。*/
|
||||
|
||||
/*数据无意义 "" -1 在此设置*/
|
||||
datagram.setDestination ( this->localAddress(), this->localPort() );
|
||||
//pline() << "udp sender:" << datagram.senderAddress() << datagram.senderPort();
|
||||
//pline() << "udp receiver:" << datagram.destinationAddress() << datagram.destinationPort();
|
||||
m_protocol->translator ( datagram );
|
||||
|
||||
bytes = datagram.data();
|
||||
host = datagram.senderAddress();
|
||||
port = datagram.senderPort();
|
||||
m_protocol->translator ( bytes, host, port );
|
||||
|
||||
QListIterator<QQtHgProtocol*> itor ( m_protocolManager->installedProtocol() );
|
||||
while ( itor.hasNext() )
|
||||
{
|
||||
QQtHgProtocol* protocol = itor.next();
|
||||
protocol->translator ( this, bytes );
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
qint64 size = pendingDatagramSize();
|
||||
//pline() << "udp new msg size:" << size;
|
||||
//这里的buf用完, 已经释放。
|
||||
char* data = new char[size + 1]();
|
||||
qint64 len = readDatagram ( data, size, &host, &port );
|
||||
pline() << len;
|
||||
bytes.setRawData ( data, size );
|
||||
delete[] data;
|
||||
|
||||
m_protocol->translator ( bytes, host, port );
|
||||
|
||||
#endif
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -1,56 +0,0 @@
|
||||
#ifndef QQTHGUDPCLIENT_H
|
||||
#define QQTHGUDPCLIENT_H
|
||||
|
||||
#include <QUdpSocket>
|
||||
#include "qqthgprotocolmanager.h"
|
||||
#include "qqt-local.h"
|
||||
#include "qqtcore.h"
|
||||
|
||||
/*
|
||||
* Udp通信客户端
|
||||
*
|
||||
* 和服务器操作区别:服务器需要绑定本地端口。
|
||||
*
|
||||
* 默认情况下,就可以接收发送数据了。在协议里处理接收、发送。
|
||||
* 只有绑定本地IP、端口才能进行接收
|
||||
*/
|
||||
class QQTSHARED_EXPORT QQtHgUdpClient : public QUdpSocket
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit QQtHgUdpClient ( QObject* parent = nullptr );
|
||||
virtual ~QQtHgUdpClient() {}
|
||||
|
||||
void installProtocolManager ( QQtHgProtocolManager* stackGroup );
|
||||
void uninstallProtocolManager ( QQtHgProtocolManager* stackGroup );
|
||||
QQtHgProtocolManager* installedProtocolManager();
|
||||
|
||||
signals:
|
||||
void signalConnecting();
|
||||
void signalConnectSucc();
|
||||
void signalConnectFail();//
|
||||
void signalDisConnectSucc();//maybe
|
||||
void signalDisConnectFail();//
|
||||
void signalUpdateProgress ( qint64 value );
|
||||
public slots:
|
||||
|
||||
protected slots:
|
||||
void readyReadData();
|
||||
private slots:
|
||||
void domainHostFound();
|
||||
void socketStateChanged ( QAbstractSocket::SocketState );
|
||||
void socketErrorOccured ( QAbstractSocket::SocketError );
|
||||
void socketConnected();
|
||||
void socketDisconnect();
|
||||
void updateProgress ( qint64 bytes );
|
||||
//如果有一个同名的槽,参数不同,并且被用宏控制起来,Qt编译不过。
|
||||
//Qt的元对象系统,解析信号和槽函数,不支持宏。
|
||||
//QtUdpSocket,writeDatagram不是个槽。
|
||||
qint64 slotWriteDatagram ( const QByteArray& datagram,
|
||||
const QHostAddress& host, quint16 port );
|
||||
|
||||
private:
|
||||
QQtHgProtocolManager* m_protocolManager;
|
||||
};
|
||||
|
||||
#endif // QQTUDPCLIENT_H
|
@ -1 +0,0 @@
|
||||
#include "qqthgudpprotocol.h"
|
@ -1,101 +0,0 @@
|
||||
#ifndef QQTUDPPROTOCOL_H
|
||||
#define QQTUDPPROTOCOL_H
|
||||
|
||||
#include <QObject>
|
||||
#include "qqthgprotocol.h"
|
||||
#include "qqthgudpclient.h"
|
||||
#include <qqt-local.h>
|
||||
#include "qqtcore.h"
|
||||
|
||||
#define QT_VERSION_DATAGRAM QT_VERSION_CHECK(5,8,0)
|
||||
|
||||
#if QT_VERSION > QT_VERSION_DATAGRAM
|
||||
#include <QNetworkDatagram>
|
||||
#endif
|
||||
|
||||
/*
|
||||
*/
|
||||
class QQTSHARED_EXPORT QQtHgUdpProtocol : public QQtHgProtocol
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit QQtHgUdpProtocol ( QObject* parent = nullptr ) : QQtHgProtocol ( parent ) {
|
||||
|
||||
}
|
||||
virtual ~QQtHgUdpProtocol() {}
|
||||
|
||||
#if QT_VERSION > QT_VERSION_DATAGRAM
|
||||
qint64 writeDatagram ( const QNetworkDatagram& datagram ) {
|
||||
QByteArray dg = datagram.data();
|
||||
QHostAddress addr = datagram.destinationAddress();
|
||||
int port = datagram.destinationPort();
|
||||
emit writeDatagram ( dg, addr, ( quint16 ) port );
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief writeDatagram
|
||||
* 会发送给writeToClient
|
||||
* @param datagram
|
||||
* @param host
|
||||
* @param port
|
||||
* @return
|
||||
*/
|
||||
qint64 writeDatagram ( const QByteArray& datagram,
|
||||
const QHostAddress& host, quint16 port ) {
|
||||
QQtHgUdpClient client;
|
||||
client;
|
||||
}
|
||||
|
||||
public slots:
|
||||
|
||||
protected:
|
||||
/**
|
||||
* @brief 语义解析器
|
||||
* @brief 用户必须继承下去,重写,need override
|
||||
* @param 数据包
|
||||
* @return 0 no dispatched(others) 1 dispatched(own)
|
||||
*/
|
||||
inline virtual void dispatcher ( const QByteArray& datagram,
|
||||
const QHostAddress& host, quint16 port ) {
|
||||
return;
|
||||
}
|
||||
/*
|
||||
* 这两个dispatcher,任选其一重写。
|
||||
*/
|
||||
#if QT_VERSION > QT_VERSION_DATAGRAM
|
||||
inline virtual void dispatcher ( const QNetworkDatagram& ) { return; }
|
||||
#endif
|
||||
inline virtual void dispatcher ( const QAbstractSocket* client, const QByteArray& bytes ) {
|
||||
return;
|
||||
}
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief 协议处理器
|
||||
* @brief 这个处理器是给QQtUdpSocket用的,不需要用户管理。
|
||||
* @param Qt通讯口readAll()读到的bytes
|
||||
* @return
|
||||
*/
|
||||
void translator ( const QByteArray& datagram,
|
||||
const QHostAddress& host, quint16 port ) {
|
||||
dispatcher ( datagram, host, port );
|
||||
}
|
||||
#if QT_VERSION > QT_VERSION_DATAGRAM
|
||||
void translator ( const QNetworkDatagram& datagram ) {
|
||||
dispatcher ( datagram );
|
||||
}
|
||||
#endif
|
||||
/**
|
||||
* @brief 协议处理器
|
||||
* @brief 这个处理器是给QQtHgUdpSocket用的,不需要用户管理。
|
||||
* @param Qt通讯口readAll()读到的bytes
|
||||
* @return
|
||||
*/
|
||||
void translator ( const QAbstractSocket* client, const QByteArray& bytes ) {
|
||||
dispatcher ( client, bytes );
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
#endif // QQTUDPPROTOCOL_H
|
@ -1,184 +0,0 @@
|
||||
#include "qqthgudpserver.h"
|
||||
|
||||
QQtHgUdpServer::QQtHgUdpServer ( QObject* parent ) : QUdpSocket ( parent )
|
||||
{
|
||||
connect ( this, SIGNAL ( stateChanged ( QAbstractSocket::SocketState ) ), this,
|
||||
SLOT ( socketStateChanged ( QAbstractSocket::SocketState ) ) );
|
||||
// connected
|
||||
connect ( this, SIGNAL ( connected() ), this, SLOT ( socketConnected() ) );
|
||||
// disconnected
|
||||
connect ( this, SIGNAL ( disconnected() ), this, SLOT ( socketDisconnect() ) );
|
||||
// domain
|
||||
connect ( this, SIGNAL ( hostFound() ), this, SLOT ( domainHostFound() ) );
|
||||
// error
|
||||
connect ( this, SIGNAL ( error ( QAbstractSocket::SocketError ) ), this,
|
||||
SLOT ( socketErrorOccured ( QAbstractSocket::SocketError ) ) );
|
||||
|
||||
connect ( this, SIGNAL ( readyRead() ), this, SLOT ( readyReadData() ) );
|
||||
|
||||
connect ( this, SIGNAL ( bytesWritten ( qint64 ) ), this, SLOT ( updateProgress ( qint64 ) ) );
|
||||
|
||||
connect ( this, SIGNAL ( bytesWritten ( qint64 ) ), this, SIGNAL ( signalUpdateProgress ( qint64 ) ) );
|
||||
|
||||
m_protocol = NULL;
|
||||
}
|
||||
|
||||
void QQtHgUdpServer::installProtocol ( QQtHgUdpProtocol* stack )
|
||||
{
|
||||
if ( m_protocol )
|
||||
return;
|
||||
|
||||
m_protocol = stack;
|
||||
connect ( m_protocol, SIGNAL ( writeDatagram ( QByteArray, QHostAddress, quint16 ) ),
|
||||
this, SLOT ( slotWriteDatagram ( QByteArray, QHostAddress, quint16 ) ) );
|
||||
}
|
||||
|
||||
void QQtHgUdpServer::uninstallProtocol ( QQtHgUdpProtocol* stack )
|
||||
{
|
||||
Q_UNUSED ( stack )
|
||||
|
||||
if ( !m_protocol )
|
||||
return;
|
||||
|
||||
disconnect ( m_protocol, SIGNAL ( writeDatagram ( QByteArray, QHostAddress, quint16 ) ),
|
||||
this, SLOT ( slotWriteDatagram ( QByteArray, QHostAddress, quint16 ) ) );
|
||||
m_protocol = NULL;
|
||||
}
|
||||
|
||||
QQtHgUdpProtocol* QQtHgUdpServer::installedProtocol()
|
||||
{
|
||||
return m_protocol;
|
||||
}
|
||||
|
||||
void QQtHgUdpServer::domainHostFound()
|
||||
{
|
||||
pline();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief QQtHgUdpClient::socketStateChanged
|
||||
* @param eSocketState
|
||||
* 状态函数
|
||||
*/
|
||||
void QQtHgUdpServer::socketStateChanged ( QAbstractSocket::SocketState eSocketState )
|
||||
{
|
||||
pline() << eSocketState;
|
||||
|
||||
switch ( eSocketState )
|
||||
{
|
||||
case QAbstractSocket::HostLookupState:
|
||||
case QAbstractSocket::ConnectingState:
|
||||
break;
|
||||
|
||||
case QAbstractSocket::ConnectedState:
|
||||
break;
|
||||
|
||||
case QAbstractSocket::ClosingState:
|
||||
break;
|
||||
|
||||
case QAbstractSocket::UnconnectedState:
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief QQtHgUdpClient::socketErrorOccured
|
||||
* @param e
|
||||
* 状态函数
|
||||
*/
|
||||
void QQtHgUdpServer::socketErrorOccured ( QAbstractSocket::SocketError e )
|
||||
{
|
||||
/*
|
||||
* 在错误状态下重新连接其他热点,直到确定连接类型,写入配置文件
|
||||
*/
|
||||
pline() << e;
|
||||
|
||||
switch ( e )
|
||||
{
|
||||
case QAbstractSocket::RemoteHostClosedError:
|
||||
break;
|
||||
|
||||
case QAbstractSocket::HostNotFoundError:
|
||||
default:
|
||||
emit signalConnectFail();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief QQtHgUdpClient::socketConnected
|
||||
* 功能接口
|
||||
*/
|
||||
void QQtHgUdpServer::socketConnected()
|
||||
{
|
||||
pline() << peerName() << peerAddress().toString() << peerPort();
|
||||
/*
|
||||
* 这个步骤,socket重建,资源重新开始
|
||||
*/
|
||||
emit signalConnectSucc();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief QQtHgUdpClient::socketDisconnect
|
||||
* 功能接口
|
||||
*/
|
||||
void QQtHgUdpServer::socketDisconnect()
|
||||
{
|
||||
pline();
|
||||
}
|
||||
|
||||
void QQtHgUdpServer::updateProgress ( qint64 bytes )
|
||||
{
|
||||
Q_UNUSED ( bytes )
|
||||
//pline() << bytes;
|
||||
}
|
||||
|
||||
qint64 QQtHgUdpServer::slotWriteDatagram ( const QByteArray& datagram, const QHostAddress& host, quint16 port )
|
||||
{
|
||||
return writeDatagram ( datagram, host, port );
|
||||
}
|
||||
|
||||
void QQtHgUdpServer::readyReadData()
|
||||
{
|
||||
/*为什么用while?*/ //Qt4 没有那么高级的一次性读取的接口?有
|
||||
while ( hasPendingDatagrams() )
|
||||
{
|
||||
QByteArray bytes;
|
||||
qint64 maxlen = 0;
|
||||
QHostAddress host;
|
||||
quint16 port;
|
||||
|
||||
#if QT_VERSION > QT_VERSION_DATAGRAM
|
||||
/*能够一次收够一条报文?测试的能。*/
|
||||
QNetworkDatagram datagram = receiveDatagram();
|
||||
/*由于添加了兼容Qt4的代码,以上注释起来。*/
|
||||
|
||||
/*数据无意义 "" -1 在此设置*/
|
||||
datagram.setDestination ( this->localAddress(), this->localPort() );
|
||||
//pline() << "udp sender:" << datagram.senderAddress() << datagram.senderPort();
|
||||
//pline() << "udp receiver:" << datagram.destinationAddress() << datagram.destinationPort();
|
||||
m_protocol->translator ( datagram );
|
||||
|
||||
bytes = datagram.data();
|
||||
host = datagram.senderAddress();
|
||||
port = datagram.senderPort();
|
||||
m_protocol->translator ( bytes, host, port );
|
||||
#else
|
||||
qint64 size = pendingDatagramSize();
|
||||
//pline() << "udp new msg size:" << size;
|
||||
//这里的buf用完, 已经释放。
|
||||
char* data = new char[size + 1]();
|
||||
qint64 len = readDatagram ( data, size, &host, &port );
|
||||
pline() << len;
|
||||
bytes.setRawData ( data, size );
|
||||
delete[] data;
|
||||
|
||||
m_protocol->translator ( bytes, host, port );
|
||||
#endif
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -1,65 +0,0 @@
|
||||
#ifndef QQTHGUDPSERVER_H
|
||||
#define QQTHGUDPSERVER_H
|
||||
|
||||
#include <QUdpSocket>
|
||||
#include "qqthgudpprotocol.h"
|
||||
#include "qqthgudpclient.h"
|
||||
#include "qqt-local.h"
|
||||
#include "qqtcore.h"
|
||||
|
||||
/*
|
||||
* Udp通信服务器
|
||||
*
|
||||
* Udp通信服务器和客户端操作区别:服务器需要绑定本地端口。
|
||||
* 区别很小。
|
||||
* 可是在服务器端,和TCP一样需要处理多个客户端通信,在这里处理。
|
||||
* 假如不处理,一个服务器会同时和多个客户端通信。
|
||||
*
|
||||
* 默认情况下,就可以接收发送数据了。在协议里处理接收、发送。
|
||||
* 只有绑定本地IP、端口才能进行接收
|
||||
*/
|
||||
class QQtHgUdpServer : public QUdpSocket
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit QQtHgUdpServer ( QObject* parent = nullptr );
|
||||
virtual ~QQtHgUdpServer() {}
|
||||
|
||||
void installProtocol ( QQtHgUdpProtocol* stack );
|
||||
void uninstallProtocol ( QQtHgUdpProtocol* stack );
|
||||
QQtHgUdpProtocol* installedProtocol();
|
||||
|
||||
QList<QQtHgUdpClient*> getClientList() const {
|
||||
return m_client_list;
|
||||
}
|
||||
|
||||
signals:
|
||||
void signalConnecting();
|
||||
void signalConnectSucc();
|
||||
void signalConnectFail();//
|
||||
void signalDisConnectSucc();//maybe
|
||||
void signalDisConnectFail();//
|
||||
void signalUpdateProgress ( qint64 value );
|
||||
public slots:
|
||||
|
||||
protected slots:
|
||||
void readyReadData();
|
||||
private slots:
|
||||
void domainHostFound();
|
||||
void socketStateChanged ( QAbstractSocket::SocketState );
|
||||
void socketErrorOccured ( QAbstractSocket::SocketError );
|
||||
void socketConnected();
|
||||
void socketDisconnect();
|
||||
void updateProgress ( qint64 bytes );
|
||||
//如果有一个同名的槽,参数不同,并且被用宏控制起来,Qt编译不过。
|
||||
//Qt的元对象系统,解析信号和槽函数,不支持宏。
|
||||
//QtUdpSocket,writeDatagram不是个槽。
|
||||
qint64 slotWriteDatagram ( const QByteArray& datagram,
|
||||
const QHostAddress& host, quint16 port );
|
||||
|
||||
private:
|
||||
QQtHgUdpProtocol* m_protocol;
|
||||
QList<QQtHgUdpClient*> m_client_list;
|
||||
};
|
||||
|
||||
#endif // QQTHGUDPSERVER_H
|
@ -1,8 +0,0 @@
|
||||
#include "qqthgwebsocketclient.h"
|
||||
|
||||
QQtHgWebSocketClient::QQtHgWebSocketClient ( QObject* parent, const QString& origin,
|
||||
QWebSocketProtocol::Version version ) :
|
||||
QWebSocket ( origin, version, parent )
|
||||
{
|
||||
|
||||
}
|
@ -1,28 +0,0 @@
|
||||
#ifndef QQTHGWEBCLIENT_H
|
||||
#define QQTHGWEBCLIENT_H
|
||||
|
||||
#include <QtWebSockets/QWebSocket>
|
||||
#include <qqtcore.h>
|
||||
#include <qqt-local.h>
|
||||
|
||||
/**
|
||||
* @brief The QQtHgWebSocketClient class
|
||||
* QQtHgWebSocketClient 通过安装QQtHgWebProtocol来实现和RawSocket相似的通信方式。
|
||||
* 暂时不确定QQtHgWebProtocol是否和QQtHgProtocol格式相同,所以暂时使用QQtHgWebProtocol继承QQtHgProtocol。
|
||||
*/
|
||||
class QQTSHARED_EXPORT QQtHgWebSocketClient : public QWebSocket
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit QQtHgWebSocketClient ( QObject* parent = nullptr,
|
||||
const QString& origin = QString(),
|
||||
QWebSocketProtocol::Version version = QWebSocketProtocol::VersionLatest );
|
||||
|
||||
signals:
|
||||
|
||||
public slots:
|
||||
|
||||
private:
|
||||
};
|
||||
|
||||
#endif // QQTHGWEBCLIENT_H
|
@ -1,7 +0,0 @@
|
||||
#include "qqthgwebsocketprotocol.h"
|
||||
|
||||
QQtHgWebSocketProtocol::QQtHgWebSocketProtocol ( QObject* parent ) : QQtHgProtocol ( parent )
|
||||
{
|
||||
|
||||
}
|
||||
|
@ -1,22 +0,0 @@
|
||||
#ifndef QQTHGWEBPROTOCOL_H
|
||||
#define QQTHGWEBPROTOCOL_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QNetworkRequest>
|
||||
#include <QNetworkReply>
|
||||
#include <QSslError>
|
||||
#include <qqt-local.h>
|
||||
#include <qqthgprotocol.h>
|
||||
|
||||
class QQTSHARED_EXPORT QQtHgWebSocketProtocol : public QQtHgProtocol
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit QQtHgWebSocketProtocol ( QObject* parent = 0 );
|
||||
|
||||
signals:
|
||||
|
||||
public slots:
|
||||
};
|
||||
|
||||
#endif // QQTHGWEBPROTOCOL_H
|
@ -1,6 +0,0 @@
|
||||
#include "qqthgwebsocketserver.h"
|
||||
|
||||
QQtHgWebSocketServer::QQtHgWebSocketServer ( QObject* parent ) : QObject ( parent )
|
||||
{
|
||||
|
||||
}
|
@ -1,19 +0,0 @@
|
||||
#ifndef QQTHGWEBSERVER_H
|
||||
#define QQTHGWEBSERVER_H
|
||||
|
||||
#include <QObject>
|
||||
#include <qqtcore.h>
|
||||
#include <qqt-local.h>
|
||||
|
||||
class QQTSHARED_EXPORT QQtHgWebSocketServer : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit QQtHgWebSocketServer ( QObject* parent = nullptr );
|
||||
|
||||
signals:
|
||||
|
||||
public slots:
|
||||
};
|
||||
|
||||
#endif // QQTHGWEBSERVER_H
|
@ -1,68 +0,0 @@
|
||||
#include "qqtprotocol.h"
|
||||
|
||||
QQtProtocol::QQtProtocol ( QObject* parent ) : QObject ( parent )
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
QQtProtocol::~QQtProtocol()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void QQtProtocol::translator ( const QByteArray& bytes )
|
||||
{
|
||||
// queued conn and queued package;
|
||||
// direct conn and direct package;
|
||||
|
||||
static QByteArray sqbaBlockOnNet;
|
||||
sqbaBlockOnNet += bytes;
|
||||
//qint64 aaa = bytesAvailable();
|
||||
//pline() << aaa;
|
||||
|
||||
do
|
||||
{
|
||||
quint16 nBlockLen = this->splitter ( sqbaBlockOnNet );
|
||||
|
||||
pmeta() << sqbaBlockOnNet.size() << "..." << nBlockLen;
|
||||
|
||||
if ( sqbaBlockOnNet.length() < nBlockLen || nBlockLen < minlength() )
|
||||
{
|
||||
/*
|
||||
* 收到数据不足或者解析包长小于最小包长
|
||||
*/
|
||||
return;
|
||||
}
|
||||
else if ( nBlockLen > maxlength() )
|
||||
{
|
||||
/*
|
||||
* 数据包长超过了最大长度
|
||||
*/
|
||||
sqbaBlockOnNet.clear();
|
||||
pmeta() << "forbidden package" << sqbaBlockOnNet.length() << nBlockLen;
|
||||
return;
|
||||
}
|
||||
else if ( sqbaBlockOnNet.length() > nBlockLen )
|
||||
{
|
||||
/*
|
||||
* 粘包
|
||||
* 还没有处理完毕,数据已经接收到,异步信号处理出现这种异常
|
||||
* 疑问:如果异步调用这个函数绘出现什么问题?正常情况,同步获取数据,异步处理;检测异步获取并且处理会有什么状况
|
||||
*/
|
||||
pmeta() << "stick package" << sqbaBlockOnNet.length() << nBlockLen;
|
||||
QByteArray netData;
|
||||
netData.resize ( nBlockLen );
|
||||
sqbaBlockOnNet >> netData;
|
||||
dispatcher ( netData );
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* 正常分发
|
||||
*/
|
||||
dispatcher ( sqbaBlockOnNet );
|
||||
break;
|
||||
} while ( 1 );
|
||||
|
||||
sqbaBlockOnNet.clear();
|
||||
}
|
@ -9,13 +9,21 @@
|
||||
/**
|
||||
* @brief The QQtProtocol class
|
||||
* very good ideology and impliment
|
||||
*
|
||||
* 特点
|
||||
* C-P
|
||||
* ClientSocket Protocol 1:1的关系
|
||||
*/
|
||||
class QQTSHARED_EXPORT QQtProtocol : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
Q_INVOKABLE explicit QQtProtocol ( QObject* parent = 0 );
|
||||
virtual ~QQtProtocol();
|
||||
Q_INVOKABLE explicit QQtProtocol ( QObject* parent = 0 ) : QObject ( parent ) {
|
||||
|
||||
}
|
||||
virtual ~QQtProtocol() {
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* 建议:用户在继承类里的函数里直接调用[emit] write(...)
|
||||
@ -25,7 +33,7 @@ Q_SIGNALS:
|
||||
/*
|
||||
* 以下函数,用户必须继承下去,重写,need override
|
||||
*/
|
||||
protected:
|
||||
public:
|
||||
/**
|
||||
* @brief 最小包长
|
||||
* @return
|
||||
@ -38,12 +46,14 @@ protected:
|
||||
inline virtual quint16 maxlength() { return 0xFFFF; }
|
||||
/**
|
||||
* @brief 语法解析器 从流中解析报文长度
|
||||
* /.../quint16 size/.../.../...
|
||||
* @param 接收到的数据段
|
||||
* @return 按照协议解析到的数据长度 可用,继续接收,丢弃,粘包。
|
||||
*/
|
||||
inline virtual quint16 splitter ( const QByteArray& ) { return 0; }
|
||||
/**
|
||||
* @brief 语义解析器
|
||||
* /.../quint16 size/.../QByteArray data/.../
|
||||
* @param 数据包
|
||||
* @return 0 no dispatched(others) 1 dispatched(own)
|
||||
*/
|
||||
@ -62,16 +72,6 @@ signals:
|
||||
* @param message
|
||||
*/
|
||||
void notifyToProtocolManager ( const QQtProtocol* self, const QQtMessage* message );
|
||||
|
||||
/*以下和用户无关。*/
|
||||
public:
|
||||
/**
|
||||
* @brief 协议处理器
|
||||
* 这个处理器是给QQtTcpSocket用的,不是给客户用的。
|
||||
* @param Qt通讯口readAll()读到的bytes
|
||||
* @return
|
||||
*/
|
||||
void translator ( const QByteArray& bytes );
|
||||
};
|
||||
|
||||
#endif // QQTPROTOCOL_H
|
||||
|
@ -1,72 +1 @@
|
||||
#include "qqtprotocolmanager.h"
|
||||
|
||||
QQtProtocolManager::QQtProtocolManager ( QObject* parent ) : QObject ( parent )
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
QQtProtocolManager::~QQtProtocolManager()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
#if 0
|
||||
|
||||
void QQtProtocolManager::translator ( const QByteArray& bytes )
|
||||
{
|
||||
// queued conn and queued package;
|
||||
// direct conn and direct package;
|
||||
|
||||
static QByteArray sqbaBlockOnNet;
|
||||
sqbaBlockOnNet += bytes;
|
||||
//qint64 aaa = bytesAvailable();
|
||||
//pline() << aaa;
|
||||
|
||||
do
|
||||
{
|
||||
quint16 nBlockLen = this->splitter ( sqbaBlockOnNet );
|
||||
|
||||
pmeta() << sqbaBlockOnNet.size() << "..." << nBlockLen;
|
||||
|
||||
if ( sqbaBlockOnNet.length() < nBlockLen || nBlockLen < minlength() )
|
||||
{
|
||||
/*
|
||||
* 收到数据不足或者解析包长小于最小包长
|
||||
*/
|
||||
return;
|
||||
}
|
||||
else if ( nBlockLen > maxlength() )
|
||||
{
|
||||
/*
|
||||
* 数据包长超过了最大长度
|
||||
*/
|
||||
sqbaBlockOnNet.clear();
|
||||
pmeta() << "forbidden package" << sqbaBlockOnNet.length() << nBlockLen;
|
||||
return;
|
||||
}
|
||||
else if ( sqbaBlockOnNet.length() > nBlockLen )
|
||||
{
|
||||
/*
|
||||
* 粘包
|
||||
* 还没有处理完毕,数据已经接收到,异步信号处理出现这种异常
|
||||
* 疑问:如果异步调用这个函数绘出现什么问题?正常情况,同步获取数据,异步处理;检测异步获取并且处理会有什么状况
|
||||
*/
|
||||
pmeta() << "stick package" << sqbaBlockOnNet.length() << nBlockLen;
|
||||
QByteArray netData;
|
||||
netData.resize ( nBlockLen );
|
||||
sqbaBlockOnNet >> netData;
|
||||
dispatcher ( netData );
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* 正常分发
|
||||
*/
|
||||
dispatcher ( sqbaBlockOnNet );
|
||||
break;
|
||||
} while ( 1 );
|
||||
|
||||
sqbaBlockOnNet.clear();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -29,9 +29,14 @@ class QQTSHARED_EXPORT QQtProtocolManager : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit QQtProtocolManager ( QObject* parent = 0 );
|
||||
virtual ~QQtProtocolManager();
|
||||
explicit QQtProtocolManager ( QObject* parent = 0 ) : QObject ( parent ) {
|
||||
mProtocol = NULL;
|
||||
}
|
||||
virtual ~QQtProtocolManager() {
|
||||
|
||||
}
|
||||
|
||||
//获取Protocol列表
|
||||
//这里列举的函数是给BusinessLevel用的,Protocol里面不要用
|
||||
//findProtocolInstanceByXXX(...);
|
||||
//findClientInfoByProtocolInstance(Protocol);
|
||||
@ -56,15 +61,20 @@ public:
|
||||
* 用于ProtocolManager内部生成用户协议实例。
|
||||
* 这个用户在生成ProtocolManager对象的时候,需要注册一下自己的协议类,需要调用一次。
|
||||
* 注意:
|
||||
* registerProtocol<QQtXXXProtocol>("QQtXXXProtocol"); ... 如此
|
||||
* registerProtocol<QQtXXXProtocol>();
|
||||
*/
|
||||
template <typename T>
|
||||
void registerProtocol () {
|
||||
//pline() << typeid ( T ) << typeid ( T ).name();
|
||||
mProtocolName = T::staticMetaObject.className();
|
||||
QQtObjectFactory::registerObject<T>();
|
||||
bool registerProtocol () {
|
||||
if ( mProtocol )
|
||||
return false;
|
||||
mProtocol = new T ( this );
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 以下和用户无关
|
||||
*/
|
||||
public:
|
||||
/**
|
||||
* @brief createProtocol
|
||||
* 这个函数给QQtSocketServer用的,不是给用户用的。
|
||||
@ -74,59 +84,21 @@ public:
|
||||
*/
|
||||
QQtProtocol* createProtocol () {
|
||||
//如果不能生成,根本不返回,而是崩溃。
|
||||
QQtProtocol* p0 = ( QQtProtocol* ) QQtObjectFactory::createObject ( mProtocolName, this );
|
||||
if ( !mProtocol )
|
||||
return NULL;
|
||||
|
||||
pmeta ( mProtocol );
|
||||
QQtProtocol* p0 = ( QQtProtocol* ) mProtocol->metaObject()->newInstance ( Q_ARG ( QQtProtocolManager*, this ) );
|
||||
//帮助Protocol给用户发数据。
|
||||
connect ( p0, SIGNAL ( notifyToProtocolManager ( const QQtProtocol*, const QQtMessage* ) ),
|
||||
this, SIGNAL ( notifyToBusinessLevel ( const QQtProtocol*, const QQtMessage* ) ) );
|
||||
return p0;
|
||||
}
|
||||
|
||||
private slots:
|
||||
void clientSocketDisConnected();
|
||||
private:
|
||||
QByteArray mProtocolName;
|
||||
|
||||
#if 0
|
||||
/*
|
||||
* 建议:用户在继承类里的函数里直接调用[emit] write(...)
|
||||
*/
|
||||
Q_SIGNALS:
|
||||
qint64 write ( const QByteArray& );
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief 协议处理器
|
||||
* 这个处理器是给QQtTcpSocket用的,不是给客户用的。
|
||||
* @param Qt通讯口readAll()读到的bytes
|
||||
* @return
|
||||
*/
|
||||
void translator ( const QByteArray& bytes );
|
||||
|
||||
/*
|
||||
* 以下函数,用户必须继承下去,重写,need override
|
||||
*/
|
||||
protected:
|
||||
/**
|
||||
* @brief 最小包长
|
||||
* @return
|
||||
*/
|
||||
inline virtual quint16 minlength() { return 0; }
|
||||
/**
|
||||
* @brief 最大包长
|
||||
* @return
|
||||
*/
|
||||
inline virtual quint16 maxlength() { return 0xFFFF; }
|
||||
/**
|
||||
* @brief 语法解析器 从流中解析报文长度
|
||||
* @param 接收到的数据段
|
||||
* @return 按照协议解析到的数据长度 可用,继续接收,丢弃,粘包。
|
||||
*/
|
||||
inline virtual quint16 splitter ( const QByteArray& ) { return 0; }
|
||||
/**
|
||||
* @brief 语义解析器
|
||||
* @param 数据包
|
||||
* @return 0 no dispatched(others) 1 dispatched(own)
|
||||
*/
|
||||
inline virtual bool dispatcher ( const QByteArray& ) { return 0; }
|
||||
#endif
|
||||
QQtProtocol* mProtocol;
|
||||
};
|
||||
|
||||
#endif // QQTPROTOCOLMANAGER_H
|
||||
|
@ -54,7 +54,7 @@ void QQtTcpClient::installProtocol ( QQtProtocol* stack )
|
||||
|
||||
m_protocol = stack;
|
||||
connect ( m_protocol, SIGNAL ( write ( const QByteArray& ) ),
|
||||
this, SLOT ( writeData ( const QByteArray& ) ) );
|
||||
this, SLOT ( slotWriteData ( const QByteArray& ) ) );
|
||||
}
|
||||
|
||||
void QQtTcpClient::uninstallProtocol ( QQtProtocol* stack )
|
||||
@ -65,7 +65,7 @@ void QQtTcpClient::uninstallProtocol ( QQtProtocol* stack )
|
||||
return;
|
||||
|
||||
disconnect ( m_protocol, SIGNAL ( write ( const QByteArray& ) ),
|
||||
this, SLOT ( writeData ( const QByteArray& ) ) );
|
||||
this, SLOT ( slotWriteData ( const QByteArray& ) ) );
|
||||
m_protocol = NULL;
|
||||
}
|
||||
|
||||
@ -74,7 +74,7 @@ QQtProtocol* QQtTcpClient::installedProtocol()
|
||||
return m_protocol;
|
||||
}
|
||||
|
||||
void QQtTcpClient::SendConnectMessage()
|
||||
void QQtTcpClient::sendConnectToHost()
|
||||
{
|
||||
pline() << isValid() << isOpen() << state();
|
||||
|
||||
@ -98,7 +98,7 @@ void QQtTcpClient::SendConnectMessage()
|
||||
}
|
||||
|
||||
|
||||
int QQtTcpClient::SendDisConnectFromHost()
|
||||
int QQtTcpClient::sendDisConnectFromHost()
|
||||
{
|
||||
pline() << isValid() << isOpen() << state();
|
||||
|
||||
@ -146,6 +146,9 @@ void QQtTcpClient::socketStateChanged ( QAbstractSocket::SocketState eSocketStat
|
||||
|
||||
case QAbstractSocket::UnconnectedState:
|
||||
eConType++;
|
||||
QSettings set;
|
||||
set.setValue ( "Network/eConType", eConType );
|
||||
set.sync();
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -188,6 +191,10 @@ void QQtTcpClient::socketConnected()
|
||||
* 这个步骤,socket重建,资源重新开始
|
||||
*/
|
||||
emit signalConnectSucc();
|
||||
if ( !m_protocol )
|
||||
{
|
||||
pline() << "please install protocol for your tcp client.";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -207,7 +214,9 @@ void QQtTcpClient::updateProgress ( qint64 bytes )
|
||||
|
||||
void QQtTcpClient::connectToSingelHost()
|
||||
{
|
||||
int contype = eConType % m_serverIP.size();
|
||||
QSettings set;
|
||||
int contype = set.value ( "Network/eConType", 0 ).toInt();
|
||||
//int contype = eConType % m_serverIP.size();
|
||||
QString ip = m_serverIP.at ( contype );
|
||||
connectToHost ( QHostAddress ( ip ), m_PORT );
|
||||
|
||||
@ -220,10 +229,77 @@ void QQtTcpClient::readyReadData()
|
||||
//self, protocol, message
|
||||
QByteArray bytes;
|
||||
bytes = readAll();
|
||||
m_protocol->translator ( bytes );
|
||||
translator ( bytes );
|
||||
}
|
||||
|
||||
void QQtTcpClient::writeData ( const QByteArray& data )
|
||||
void QQtTcpClient::slotWriteData ( const QByteArray& data )
|
||||
{
|
||||
write ( data );
|
||||
}
|
||||
|
||||
void QQtTcpClient::translator ( const QByteArray& bytes )
|
||||
{
|
||||
// queued conn and queued package;
|
||||
// direct conn and direct package;
|
||||
/**
|
||||
* 这个地方的实现,还是有一些复杂,
|
||||
* 但是只有流式传输才需要,
|
||||
* 而且,每种通讯接口的流式传输都是一样的,
|
||||
* 过去,写在protocol里是为了增添传输工具客户端类型方便
|
||||
* 现在,这块比较稳定,所以挪动回来。
|
||||
*
|
||||
* 只能安装一个协议。
|
||||
* 如果安装多个,这个地方的static,需要给协议们分配独立的buffer。
|
||||
* 一个客户端,和服务器通信,一条流,可以由多个协议进行解析吗?
|
||||
*/
|
||||
static QByteArray sqbaBlockOnNet;
|
||||
sqbaBlockOnNet += bytes;
|
||||
//qint64 aaa = bytesAvailable();
|
||||
//pline() << aaa;
|
||||
|
||||
do
|
||||
{
|
||||
quint16 nBlockLen = m_protocol->splitter ( sqbaBlockOnNet );
|
||||
|
||||
pmeta ( this ) << sqbaBlockOnNet.size() << "..." << nBlockLen;
|
||||
|
||||
if ( sqbaBlockOnNet.length() < nBlockLen || nBlockLen < m_protocol->minlength() )
|
||||
{
|
||||
/*
|
||||
* 收到数据不足或者解析包长小于最小包长
|
||||
*/
|
||||
return;
|
||||
}
|
||||
else if ( nBlockLen > m_protocol->maxlength() )
|
||||
{
|
||||
/*
|
||||
* 数据包长超过了最大长度
|
||||
*/
|
||||
sqbaBlockOnNet.clear();
|
||||
pmeta ( this ) << "forbidden package" << sqbaBlockOnNet.length() << nBlockLen;
|
||||
return;
|
||||
}
|
||||
else if ( sqbaBlockOnNet.length() > nBlockLen )
|
||||
{
|
||||
/*
|
||||
* 粘包
|
||||
* 还没有处理完毕,数据已经接收到,异步信号处理出现这种异常
|
||||
* 疑问:如果异步调用这个函数绘出现什么问题?正常情况,同步获取数据,异步处理;检测异步获取并且处理会有什么状况
|
||||
*/
|
||||
pmeta ( this ) << "stick package" << sqbaBlockOnNet.length() << nBlockLen;
|
||||
QByteArray netData;
|
||||
netData.resize ( nBlockLen );
|
||||
sqbaBlockOnNet >> netData;
|
||||
m_protocol->dispatcher ( netData );
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* 正常分发
|
||||
*/
|
||||
m_protocol->dispatcher ( sqbaBlockOnNet );
|
||||
break;
|
||||
} while ( 1 );
|
||||
|
||||
sqbaBlockOnNet.clear();
|
||||
}
|
||||
|
@ -2,8 +2,8 @@
|
||||
* QQtTcpClient
|
||||
* 在一个工程当中仅仅存在一个实例,通过调用QQtTcpClient实现。
|
||||
**************************************************/
|
||||
#ifndef QQT_CLIENT_H
|
||||
#define QQT_CLIENT_H
|
||||
#ifndef QQTTCPCLIENT_H
|
||||
#define QQTTCPCLIENT_H
|
||||
|
||||
#include <QTcpSocket>
|
||||
#include "QStringList"
|
||||
@ -32,15 +32,21 @@ public:
|
||||
explicit QQtTcpClient ( QObject* parent = 0 );
|
||||
virtual ~QQtTcpClient();
|
||||
|
||||
void SetServerIPAddress ( QStringList ip ) { m_serverIP = ip; }
|
||||
void SetServerPort ( quint32 p = 7079 ) { m_PORT = p; }
|
||||
void setServerIPAddress ( QString ip ) {
|
||||
if ( m_serverIP.contains ( ip ) )
|
||||
return;
|
||||
m_serverIP.push_back ( ip );
|
||||
}
|
||||
QStringList& serverIPAddress() { return m_serverIP; }
|
||||
void setServerIPAddress ( QStringList ipList ) { m_serverIP = ipList; }
|
||||
void setServerPort ( quint32 p = 7079 ) { m_PORT = p; }
|
||||
|
||||
void installProtocol ( QQtProtocol* stack );
|
||||
void uninstallProtocol ( QQtProtocol* stack );
|
||||
QQtProtocol* installedProtocol();
|
||||
|
||||
void SendConnectMessage();
|
||||
int SendDisConnectFromHost();
|
||||
void sendConnectToHost();
|
||||
int sendDisConnectFromHost();
|
||||
|
||||
signals:
|
||||
void signalConnecting();
|
||||
@ -61,11 +67,18 @@ private slots:
|
||||
|
||||
protected slots:
|
||||
void readyReadData();
|
||||
void writeData ( const QByteArray& );
|
||||
void slotWriteData ( const QByteArray& );
|
||||
|
||||
private:
|
||||
protected:
|
||||
/**
|
||||
* @brief translator
|
||||
* 用于拆分和分发数据报
|
||||
* @param bytes
|
||||
*/
|
||||
virtual void translator ( const QByteArray& bytes );
|
||||
void connectToSingelHost();
|
||||
|
||||
private:
|
||||
/*
|
||||
* TODO:如果文件传输影响到了UI线程,那么需要将QTcpSocket局部变量化
|
||||
* 阻塞UI不必考虑此处
|
||||
@ -80,4 +93,4 @@ private:
|
||||
};
|
||||
|
||||
|
||||
#endif // QQT_CLIENT_H
|
||||
#endif // QQTTCPCLIENT_H
|
||||
|
@ -1,10 +1,9 @@
|
||||
#include "qqttcpserver.h"
|
||||
#include "qqtnetwork.h"
|
||||
|
||||
|
||||
QQtTcpServer::QQtTcpServer ( QObject* parent ) :
|
||||
QTcpServer ( parent )
|
||||
{
|
||||
m_protocolManager = NULL;
|
||||
}
|
||||
|
||||
QQtTcpServer::~QQtTcpServer()
|
||||
@ -17,30 +16,48 @@ void QQtTcpServer::incomingConnection ( qintptr handle )
|
||||
{
|
||||
QQtTcpClient* clientSocket = new QQtTcpClient ( this );
|
||||
clientSocket->setSocketDescriptor ( handle );
|
||||
connect ( clientSocket, SIGNAL ( disconnected() ), clientSocket, SLOT ( deleteLater() ) );
|
||||
clientSocket->installProtocol ( m_protocol );
|
||||
if ( !m_protocolManager )
|
||||
{
|
||||
pline() << "please install protocol manager for your server.";
|
||||
clientSocket->deleteLater();
|
||||
return;
|
||||
}
|
||||
|
||||
connect ( clientSocket, SIGNAL ( disconnected() ), this, SLOT ( clientSocketDisConnected() ) );
|
||||
//如果崩溃,对这个操作进行加锁。
|
||||
QQtProtocol* protocol = m_protocolManager->createProtocol();
|
||||
clientSocket->installProtocol ( protocol );
|
||||
}
|
||||
|
||||
void QQtTcpServer::installProtocol ( QQtProtocol* stack )
|
||||
void QQtTcpServer::clientSocketDisConnected()
|
||||
{
|
||||
if ( m_protocol )
|
||||
QObject* obj = sender();
|
||||
QQtTcpClient* clientSocket = ( QQtTcpClient* ) obj;
|
||||
QQtProtocol* protocol = clientSocket->installedProtocol();
|
||||
clientSocket->uninstallProtocol ( protocol );
|
||||
clientSocket->deleteLater();
|
||||
protocol->deleteLater();
|
||||
}
|
||||
|
||||
void QQtTcpServer::installProtocolManager ( QQtProtocolManager* stackGroup )
|
||||
{
|
||||
if ( m_protocolManager )
|
||||
return;
|
||||
|
||||
m_protocol = stack;
|
||||
m_protocolManager = stackGroup;
|
||||
}
|
||||
|
||||
void QQtTcpServer::uninstallProtocol ( QQtProtocol* stack )
|
||||
void QQtTcpServer::uninstallProtocolManager ( QQtProtocolManager* stackGroup )
|
||||
{
|
||||
Q_UNUSED ( stack )
|
||||
Q_UNUSED ( stackGroup )
|
||||
|
||||
if ( !m_protocol )
|
||||
if ( !m_protocolManager )
|
||||
return;
|
||||
|
||||
m_protocol = NULL;
|
||||
m_protocolManager = NULL;
|
||||
}
|
||||
|
||||
QQtProtocol* QQtTcpServer::installedProtocol()
|
||||
QQtProtocolManager* QQtTcpServer::installedProtocolManager()
|
||||
{
|
||||
return m_protocol;
|
||||
return m_protocolManager;
|
||||
}
|
||||
|
||||
|
@ -2,15 +2,13 @@
|
||||
#define QQTTCPSERVER_H
|
||||
|
||||
#include <QTcpServer>
|
||||
#include "qqtprotocol.h"
|
||||
#include "qqtprotocolmanager.h"
|
||||
#include "qqttcpclient.h"
|
||||
#include "qqt-local.h"
|
||||
#include "qqtcore.h"
|
||||
|
||||
/**
|
||||
* @brief The QQtTcpServer class
|
||||
* 这个是群发Server,
|
||||
* 给一个客户端发一个信息,多个客户端,这一个信息会群发。
|
||||
*/
|
||||
class QQTSHARED_EXPORT QQtTcpServer : public QTcpServer
|
||||
{
|
||||
@ -19,16 +17,18 @@ public:
|
||||
explicit QQtTcpServer ( QObject* parent = 0 );
|
||||
~QQtTcpServer();
|
||||
|
||||
void installProtocol ( QQtProtocol* stack );
|
||||
void uninstallProtocol ( QQtProtocol* stack );
|
||||
QQtProtocol* installedProtocol();
|
||||
void installProtocolManager ( QQtProtocolManager* stackGroup );
|
||||
void uninstallProtocolManager ( QQtProtocolManager* stackGroup );
|
||||
QQtProtocolManager* installedProtocolManager();
|
||||
|
||||
signals:
|
||||
// QTcpServer interface
|
||||
protected:
|
||||
virtual void incomingConnection ( qintptr handle ) override;
|
||||
private:
|
||||
QQtProtocol* m_protocol;
|
||||
QQtProtocolManager* m_protocolManager;
|
||||
public slots:
|
||||
void clientSocketDisConnected();
|
||||
};
|
||||
|
||||
|
||||
|
@ -23,29 +23,29 @@ QQtUdpClient::QQtUdpClient ( QObject* parent ) : QUdpSocket ( parent )
|
||||
m_protocol = NULL;
|
||||
}
|
||||
|
||||
void QQtUdpClient::installProtocol ( QQtUdpProtocol* stack )
|
||||
void QQtUdpClient::installProtocol ( QQtProtocol* stack )
|
||||
{
|
||||
if ( m_protocol )
|
||||
return;
|
||||
|
||||
m_protocol = stack;
|
||||
connect ( m_protocol, SIGNAL ( writeDatagram ( QByteArray, QHostAddress, quint16 ) ),
|
||||
this, SLOT ( slotWriteDatagram ( QByteArray, QHostAddress, quint16 ) ) );
|
||||
connect ( m_protocol, SIGNAL ( write ( const QByteArray& ) ),
|
||||
this, SLOT ( slotWriteData ( const QByteArray& ) ) );
|
||||
}
|
||||
|
||||
void QQtUdpClient::uninstallProtocol ( QQtUdpProtocol* stack )
|
||||
void QQtUdpClient::uninstallProtocol ( QQtProtocol* stack )
|
||||
{
|
||||
Q_UNUSED ( stack )
|
||||
|
||||
if ( !m_protocol )
|
||||
return;
|
||||
|
||||
disconnect ( m_protocol, SIGNAL ( writeDatagram ( QByteArray, QHostAddress, quint16 ) ),
|
||||
this, SLOT ( slotWriteDatagram ( QByteArray, QHostAddress, quint16 ) ) );
|
||||
disconnect ( m_protocol, SIGNAL ( write ( const QByteArray& ) ),
|
||||
this, SLOT ( slotWriteData ( const QByteArray& ) ) );
|
||||
m_protocol = NULL;
|
||||
}
|
||||
|
||||
QQtUdpProtocol* QQtUdpClient::installedProtocol()
|
||||
QQtProtocol* QQtUdpClient::installedProtocol()
|
||||
{
|
||||
return m_protocol;
|
||||
}
|
||||
@ -119,6 +119,10 @@ void QQtUdpClient::socketConnected()
|
||||
* 这个步骤,socket重建,资源重新开始
|
||||
*/
|
||||
emit signalConnectSucc();
|
||||
if ( !m_protocol )
|
||||
{
|
||||
pline() << "please install protocol for your udp client.";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -136,9 +140,35 @@ void QQtUdpClient::updateProgress ( qint64 bytes )
|
||||
//pline() << bytes;
|
||||
}
|
||||
|
||||
qint64 QQtUdpClient::slotWriteDatagram ( const QByteArray& datagram, const QHostAddress& host, quint16 port )
|
||||
void QQtUdpClient::translator ( const QByteArray& bytes )
|
||||
{
|
||||
return writeDatagram ( datagram, host, port );
|
||||
//pline() << m_protocol;
|
||||
m_protocol->dispatcher ( bytes );
|
||||
}
|
||||
|
||||
void QQtUdpClient::recvDatagram ( QByteArray& bytes, QHostAddress& address, quint16& port )
|
||||
{
|
||||
#if QT_VERSION > QT_VERSION_DATAGRAM
|
||||
/*能够一次收够一条报文?测试的能。*/
|
||||
QNetworkDatagram datagram = receiveDatagram();
|
||||
/*由于添加了兼容Qt4的代码,以上注释起来。*/
|
||||
/*数据无意义 "" -1 在此设置*/
|
||||
datagram.setDestination ( this->localAddress(), this->localPort() );
|
||||
//pline() << "udp sender:" << datagram.senderAddress() << datagram.senderPort();
|
||||
//pline() << "udp receiver:" << datagram.destinationAddress() << datagram.destinationPort();
|
||||
bytes = datagram.data();
|
||||
address = datagram.senderAddress();
|
||||
port = datagram.senderPort();
|
||||
#else
|
||||
qint64 size = pendingDatagramSize();
|
||||
//pline() << "udp new msg size:" << size;
|
||||
//这里的buf用完, 已经释放。
|
||||
char* data = new char[size + 1]();
|
||||
qint64 len = readDatagram ( data, size, &address, &port );
|
||||
pline() << len;
|
||||
bytes.setRawData ( data, size );
|
||||
delete[] data;
|
||||
#endif
|
||||
}
|
||||
|
||||
void QQtUdpClient::readyReadData()
|
||||
@ -147,38 +177,23 @@ void QQtUdpClient::readyReadData()
|
||||
while ( hasPendingDatagrams() )
|
||||
{
|
||||
QByteArray bytes;
|
||||
qint64 maxlen = 0;
|
||||
QHostAddress host;
|
||||
QHostAddress address;
|
||||
quint16 port;
|
||||
|
||||
#if QT_VERSION > QT_VERSION_DATAGRAM
|
||||
/*能够一次收够一条报文?测试的能。*/
|
||||
QNetworkDatagram datagram = receiveDatagram();
|
||||
/*由于添加了兼容Qt4的代码,以上注释起来。*/
|
||||
|
||||
/*数据无意义 "" -1 在此设置*/
|
||||
datagram.setDestination ( this->localAddress(), this->localPort() );
|
||||
//pline() << "udp sender:" << datagram.senderAddress() << datagram.senderPort();
|
||||
//pline() << "udp receiver:" << datagram.destinationAddress() << datagram.destinationPort();
|
||||
m_protocol->translator ( datagram );
|
||||
|
||||
bytes = datagram.data();
|
||||
host = datagram.senderAddress();
|
||||
port = datagram.senderPort();
|
||||
m_protocol->translator ( bytes, host, port );
|
||||
#else
|
||||
qint64 size = pendingDatagramSize();
|
||||
//pline() << "udp new msg size:" << size;
|
||||
//这里的buf用完, 已经释放。
|
||||
char* data = new char[size + 1]();
|
||||
qint64 len = readDatagram ( data, size, &host, &port );
|
||||
pline() << len;
|
||||
bytes.setRawData ( data, size );
|
||||
delete[] data;
|
||||
|
||||
m_protocol->translator ( bytes, host, port );
|
||||
#endif
|
||||
|
||||
recvDatagram ( bytes, address, port );
|
||||
translator ( bytes );
|
||||
}
|
||||
}
|
||||
|
||||
void QQtUdpClient::slotWriteData ( const QByteArray& bytes )
|
||||
{
|
||||
#if QT_VERSION > QT_VERSION_DATAGRAM
|
||||
QNetworkDatagram datagram;
|
||||
datagram.setData ( dg );
|
||||
datagram.setDestination ( QHostAddress ( mIP ), mPort );
|
||||
datagram.setSender ( localAddress(), localPort() );
|
||||
writeDatagram ( datagram );
|
||||
#else
|
||||
writeDatagram ( bytes, QHostAddress ( mIP ), mPort );
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -2,10 +2,16 @@
|
||||
#define QQTUDPCLIENT_H
|
||||
|
||||
#include <QUdpSocket>
|
||||
#include "qqtudpprotocol.h"
|
||||
#include "qqtprotocol.h"
|
||||
#include "qqt-local.h"
|
||||
#include "qqtcore.h"
|
||||
|
||||
#define QT_VERSION_DATAGRAM QT_VERSION_CHECK(5,8,0)
|
||||
|
||||
#if QT_VERSION > QT_VERSION_DATAGRAM
|
||||
#include <QNetworkDatagram>
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Udp通信客户端
|
||||
*
|
||||
@ -13,6 +19,7 @@
|
||||
*
|
||||
* 默认情况下,就可以接收发送数据了。在协议里处理接收、发送。
|
||||
* 只有绑定本地IP、端口才能进行接收
|
||||
*
|
||||
*/
|
||||
class QQTSHARED_EXPORT QQtUdpClient : public QUdpSocket
|
||||
{
|
||||
@ -21,9 +28,18 @@ public:
|
||||
explicit QQtUdpClient ( QObject* parent = nullptr );
|
||||
virtual ~QQtUdpClient() {}
|
||||
|
||||
void installProtocol ( QQtUdpProtocol* stack );
|
||||
void uninstallProtocol ( QQtUdpProtocol* stack );
|
||||
QQtUdpProtocol* installedProtocol();
|
||||
void setServer ( QString ip, quint16 port ) {
|
||||
mIP = ip;
|
||||
mPort = port;
|
||||
}
|
||||
void getServer ( QString& ip, quint16& port ) {
|
||||
ip = mIP;
|
||||
port = mPort;
|
||||
}
|
||||
|
||||
void installProtocol ( QQtProtocol* stack );
|
||||
void uninstallProtocol ( QQtProtocol* stack );
|
||||
QQtProtocol* installedProtocol();
|
||||
|
||||
signals:
|
||||
void signalConnecting();
|
||||
@ -35,7 +51,8 @@ signals:
|
||||
public slots:
|
||||
|
||||
protected slots:
|
||||
void readyReadData();
|
||||
virtual void readyReadData();
|
||||
void slotWriteData ( const QByteArray& );
|
||||
private slots:
|
||||
void domainHostFound();
|
||||
void socketStateChanged ( QAbstractSocket::SocketState );
|
||||
@ -46,11 +63,19 @@ private slots:
|
||||
//如果有一个同名的槽,参数不同,并且被用宏控制起来,Qt编译不过。
|
||||
//Qt的元对象系统,解析信号和槽函数,不支持宏。
|
||||
//QtUdpSocket,writeDatagram不是个槽。
|
||||
qint64 slotWriteDatagram ( const QByteArray& datagram,
|
||||
const QHostAddress& host, quint16 port );
|
||||
|
||||
protected:
|
||||
/**
|
||||
* @brief translator
|
||||
* 用于拆分和分发数据报
|
||||
* @param bytes
|
||||
*/
|
||||
void translator ( const QByteArray& bytes );
|
||||
virtual void recvDatagram ( QByteArray& bytes, QHostAddress& address, quint16& port );
|
||||
private:
|
||||
QQtUdpProtocol* m_protocol;
|
||||
QQtProtocol* m_protocol;
|
||||
QString mIP;
|
||||
quint16 mPort;
|
||||
};
|
||||
|
||||
#endif // QQTUDPCLIENT_H
|
||||
|
@ -1 +0,0 @@
|
||||
#include "qqtudpprotocol.h"
|
@ -1,77 +0,0 @@
|
||||
#ifndef QQTUDPPROTOCOL_H
|
||||
#define QQTUDPPROTOCOL_H
|
||||
|
||||
#include <QObject>
|
||||
#include <qqt-local.h>
|
||||
#include "qqtmessage.h"
|
||||
#include "qqtcore.h"
|
||||
|
||||
#define QT_VERSION_DATAGRAM QT_VERSION_CHECK(5,8,0)
|
||||
|
||||
#if QT_VERSION > QT_VERSION_DATAGRAM
|
||||
#include <QNetworkDatagram>
|
||||
#endif
|
||||
|
||||
/*
|
||||
*/
|
||||
class QQTSHARED_EXPORT QQtUdpProtocol : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit QQtUdpProtocol ( QObject* parent = nullptr ) : QObject ( parent ) {
|
||||
|
||||
}
|
||||
virtual ~QQtUdpProtocol() {}
|
||||
|
||||
#if QT_VERSION > QT_VERSION_DATAGRAM
|
||||
qint64 writeDatagram ( const QNetworkDatagram& datagram ) {
|
||||
QByteArray dg = datagram.data();
|
||||
QHostAddress addr = datagram.destinationAddress();
|
||||
int port = datagram.destinationPort();
|
||||
emit writeDatagram ( dg, addr, ( quint16 ) port );
|
||||
}
|
||||
#endif
|
||||
|
||||
signals:
|
||||
qint64 writeDatagram ( const QByteArray& datagram,
|
||||
const QHostAddress& host, quint16 port );
|
||||
|
||||
public slots:
|
||||
|
||||
protected:
|
||||
/**
|
||||
* @brief 语义解析器
|
||||
* @brief 用户必须继承下去,重写,need override
|
||||
* @param 数据包
|
||||
* @return 0 no dispatched(others) 1 dispatched(own)
|
||||
*/
|
||||
inline virtual bool dispatcher ( const QByteArray& datagram,
|
||||
const QHostAddress& host, quint16 port ) {
|
||||
return 0;
|
||||
}
|
||||
/*
|
||||
* 这两个dispatcher,任选其一重写。
|
||||
*/
|
||||
#if QT_VERSION > QT_VERSION_DATAGRAM
|
||||
inline virtual bool dispatcher ( const QNetworkDatagram& ) { return 0; }
|
||||
#endif
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief 协议处理器
|
||||
* @brief 这个处理器是给QQtUdpSocket用的,不需要用户管理。
|
||||
* @param Qt通讯口readAll()读到的bytes
|
||||
* @return
|
||||
*/
|
||||
void translator ( const QByteArray& datagram,
|
||||
const QHostAddress& host, quint16 port ) {
|
||||
dispatcher ( datagram, host, port );
|
||||
}
|
||||
#if QT_VERSION > QT_VERSION_DATAGRAM
|
||||
void translator ( const QNetworkDatagram& datagram ) {
|
||||
dispatcher ( datagram );
|
||||
}
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif // QQTUDPPROTOCOL_H
|
@ -1,145 +1,76 @@
|
||||
#include "qqtudpserver.h"
|
||||
|
||||
QQtUdpServer::QQtUdpServer ( QObject* parent ) : QUdpSocket ( parent )
|
||||
QQtUdpServer::QQtUdpServer ( QObject* parent ) : QQtUdpClient ( parent )
|
||||
{
|
||||
connect ( this, SIGNAL ( stateChanged ( QAbstractSocket::SocketState ) ), this,
|
||||
SLOT ( socketStateChanged ( QAbstractSocket::SocketState ) ) );
|
||||
// connected
|
||||
connect ( this, SIGNAL ( connected() ), this, SLOT ( socketConnected() ) );
|
||||
// disconnected
|
||||
connect ( this, SIGNAL ( disconnected() ), this, SLOT ( socketDisconnect() ) );
|
||||
// domain
|
||||
connect ( this, SIGNAL ( hostFound() ), this, SLOT ( domainHostFound() ) );
|
||||
// error
|
||||
connect ( this, SIGNAL ( error ( QAbstractSocket::SocketError ) ), this,
|
||||
SLOT ( socketErrorOccured ( QAbstractSocket::SocketError ) ) );
|
||||
|
||||
connect ( this, SIGNAL ( readyRead() ), this, SLOT ( readyReadData() ) );
|
||||
|
||||
connect ( this, SIGNAL ( bytesWritten ( qint64 ) ), this, SLOT ( updateProgress ( qint64 ) ) );
|
||||
|
||||
connect ( this, SIGNAL ( bytesWritten ( qint64 ) ), this, SIGNAL ( signalUpdateProgress ( qint64 ) ) );
|
||||
|
||||
m_protocol = NULL;
|
||||
m_protocolManager = NULL;
|
||||
}
|
||||
|
||||
void QQtUdpServer::installProtocol ( QQtUdpProtocol* stack )
|
||||
void QQtUdpServer::installProtocolManager ( QQtProtocolManager* stackGroup )
|
||||
{
|
||||
if ( m_protocol )
|
||||
if ( m_protocolManager )
|
||||
return;
|
||||
|
||||
m_protocol = stack;
|
||||
connect ( m_protocol, SIGNAL ( writeDatagram ( QByteArray, QHostAddress, quint16 ) ),
|
||||
this, SLOT ( slotWriteDatagram ( QByteArray, QHostAddress, quint16 ) ) );
|
||||
m_protocolManager = stackGroup;
|
||||
}
|
||||
|
||||
void QQtUdpServer::uninstallProtocol ( QQtUdpProtocol* stack )
|
||||
void QQtUdpServer::uninstallProtocolManager ( QQtProtocolManager* stackGroup )
|
||||
{
|
||||
Q_UNUSED ( stack )
|
||||
Q_UNUSED ( stackGroup )
|
||||
|
||||
if ( !m_protocol )
|
||||
if ( !m_protocolManager )
|
||||
return;
|
||||
|
||||
disconnect ( m_protocol, SIGNAL ( writeDatagram ( QByteArray, QHostAddress, quint16 ) ),
|
||||
this, SLOT ( slotWriteDatagram ( QByteArray, QHostAddress, quint16 ) ) );
|
||||
m_protocol = NULL;
|
||||
m_protocolManager = NULL;
|
||||
}
|
||||
|
||||
QQtUdpProtocol* QQtUdpServer::installedProtocol()
|
||||
QQtProtocolManager* QQtUdpServer::installedProtocolManager()
|
||||
{
|
||||
return m_protocol;
|
||||
return m_protocolManager;
|
||||
}
|
||||
|
||||
void QQtUdpServer::domainHostFound()
|
||||
void QQtUdpServer::clientSocketDisConnected()
|
||||
{
|
||||
pline();
|
||||
QObject* obj = sender();
|
||||
QQtUdpClient* clientSocket = ( QQtUdpClient* ) obj;
|
||||
QQtProtocol* protocol = clientSocket->installedProtocol();
|
||||
clientSocket->uninstallProtocol ( protocol );
|
||||
clientSocket->deleteLater();
|
||||
protocol->deleteLater();
|
||||
m_clientList.removeOne ( clientSocket );
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief QQtUdpClient::socketStateChanged
|
||||
* @param eSocketState
|
||||
* 状态函数
|
||||
*/
|
||||
void QQtUdpServer::socketStateChanged ( QAbstractSocket::SocketState eSocketState )
|
||||
QQtUdpClient* QQtUdpServer::findClientByProtocolInstance ( QQtProtocol* protocol )
|
||||
{
|
||||
pline() << eSocketState;
|
||||
|
||||
switch ( eSocketState )
|
||||
QListIterator<QQtUdpClient*> itor ( m_clientList );
|
||||
while ( itor.hasNext() )
|
||||
{
|
||||
case QAbstractSocket::HostLookupState:
|
||||
case QAbstractSocket::ConnectingState:
|
||||
break;
|
||||
|
||||
case QAbstractSocket::ConnectedState:
|
||||
break;
|
||||
|
||||
case QAbstractSocket::ClosingState:
|
||||
break;
|
||||
|
||||
case QAbstractSocket::UnconnectedState:
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
QQtUdpClient* client = itor.next();
|
||||
QQtProtocol* cprotocol = client->installedProtocol();
|
||||
if ( cprotocol == protocol )
|
||||
{
|
||||
return client;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief QQtUdpClient::socketErrorOccured
|
||||
* @param e
|
||||
* 状态函数
|
||||
*/
|
||||
void QQtUdpServer::socketErrorOccured ( QAbstractSocket::SocketError e )
|
||||
QQtUdpClient* QQtUdpServer::findClientByIPAddress ( QString ip, quint16 port )
|
||||
{
|
||||
/*
|
||||
* 在错误状态下重新连接其他热点,直到确定连接类型,写入配置文件
|
||||
*/
|
||||
pline() << e;
|
||||
|
||||
switch ( e )
|
||||
QListIterator<QQtUdpClient*> itor ( m_clientList );
|
||||
while ( itor.hasNext() )
|
||||
{
|
||||
case QAbstractSocket::RemoteHostClosedError:
|
||||
break;
|
||||
|
||||
case QAbstractSocket::HostNotFoundError:
|
||||
default:
|
||||
emit signalConnectFail();
|
||||
break;
|
||||
QQtUdpClient* client = itor.next();
|
||||
QString aip;
|
||||
quint16 aport;
|
||||
client->getServer ( aip, aport );
|
||||
if ( aip == ip && aport == port )
|
||||
{
|
||||
return client;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief QQtUdpClient::socketConnected
|
||||
* 功能接口
|
||||
*/
|
||||
void QQtUdpServer::socketConnected()
|
||||
{
|
||||
pline() << peerName() << peerAddress().toString() << peerPort();
|
||||
/*
|
||||
* 这个步骤,socket重建,资源重新开始
|
||||
*/
|
||||
emit signalConnectSucc();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief QQtUdpClient::socketDisconnect
|
||||
* 功能接口
|
||||
*/
|
||||
void QQtUdpServer::socketDisconnect()
|
||||
{
|
||||
pline();
|
||||
}
|
||||
|
||||
void QQtUdpServer::updateProgress ( qint64 bytes )
|
||||
{
|
||||
Q_UNUSED ( bytes )
|
||||
//pline() << bytes;
|
||||
}
|
||||
|
||||
qint64 QQtUdpServer::slotWriteDatagram ( const QByteArray& datagram, const QHostAddress& host, quint16 port )
|
||||
{
|
||||
return writeDatagram ( datagram, host, port );
|
||||
}
|
||||
|
||||
void QQtUdpServer::readyReadData()
|
||||
{
|
||||
@ -147,38 +78,34 @@ void QQtUdpServer::readyReadData()
|
||||
while ( hasPendingDatagrams() )
|
||||
{
|
||||
QByteArray bytes;
|
||||
qint64 maxlen = 0;
|
||||
QHostAddress host;
|
||||
QHostAddress address;
|
||||
quint16 port;
|
||||
recvDatagram ( bytes, address, port );
|
||||
|
||||
#if QT_VERSION > QT_VERSION_DATAGRAM
|
||||
/*能够一次收够一条报文?测试的能。*/
|
||||
QNetworkDatagram datagram = receiveDatagram();
|
||||
/*由于添加了兼容Qt4的代码,以上注释起来。*/
|
||||
|
||||
/*数据无意义 "" -1 在此设置*/
|
||||
datagram.setDestination ( this->localAddress(), this->localPort() );
|
||||
//pline() << "udp sender:" << datagram.senderAddress() << datagram.senderPort();
|
||||
//pline() << "udp receiver:" << datagram.destinationAddress() << datagram.destinationPort();
|
||||
m_protocol->translator ( datagram );
|
||||
|
||||
bytes = datagram.data();
|
||||
host = datagram.senderAddress();
|
||||
port = datagram.senderPort();
|
||||
m_protocol->translator ( bytes, host, port );
|
||||
#else
|
||||
qint64 size = pendingDatagramSize();
|
||||
//pline() << "udp new msg size:" << size;
|
||||
//这里的buf用完, 已经释放。
|
||||
char* data = new char[size + 1]();
|
||||
qint64 len = readDatagram ( data, size, &host, &port );
|
||||
pline() << len;
|
||||
bytes.setRawData ( data, size );
|
||||
delete[] data;
|
||||
|
||||
m_protocol->translator ( bytes, host, port );
|
||||
#endif
|
||||
|
||||
QString sip;
|
||||
quint16 sport;
|
||||
getServer ( sip, sport );
|
||||
if ( address.toString() == sip && sport == port )
|
||||
{
|
||||
//如果,特别的那个目标。
|
||||
translator ( bytes );
|
||||
}
|
||||
else
|
||||
{
|
||||
QQtUdpClient* clientSocket = findClientByIPAddress ( address.toString(), port );
|
||||
if ( !clientSocket )
|
||||
{
|
||||
clientSocket = new QQtUdpClient ( this );
|
||||
clientSocket->setServer ( address.toString(), port );
|
||||
connect ( clientSocket, SIGNAL ( disconnected() ), this, SLOT ( clientSocketDisConnected() ) );
|
||||
//如果崩溃,对这个操作进行加锁。
|
||||
QQtProtocol* protocol = m_protocolManager->createProtocol();
|
||||
clientSocket->installProtocol ( protocol );
|
||||
m_clientList.push_back ( clientSocket );
|
||||
}
|
||||
clientSocket->translator ( bytes );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -1,8 +1,7 @@
|
||||
#ifndef QQTUDPSERVER_H
|
||||
#define QQTUDPSERVER_H
|
||||
|
||||
#include <QUdpSocket>
|
||||
#include "qqtudpprotocol.h"
|
||||
#include "qqtprotocolmanager.h"
|
||||
#include "qqtudpclient.h"
|
||||
#include "qqt-local.h"
|
||||
#include "qqtcore.h"
|
||||
@ -17,49 +16,62 @@
|
||||
*
|
||||
* 默认情况下,就可以接收发送数据了。在协议里处理接收、发送。
|
||||
* 只有绑定本地IP、端口才能进行接收
|
||||
*
|
||||
* 注意
|
||||
* Server
|
||||
* bind 固定port recv
|
||||
* 句柄1 动态port sendTo Client必须绑定才能接收。
|
||||
* 句柄1 不能接收
|
||||
* Server端发出信息的肯定是动态端口。
|
||||
* Client
|
||||
* no bind 动态端口 sendTo
|
||||
* bind 固定端口 sendTo 而且可以recv
|
||||
*
|
||||
* 特点
|
||||
* Server发出去的时候,本地端口是动态端口。
|
||||
* 经过分析,Client一般都会忽视这个端口,只重视Server的IP和bind port。
|
||||
* 所以,Client端一定不会混淆服务器的。
|
||||
* 既然可以发回去,那么Client一定bind port了。Client bind port的时候,发出消息的本地端口是个固定值。:)
|
||||
*
|
||||
* 继承于QQtUdpClient
|
||||
* 说明有一套特殊的协议,用于一个特殊的目标,一般为组播服务器。
|
||||
*/
|
||||
class QQtUdpServer : public QUdpSocket
|
||||
class QQTSHARED_EXPORT QQtUdpServer : public QQtUdpClient
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit QQtUdpServer ( QObject* parent = nullptr );
|
||||
virtual ~QQtUdpServer() {}
|
||||
|
||||
void installProtocol ( QQtUdpProtocol* stack );
|
||||
void uninstallProtocol ( QQtUdpProtocol* stack );
|
||||
QQtUdpProtocol* installedProtocol();
|
||||
void installProtocolManager ( QQtProtocolManager* stackGroup );
|
||||
void uninstallProtocolManager ( QQtProtocolManager* stackGroup );
|
||||
QQtProtocolManager* installedProtocolManager();
|
||||
|
||||
QList<QQtUdpClient*> getClientList() const {
|
||||
return m_client_list;
|
||||
}
|
||||
|
||||
signals:
|
||||
void signalConnecting();
|
||||
void signalConnectSucc();
|
||||
void signalConnectFail();//
|
||||
void signalDisConnectSucc();//maybe
|
||||
void signalDisConnectFail();//
|
||||
void signalUpdateProgress ( qint64 value );
|
||||
public slots:
|
||||
public:
|
||||
QQtUdpClient* findClientByProtocolInstance ( QQtProtocol* protocol );
|
||||
QQtUdpClient* findClientByIPAddress ( QString ip, quint16 port );
|
||||
QList<QQtUdpClient*>& clientList() const { return m_clientList; }
|
||||
|
||||
/**
|
||||
* 以下和用户无关
|
||||
*/
|
||||
protected slots:
|
||||
void readyReadData();
|
||||
private slots:
|
||||
void domainHostFound();
|
||||
void socketStateChanged ( QAbstractSocket::SocketState );
|
||||
void socketErrorOccured ( QAbstractSocket::SocketError );
|
||||
void socketConnected();
|
||||
void socketDisconnect();
|
||||
void updateProgress ( qint64 bytes );
|
||||
//如果有一个同名的槽,参数不同,并且被用宏控制起来,Qt编译不过。
|
||||
//Qt的元对象系统,解析信号和槽函数,不支持宏。
|
||||
//QtUdpSocket,writeDatagram不是个槽。
|
||||
qint64 slotWriteDatagram ( const QByteArray& datagram,
|
||||
const QHostAddress& host, quint16 port );
|
||||
/**
|
||||
* 这个函数,在UDP Server里面没有用。Client句柄安装的Protocol会从Client句柄发出,不会从这里发出。
|
||||
* 我打算从这里往组播服务器发消息。
|
||||
* 用户可以在协议里面定义组播服务器的位置,并且定义获取组播地址的命令。
|
||||
* 注意哦,组播服务器一定要设置为仅仅识别为有数的几个服务器的接收,包括本服务器,否则会风暴的。
|
||||
*/
|
||||
//
|
||||
|
||||
public slots:
|
||||
void clientSocketDisConnected();
|
||||
|
||||
protected:
|
||||
private:
|
||||
QQtUdpProtocol* m_protocol;
|
||||
QList<QQtUdpClient*> m_client_list;
|
||||
QQtProtocolManager* m_protocolManager;
|
||||
QList<QQtUdpClient*> m_clientList;
|
||||
};
|
||||
|
||||
#endif // QQTUDPSERVER_H
|
||||
|
@ -1,7 +0,0 @@
|
||||
#include "qqtwebsocketprotocol.h"
|
||||
|
||||
QQtWebSocketProtocol::QQtWebSocketProtocol ( QObject* parent ) : QQtProtocol ( parent )
|
||||
{
|
||||
|
||||
}
|
||||
|
@ -1,22 +0,0 @@
|
||||
#ifndef QQTWEBPROTOCOL_H
|
||||
#define QQTWEBPROTOCOL_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QNetworkRequest>
|
||||
#include <QNetworkReply>
|
||||
#include <QSslError>
|
||||
#include <qqt-local.h>
|
||||
#include <qqtprotocol.h>
|
||||
|
||||
class QQTSHARED_EXPORT QQtWebSocketProtocol : public QQtProtocol
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit QQtWebSocketProtocol ( QObject* parent = 0 );
|
||||
|
||||
signals:
|
||||
|
||||
public slots:
|
||||
};
|
||||
|
||||
#endif // QQTWEBPROTOCOL_H
|
@ -224,46 +224,73 @@ contains(DEFINES, __QQTCHARTS__) {
|
||||
|
||||
#network
|
||||
contains (DEFINES, __NETWORKSUPPORT__) {
|
||||
HEADERS += \
|
||||
$$PWD/network/qqtmessage.h \
|
||||
SOURCES += \
|
||||
$$PWD/network/qqtprotocol.cpp \
|
||||
$$PWD/network/qqtnetwork.cpp
|
||||
HEADERS += \
|
||||
$$PWD/network/qqtprotocol.h \
|
||||
$$PWD/network/qqtnetwork.h
|
||||
SOURCES += \
|
||||
$$PWD/network/qqtudpprotocol.cpp
|
||||
HEADERS += \
|
||||
$$PWD/network/qqtudpprotocol.h
|
||||
|
||||
#tcpudpsocket
|
||||
#报文 用户重要
|
||||
HEADERS += \
|
||||
$$PWD/network/qqtmessage.h
|
||||
|
||||
#协议 用户重要
|
||||
HEADERS += \
|
||||
$$PWD/network/qqtprotocol.h
|
||||
|
||||
#protocol manager for server iodevice
|
||||
SOURCES += \
|
||||
$$PWD/network/qqtprotocolmanager.cpp
|
||||
HEADERS += \
|
||||
$$PWD/network/qqtprotocolmanager.h
|
||||
|
||||
#tcp and udp iodevice
|
||||
contains(DEFINES, __TCPUDPSOCKET__){
|
||||
#tcp client iodevice
|
||||
SOURCES += \
|
||||
$$PWD/network/qqttcpclient.cpp
|
||||
HEADERS += \
|
||||
$$PWD/network/qqttcpclient.h
|
||||
|
||||
#tcp server iodevice
|
||||
SOURCES += \
|
||||
$$PWD/network/qqttcpserver.cpp
|
||||
HEADERS += \
|
||||
$$PWD/network/qqttcpserver.h
|
||||
|
||||
#udp client iodevice
|
||||
SOURCES += \
|
||||
$$PWD/network/qqtudpclient.cpp
|
||||
HEADERS += \
|
||||
$$PWD/network/qqtudpclient.h
|
||||
|
||||
#udp server iodevice
|
||||
SOURCES += \
|
||||
$$PWD/network/qqtudpserver.cpp
|
||||
HEADERS += \
|
||||
$$PWD/network/qqtudpserver.h
|
||||
}
|
||||
|
||||
#serialport
|
||||
#serialport iodevice
|
||||
SOURCES += \
|
||||
$$PWD/network/qqtserialport.cpp
|
||||
HEADERS += \
|
||||
$$PWD/network/qqtserialport.h
|
||||
|
||||
#bluetooth
|
||||
#bluetooth iodevice
|
||||
#注释:在qqt_header.pri打开 DEFINES += __BLUETOOTH__
|
||||
contains (DEFINES, __BLUETOOTH__) {
|
||||
#bluetooth socket
|
||||
#bluetooth client iodevice
|
||||
SOURCES += \
|
||||
$$PWD/network/qqtbluetoothclient.cpp
|
||||
HEADERS += \
|
||||
$$PWD/network/qqtbluetoothclient.h
|
||||
|
||||
#bluetooth server iodevice
|
||||
SOURCES += \
|
||||
$$PWD/network/qqtbluetoothserver.cpp
|
||||
HEADERS += \
|
||||
$$PWD/network/qqtbluetoothserver.h
|
||||
|
||||
#bluetooth manager
|
||||
SOURCES += \
|
||||
$$PWD/network/qqtbluetoothmanager.cpp
|
||||
@ -271,6 +298,19 @@ contains (DEFINES, __NETWORKSUPPORT__) {
|
||||
$$PWD/network/qqtbluetoothmanager.h
|
||||
}
|
||||
|
||||
contains (DEFINES, __WEBSOCKETSUPPORT__) {
|
||||
#websocket client iodevice
|
||||
SOURCES += \
|
||||
$$PWD/network/qqtwebsocketclient.cpp
|
||||
HEADERS += \
|
||||
$$PWD/network/qqtwebsocketclient.h
|
||||
#websocket server iodevice
|
||||
SOURCES += \
|
||||
$$PWD/network/qqtwebsocketserver.cpp
|
||||
HEADERS += \
|
||||
$$PWD/network/qqtwebsocketserver.h
|
||||
}
|
||||
|
||||
#ethnet(+wifi) manager
|
||||
#arm mips
|
||||
#TODO: +wince +android +ios +macOS? +win? +linux?
|
||||
@ -289,45 +329,6 @@ contains (DEFINES, __NETWORKSUPPORT__) {
|
||||
HEADERS += \
|
||||
$$PWD/network/qqtwebaccessmanager.h
|
||||
}
|
||||
|
||||
contains (DEFINES, __WEBSOCKETSUPPORT__) {
|
||||
SOURCES += \
|
||||
$$PWD/network/qqtwebsocketclient.cpp \
|
||||
$$PWD/network/qqtwebsocketprotocol.cpp
|
||||
HEADERS += \
|
||||
$$PWD/network/qqtwebsocketclient.h \
|
||||
$$PWD/network/qqtwebsocketprotocol.h
|
||||
}
|
||||
|
||||
#server
|
||||
SOURCES += \
|
||||
$$PWD/network/qqtprotocolmanager.cpp \
|
||||
HEADERS += \
|
||||
$$PWD/network/qqtprotocolmanager.h \
|
||||
|
||||
contains(DEFINES, __TCPUDPSOCKET__){
|
||||
SOURCES += \
|
||||
$$PWD/network/qqttcpserver.cpp
|
||||
HEADERS += \
|
||||
$$PWD/network/qqttcpserver.h
|
||||
SOURCES += \
|
||||
$$PWD/network/qqtudpserver.cpp
|
||||
HEADERS += \
|
||||
$$PWD/network/qqtudpserver.h
|
||||
}
|
||||
contains(DEFINES, __BLUETOOTH) {
|
||||
SOURCES += \
|
||||
$$PWD/network/qqtbluetoothserver.cpp
|
||||
HEADERS += \
|
||||
$$PWD/network/qqtbluetoothserver.h
|
||||
}
|
||||
contains (DEFINES, __WEBSOCKETSUPPORT__) {
|
||||
SOURCES += \
|
||||
$$PWD/network/qqtwebsocketserver.cpp
|
||||
HEADERS += \
|
||||
$$PWD/network/qqtwebsocketserver.h
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
contains (DEFINES, __EXQUISITE__) {
|
||||
@ -428,90 +429,4 @@ contains (DEFINES, __EXQUISITE__) {
|
||||
}
|
||||
}
|
||||
|
||||
contains (DEFINES, __HIGHGRADE__) {
|
||||
SOURCES += \
|
||||
$$PWD/highgrade/qqthgprotocolmanager.cpp
|
||||
HEADERS += \
|
||||
$$PWD/highgrade/qqthgprotocolmanager.h
|
||||
|
||||
SOURCES += \
|
||||
$$PWD/highgrade/qqthgprotocol.cpp
|
||||
HEADERS += \
|
||||
$$PWD/highgrade/qqthgprotocol.h
|
||||
|
||||
SOURCES += \
|
||||
$$PWD/highgrade/qqthgtcpprotocol.cpp
|
||||
HEADERS += \
|
||||
$$PWD/highgrade/qqthgtcpprotocol.h
|
||||
|
||||
SOURCES += \
|
||||
$$PWD/highgrade/qqthgudpprotocol.cpp
|
||||
HEADERS += \
|
||||
$$PWD/highgrade/qqthgudpprotocol.h
|
||||
|
||||
#tcpudpsocket
|
||||
contains(DEFINES, __TCPUDPSOCKET__){
|
||||
SOURCES += \
|
||||
$$PWD/highgrade/qqthgtcpclient.cpp
|
||||
HEADERS += \
|
||||
$$PWD/highgrade/qqthgtcpclient.h
|
||||
|
||||
SOURCES += \
|
||||
$$PWD/highgrade/qqthgudpclient.cpp
|
||||
HEADERS += \
|
||||
$$PWD/highgrade/qqthgudpclient.h
|
||||
}
|
||||
|
||||
#bluetooth
|
||||
#注释:在qqt_header.pri打开 DEFINES += __BLUETOOTH__
|
||||
contains (DEFINES, __BLUETOOTH__) {
|
||||
#bluetooth socket
|
||||
SOURCES += \
|
||||
$$PWD/highgrade/qqthgbluetoothclient.cpp
|
||||
HEADERS += \
|
||||
$$PWD/highgrade/qqthgbluetoothclient.h
|
||||
}
|
||||
|
||||
#webaccess manager
|
||||
contains (DEFINES, __WEBACCESSSUPPORT__) {
|
||||
SOURCES += \
|
||||
$$PWD/highgrade/qqthgwebaccessmanager.cpp
|
||||
HEADERS += \
|
||||
$$PWD/highgrade/qqthgwebaccessmanager.h
|
||||
}
|
||||
|
||||
contains (DEFINES, __WEBSOCKETSUPPORT__) {
|
||||
SOURCES += \
|
||||
$$PWD/highgrade/qqthgwebsocketclient.cpp \
|
||||
$$PWD/highgrade/qqthgwebsocketprotocol.cpp
|
||||
HEADERS += \
|
||||
$$PWD/highgrade/qqthgwebsocketclient.h \
|
||||
$$PWD/highgrade/qqthgwebsocketprotocol.h
|
||||
}
|
||||
|
||||
#highgrade server
|
||||
contains(DEFINES, __TCPUDPSOCKET__){
|
||||
SOURCES += \
|
||||
$$PWD/highgrade/qqthgtcpserver.cpp
|
||||
HEADERS += \
|
||||
$$PWD/highgrade/qqthgtcpserver.h
|
||||
SOURCES += \
|
||||
$$PWD/highgrade/qqthgudpserver.cpp
|
||||
HEADERS += \
|
||||
$$PWD/highgrade/qqthgudpserver.h
|
||||
}
|
||||
contains(DEFINES, __BLUETOOTH) {
|
||||
SOURCES += \
|
||||
$$PWD/highgrade/qqthgbluetoothserver.cpp
|
||||
HEADERS += \
|
||||
$$PWD/highgrade/qqthgbluetoothserver.h
|
||||
}
|
||||
contains (DEFINES, __WEBSOCKETSUPPORT__) {
|
||||
SOURCES += \
|
||||
$$PWD/highgrade/qqthgwebsocketserver.cpp
|
||||
HEADERS += \
|
||||
$$PWD/highgrade/qqthgwebsocketserver.h
|
||||
}
|
||||
}
|
||||
|
||||
include ($$PWD/qqt_3rdparty.pri)
|
||||
|
Loading…
x
Reference in New Issue
Block a user