From 15104ce7c2f9f9550f85c63ee8db136cf065519c Mon Sep 17 00:00:00 2001 From: tianduanrui Date: Sun, 29 Apr 2018 01:13:42 +0800 Subject: [PATCH] update bluetooth serial socket --- src/network/qqtbluetoothclient.cpp | 78 +++++++++++++++++++++++- src/network/qqtbluetoothclient.h | 11 +++- src/network/qqtserialport.cpp | 96 ++++++++++++++++++++++++++---- src/network/qqtserialport.h | 36 ++++++----- src/network/qqtwebsocketclient.cpp | 45 +++++++++++++- src/network/qqtwebsocketclient.h | 29 ++++++--- src/network/qqtwebsocketserver.h | 10 ++-- src/qqt_source.pri | 84 +++++++++----------------- 8 files changed, 291 insertions(+), 98 deletions(-) diff --git a/src/network/qqtbluetoothclient.cpp b/src/network/qqtbluetoothclient.cpp index ac777ae4..fe041031 100644 --- a/src/network/qqtbluetoothclient.cpp +++ b/src/network/qqtbluetoothclient.cpp @@ -46,7 +46,7 @@ void QQtBluetoothClient::installProtocol ( QQtProtocol* stack ) m_protocol = stack; connect ( m_protocol, SIGNAL ( write ( const QByteArray& ) ), - this, SLOT ( write ( const QByteArray& ) ) ); + this, SLOT ( slotWriteData ( const QByteArray& ) ) ); } void QQtBluetoothClient::uninstallProtocol ( QQtProtocol* stack ) @@ -57,7 +57,7 @@ void QQtBluetoothClient::uninstallProtocol ( QQtProtocol* stack ) return; disconnect ( m_protocol, SIGNAL ( write ( const QByteArray& ) ), - this, SLOT ( write ( const QByteArray& ) ) ); + this, SLOT ( slotWriteData ( const QByteArray& ) ) ); m_protocol = NULL; } @@ -212,5 +212,77 @@ void QQtBluetoothClient::readyReadData() { QByteArray bytes; bytes = readAll(); - m_protocol->translator ( bytes ); + translator ( bytes ); +} + +void QQtBluetoothClient::slotWriteData ( const QByteArray& bytes ) +{ + write ( bytes ); +} + +void QQtBluetoothClient::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(); } diff --git a/src/network/qqtbluetoothclient.h b/src/network/qqtbluetoothclient.h index 702e4a25..0883faf7 100644 --- a/src/network/qqtbluetoothclient.h +++ b/src/network/qqtbluetoothclient.h @@ -10,7 +10,7 @@ class QQTSHARED_EXPORT QQtBluetoothClient : public QBluetoothSocket Q_OBJECT public: explicit QQtBluetoothClient ( QBluetoothServiceInfo::Protocol socketType = QBluetoothServiceInfo::RfcommProtocol, - QObject* parent = nullptr ); + QObject* parent = nullptr ); explicit QQtBluetoothClient ( QObject* parent = nullptr ); /** @@ -56,6 +56,15 @@ private slots: protected slots: void readyReadData(); + void slotWriteData ( const QByteArray& bytes ); + +protected: + /** + * @brief translator + * 用于拆分和分发数据报 + * @param bytes + */ + virtual void translator ( const QByteArray& bytes ); private: void connectToSingelHost(); diff --git a/src/network/qqtserialport.cpp b/src/network/qqtserialport.cpp index 3f5de1ef..a53126df 100644 --- a/src/network/qqtserialport.cpp +++ b/src/network/qqtserialport.cpp @@ -1,37 +1,39 @@ #include "qqtserialport.h" #include "qqtcore.h" -QQtSerialPort::QQtSerialPort(QObject* parent) : QSerialPort(parent) +QQtSerialPort::QQtSerialPort ( QObject* parent ) : QSerialPort ( parent ) { //connect(this, SIGNAL(bytesWritten(qint64)), this, SLOT(updateProgress(qint64)) ); - connect(this, SIGNAL(readyRead()), this, SLOT(readyReadData())); + connect ( this, SIGNAL ( readyRead() ), this, SLOT ( readyReadData() ) ); //connect(this, SIGNAL(aboutToClose()), this, SLOT(aboutToClose())); //connect(this, SIGNAL(readChannelFinished()), this, SLOT(readChannelFinished())); } QQtSerialPort::~QQtSerialPort() { - if (isOpen()) + if ( isOpen() ) close(); } -void QQtSerialPort::installProtocol(QQtProtocol* stack) +void QQtSerialPort::installProtocol ( QQtProtocol* stack ) { - if (m_protocol) + if ( m_protocol ) return; m_protocol = stack; - connect(m_protocol, SIGNAL(write(const QByteArray&)), this, SLOT(write(const QByteArray&))); + connect ( m_protocol, SIGNAL ( write ( const QByteArray& ) ), + this, SLOT ( slotWriteData ( const QByteArray& ) ) ); } -void QQtSerialPort::uninstallProtocol(QQtProtocol* stack) +void QQtSerialPort::uninstallProtocol ( QQtProtocol* stack ) { - Q_UNUSED(stack) + Q_UNUSED ( stack ) - if (!m_protocol) + if ( !m_protocol ) return; - disconnect(m_protocol, SIGNAL(write(const QByteArray&)), this, SLOT(write(const QByteArray&))); + disconnect ( m_protocol, SIGNAL ( write ( const QByteArray& ) ), + this, SLOT ( slotWriteData ( const QByteArray& ) ) ); m_protocol = NULL; } @@ -44,5 +46,77 @@ void QQtSerialPort::readyReadData() { QByteArray bytes; bytes = readAll(); - m_protocol->translator(bytes); + translator ( bytes ); +} + +void QQtSerialPort::slotWriteData ( const QByteArray& bytes ) +{ + write ( bytes ); +} + +void QQtSerialPort::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(); } diff --git a/src/network/qqtserialport.h b/src/network/qqtserialport.h index 5d16eb07..d264d84a 100644 --- a/src/network/qqtserialport.h +++ b/src/network/qqtserialport.h @@ -10,7 +10,7 @@ class QSerialPort : public QextSerialPort { Q_OBJECT public: - explicit QSerialPort(QObject* parent = 0) {} + explicit QSerialPort ( QObject* parent = 0 ) {} virtual ~QSerialPort() {} enum BaudRate { @@ -24,7 +24,7 @@ public: Baud115200 = BAUD115200, UnknownBaud = -1 }; - Q_ENUMS(BaudRate) + Q_ENUMS ( BaudRate ) enum DataBits { Data5 = DATA_5, @@ -33,7 +33,7 @@ public: Data8 = DATA_8, UnknownDataBits = -1 }; - Q_ENUMS(DataBits) + Q_ENUMS ( DataBits ) enum Parity { NoParity = PAR_NONE, @@ -43,7 +43,7 @@ public: MarkParity = PAR_MARK, UnknownParity = -1 }; - Q_ENUMS(Parity) + Q_ENUMS ( Parity ) enum StopBits { OneStop = STOP_1, @@ -51,7 +51,7 @@ public: TwoStop = STOP_2, UnknownStopBits = -1 }; - Q_ENUMS(StopBits) + Q_ENUMS ( StopBits ) enum FlowControl { NoFlowControl = FLOW_OFF, @@ -59,14 +59,14 @@ public: SoftwareControl = FLOW_XONXOFF, UnknownFlowControl = -1 }; - Q_ENUMS(FlowControl) + Q_ENUMS ( FlowControl ) // QextSerialBase interface public: - virtual void setBaudRate(BaudRate v) { QextSerialPort::setBaudRate((BaudRateType)v); } - virtual void setDataBits(DataBits v) { QextSerialPort::setDataBits((DataBitsType)v); } - virtual void setParity(Parity v) { QextSerialPort::setParity((ParityType)v); } - virtual void setStopBits(StopBits v) { QextSerialPort::setStopBits((StopBitsType)v); } - virtual void setFlowControl(FlowControl v) { QextSerialPort::setFlowControl((FlowType)v); } + virtual void setBaudRate ( BaudRate v ) { QextSerialPort::setBaudRate ( ( BaudRateType ) v ); } + virtual void setDataBits ( DataBits v ) { QextSerialPort::setDataBits ( ( DataBitsType ) v ); } + virtual void setParity ( Parity v ) { QextSerialPort::setParity ( ( ParityType ) v ); } + virtual void setStopBits ( StopBits v ) { QextSerialPort::setStopBits ( ( StopBitsType ) v ); } + virtual void setFlowControl ( FlowControl v ) { QextSerialPort::setFlowControl ( ( FlowType ) v ); } }; #else #include @@ -76,16 +76,24 @@ class QQTSHARED_EXPORT QQtSerialPort : public QSerialPort { Q_OBJECT public: - explicit QQtSerialPort(QObject* parent = 0); + explicit QQtSerialPort ( QObject* parent = 0 ); ~QQtSerialPort(); - void installProtocol(QQtProtocol* stack); - void uninstallProtocol(QQtProtocol* stack); + void installProtocol ( QQtProtocol* stack ); + void uninstallProtocol ( QQtProtocol* stack ); QQtProtocol* installedProtocol(); private slots: void readyReadData(); + void slotWriteData ( const QByteArray& bytes ); +protected: + /** + * @brief translator + * 用于拆分和分发数据报 + * @param bytes + */ + virtual void translator ( const QByteArray& bytes ); private: QQtProtocol* m_protocol; }; diff --git a/src/network/qqtwebsocketclient.cpp b/src/network/qqtwebsocketclient.cpp index 3f7a36f4..b12c2a20 100644 --- a/src/network/qqtwebsocketclient.cpp +++ b/src/network/qqtwebsocketclient.cpp @@ -3,5 +3,48 @@ QQtWebSocketClient::QQtWebSocketClient ( QObject* parent, const QString& origin, QWebSocketProtocol::Version version ) : QWebSocket ( origin, version, parent ) { - + connect ( this, SIGNAL ( binaryMessageReceived ( QByteArray ) ), + this, SLOT ( slotReadData ( QByteArray ) ) ); +} + +void QQtWebSocketClient::installProtocol ( QQtProtocol* stack ) +{ + if ( m_protocol ) + return; + + m_protocol = stack; + connect ( m_protocol, SIGNAL ( write ( const QByteArray& ) ), + this, SLOT ( slotWriteData ( const QByteArray& ) ) ); +} + +void QQtWebSocketClient::uninstallProtocol ( QQtProtocol* stack ) +{ + Q_UNUSED ( stack ) + + if ( !m_protocol ) + return; + + disconnect ( m_protocol, SIGNAL ( write ( const QByteArray& ) ), + this, SLOT ( slotWriteData ( const QByteArray& ) ) ); + m_protocol = NULL; +} + +QQtProtocol* QQtWebSocketClient::installedProtocol() +{ + return m_protocol; +} + +void QQtWebSocketClient::slotReadData ( const QByteArray& bytes ) +{ + translator ( bytes ); +} + +void QQtWebSocketClient::slotWriteData ( const QByteArray& bytes ) +{ + sendBinaryMessage ( bytes ); +} + +void QQtWebSocketClient::translator ( const QByteArray& bytes ) +{ + m_protocol->dispatcher ( bytes ); } diff --git a/src/network/qqtwebsocketclient.h b/src/network/qqtwebsocketclient.h index 983d4014..e20f2d3b 100644 --- a/src/network/qqtwebsocketclient.h +++ b/src/network/qqtwebsocketclient.h @@ -1,14 +1,14 @@ -#ifndef QQTWEBCLIENT_H -#define QQTWEBCLIENT_H +#ifndef QQTWEBSOCKETCLIENT_H +#define QQTWEBSOCKETCLIENT_H #include +#include #include #include /** - * @brief The QQtWebClient class - * QQtWebSocketClient通过安装QQtWebProtocol来实现和RawSocket相似的通信方式。 - * 暂时不确定QQtWebProtocol是否和QQtProtocol格式相同,所以暂时使用QQtWebProtocol继承QQtProtocol。 + * @brief The QQtWebSocketClient class + * QQtWebSocketClient通过安装QQtProtocol来实现和RawSocket相似的通信方式。 */ class QQTSHARED_EXPORT QQtWebSocketClient : public QWebSocket { @@ -18,11 +18,26 @@ public: const QString& origin = QString(), QWebSocketProtocol::Version version = QWebSocketProtocol::VersionLatest ); + void installProtocol ( QQtProtocol* stack ); + void uninstallProtocol ( QQtProtocol* stack ); + QQtProtocol* installedProtocol(); + signals: -public slots: +private slots: + void slotReadData ( const QByteArray& bytes ); + void slotWriteData ( const QByteArray& bytes ); + +protected: + /** + * @brief translator + * 用于拆分和分发数据报 + * @param bytes + */ + virtual void translator ( const QByteArray& bytes ); private: + QQtProtocol* m_protocol; }; -#endif // QQTWEBCLIENT_H +#endif // QQTWEBSOCKETCLIENT_H diff --git a/src/network/qqtwebsocketserver.h b/src/network/qqtwebsocketserver.h index cfb0b5dc..51f866c4 100644 --- a/src/network/qqtwebsocketserver.h +++ b/src/network/qqtwebsocketserver.h @@ -1,10 +1,10 @@ -#ifndef QQTWEBSERVER_H -#define QQTWEBSERVER_H +#ifndef QQTWEBSOCKETSERVER_H +#define QQTWEBSOCKETSERVER_H -#include +#include #include -class QQtWebSocketServer : public QObject +class QQtWebSocketServer : public QWebSocketServer { Q_OBJECT public: @@ -15,4 +15,4 @@ signals: public slots: }; -#endif // QQTWEBSERVER_H +#endif // QQTWEBSOCKETSERVER_H diff --git a/src/qqt_source.pri b/src/qqt_source.pri index 417781c1..3f0b4bbf 100644 --- a/src/qqt_source.pri +++ b/src/qqt_source.pri @@ -224,91 +224,65 @@ contains(DEFINES, __QQTCHARTS__) { #network contains (DEFINES, __NETWORKSUPPORT__) { - SOURCES += \ - $$PWD/network/qqtnetwork.cpp - HEADERS += \ - $$PWD/network/qqtnetwork.h + SOURCES += $$PWD/network/qqtnetwork.cpp + HEADERS += $$PWD/network/qqtnetwork.h #报文 用户重要 - HEADERS += \ - $$PWD/network/qqtmessage.h + HEADERS += $$PWD/network/qqtmessage.h #协议 用户重要 - HEADERS += \ - $$PWD/network/qqtprotocol.h + HEADERS += $$PWD/network/qqtprotocol.h #protocol manager for server iodevice - SOURCES += \ - $$PWD/network/qqtprotocolmanager.cpp - HEADERS += \ - $$PWD/network/qqtprotocolmanager.h + 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 + SOURCES += $$PWD/network/qqttcpclient.cpp + HEADERS += $$PWD/network/qqttcpclient.h #tcp server iodevice - SOURCES += \ - $$PWD/network/qqttcpserver.cpp - HEADERS += \ - $$PWD/network/qqttcpserver.h + SOURCES += $$PWD/network/qqttcpserver.cpp + HEADERS += $$PWD/network/qqttcpserver.h #udp client iodevice - SOURCES += \ - $$PWD/network/qqtudpclient.cpp - HEADERS += \ - $$PWD/network/qqtudpclient.h + SOURCES += $$PWD/network/qqtudpclient.cpp + HEADERS += $$PWD/network/qqtudpclient.h #udp server iodevice - SOURCES += \ - $$PWD/network/qqtudpserver.cpp - HEADERS += \ - $$PWD/network/qqtudpserver.h + SOURCES += $$PWD/network/qqtudpserver.cpp + HEADERS += $$PWD/network/qqtudpserver.h } #serialport iodevice - SOURCES += \ - $$PWD/network/qqtserialport.cpp - HEADERS += \ - $$PWD/network/qqtserialport.h + SOURCES += $$PWD/network/qqtserialport.cpp + HEADERS += $$PWD/network/qqtserialport.h #bluetooth iodevice #注释:在qqt_header.pri打开 DEFINES += __BLUETOOTH__ contains (DEFINES, __BLUETOOTH__) { #bluetooth client iodevice - SOURCES += \ - $$PWD/network/qqtbluetoothclient.cpp - HEADERS += \ - $$PWD/network/qqtbluetoothclient.h + SOURCES += $$PWD/network/qqtbluetoothclient.cpp + HEADERS += $$PWD/network/qqtbluetoothclient.h #bluetooth server iodevice - SOURCES += \ - $$PWD/network/qqtbluetoothserver.cpp - HEADERS += \ - $$PWD/network/qqtbluetoothserver.h + SOURCES += $$PWD/network/qqtbluetoothserver.cpp + HEADERS += $$PWD/network/qqtbluetoothserver.h #bluetooth manager - SOURCES += \ - $$PWD/network/qqtbluetoothmanager.cpp - HEADERS += \ - $$PWD/network/qqtbluetoothmanager.h + SOURCES += $$PWD/network/qqtbluetoothmanager.cpp + HEADERS += $$PWD/network/qqtbluetoothmanager.h } contains (DEFINES, __WEBSOCKETSUPPORT__) { #websocket client iodevice - SOURCES += \ - $$PWD/network/qqtwebsocketclient.cpp - HEADERS += \ - $$PWD/network/qqtwebsocketclient.h + SOURCES += $$PWD/network/qqtwebsocketclient.cpp + HEADERS += $$PWD/network/qqtwebsocketclient.h #websocket server iodevice - SOURCES += \ - $$PWD/network/qqtwebsocketserver.cpp - HEADERS += \ - $$PWD/network/qqtwebsocketserver.h + SOURCES += $$PWD/network/qqtwebsocketserver.cpp + HEADERS += $$PWD/network/qqtwebsocketserver.h } #ethnet(+wifi) manager @@ -324,10 +298,8 @@ contains (DEFINES, __NETWORKSUPPORT__) { #webaccess manager contains (DEFINES, __WEBACCESSSUPPORT__) { - SOURCES += \ - $$PWD/network/qqtwebaccessmanager.cpp - HEADERS += \ - $$PWD/network/qqtwebaccessmanager.h + SOURCES += $$PWD/network/qqtwebaccessmanager.cpp + HEADERS += $$PWD/network/qqtwebaccessmanager.h } }