Coder Social home page Coder Social logo

tcpserver's Introduction

基于QT网络库的服务器/客户端框架

依赖

  1. QT += network
  2. 主要使用了QTcpServerQTcpSocket

限制与约定

  1. 该框架实现了TCP短连接模型,服务器在回复TCP包后会主动close连接。
  2. srv.Start() 以后必须进入主事件循环。
  3. 框架底层在自动在每个数据包前加上一个4字节的包头,但是对于框架使用者来说是透明的。
void onMessage(Connection* conn, const QByteArray& msg);

参数msg是一个完整的消息且没有包头,不管tcp将该消息拆成多少个packet发送,msg是底层将packet组装后的完整数据。

  1. 消息msg在最大长度为4M-1,如果发送大文件,需要自行拆片。

协议包头格式

每一个数据包在发送前,应加上一个4字节(32位)的包头,包头有以下三个作用:

  • 校验数据包合法性。
  • 保证接收方能接收到一个完整的数据包。
  • 标识数据包采用的数据加密方式。
SS  XXXXXXXX  YYYYYYYYYYYYYYYYYYYYYY
┬-  ---┬----  ---------┬------------
│      │               │
│      │               └---> 包长度
│      └--------->包标识
└--->数据加密标识

说明:

  1. 前2位(SS)为数据加密标识位,用于标识数据采用何种加密算法进行加密,最大支持4种数据加密方式。
  • 00 加密算法0, 通常不加密
  • 01 加密算法1
  • 10 加密算法2
  • 11 加密算法3
  1. 中8位(X)为包头标识位,用于数据包校验。有效包头标识取值范围 0 ~ 255(0xFF)。默认值为0xE5。

  2. 后22位(Y)为长度位,记录包体长度。有效数据包最大长度不能超过 4194303(0x3FFFFF)字节。默认最大值4194303(4M-1)。

#define TCP_PACK_LENGTH_BITS    22
#define TCP_PACK_CRYPTION_BITS  30

#define TCP_PACK_HEADER_FLAG    0xE5
#define TCP_PACK_FLAG_MASK      0xFF

#define TCP_PACK_MAX_LEN        0x3FFFFF
#define TCP_PACK_LENGTH_MASK    0x3FFFFF

// 构造包头
inline quint32 MakeHeader(int len, int encryption)
{
    return (encryption << TCP_PACK_CRYPTION_BITS) | (TCP_PACK_HEADER_FLAG << TCP_PACK_LENGTH_BITS) | len;
}

// 从包头解出长度,返回-1表示非法包头
inline int GetPacketLen(quint32 header)
{
    unsigned short flag = (unsigned short)((header >> TCP_PACK_LENGTH_BITS) & TCP_PACK_FLAG_MASK);
    if (flag != TCP_PACK_HEADER_FLAG) {
        return -1;
    }
    return header & TCP_PACK_LENGTH_MASK;
}

// 获取数据加密算法类型
inline int GetEncryption(quint32 header)
{
    return header >> TCP_PACK_CRYPTION_BITS;
}

使用示例

#include "tcpserver.hpp"

// 服务器只需要实现 onMessage 内的业务逻辑
void onMessage(Connection* conn, const QByteArray& msg)
{
//    qDebug() << QThread::currentThreadId() << " recved: " << msg.size() << "MD5: "
//             << QCryptographicHash::hash(msg, QCryptographicHash::Md5).toHex();
    conn->Write(msg);
}

// 客户端使用方法
void TestClient()
{
    TcpClient clt("127.0.0.1", 8080);
    if (clt.Connect()) {
        QByteArray ret = clt.Send("Hello world!");
        qDebug() << ret;
    }
}

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    TcpServer srv(8080);
    srv.Start();

    QThread::sleep(1);

    std::thread t([](){
       TestClient();
    });

    return a.exec();
}

tcpserver's People

Watchers

James Cloos avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.