• qt udp tcp代替RPC(二) 图片AI服务器


    以下是为了建立一个图片服务器而作,tcp作为服务端, 接收图片后可以用来做AI识别,因此而做,图片在内存里面,不经过AI存储到磁盘,经过推理后存储到磁盘,传输时需要缩小成AI服务器需要的样品大小。

    qt tcp

    本次介绍qt使用tcp 发送http restful 接口请求
    上次介绍过使用tcp和udp来发送信息,这次使用http发送,依然是使用异步发送,同时tcp放在一个线程里面,继承于QThread。缺点:http协议的字节数发送较多, http协议和rpc 协议的好处是一样的,rpc 一般来说兼容各种语言,http同样如此,本身就是标准协议。不同于rpc,http协议本身并不压缩。不过可以使用压缩方式来传送需要的字节,以下使用二进制方式读取。

    #include "mythread.h"
    #include 
    #include 
    #include 
    
    HTTPThread::HTTPThread(QObject *parent) : QThread(parent)
    {
    }
    
    HTTPThread::HTTPThread(QString ip, int port, QObject *parent) : QThread(parent)
    {
    	this->ip = ip;
    	this->port = port;
    }
    
    HTTPThread::~HTTPThread()
    {
    }
    
    void HTTPThread::run()
    {
    	isRunning = true;
    
    	QTcpSocket socket;
    	connect(&socket, SIGNAL(disconnected()), this, SIGNAL(disconnectSlot()));
    	socket.connectToHost(ip, port);
    
    	if(!socket.waitForConnected(3000)){
    		qDebug()<<"连接失败:"<<socket.errorString();
    		emit disconnectSlot();
    		return;
    	}else{
    		qDebug()<<"连接成功!";
    	}
    
    	//发送HTTP请求
    	socket.write("\r\n\r\n");
    	if(socket.waitForBytesWritten(1000)){
    		qDebug()<<"发送Http Request成功!";
    	}else{
    		qDebug()<<"发送Http Request失败!";
    		return;
    	}
    
    	//读取接收一副图片
    	QByteArray dataStream;
    	QRegExp rx("\\d+");
    	while(isRunning){
    		if(socket.waitForReadyRead()){
    			dataStream = socket.readLine();
    			if(dataStream.contains("Content-Length")){
    				int pos = rx.indexIn(dataStream);
    				if(pos > -1){
    					pos = rx.cap(0).toInt();
    					dataStream.resize(pos);
    					socket.readLine();
    					socket.read(dataStream.data(), pos);
    					emit transmitData(QImage::fromData(dataStream, "JPEG"));
    				}
    
    			}
    		}
    	}
    }
    

    注意点:
    1 http协议要代替rpc,尽量使用较少的头部字节,尽量简单,利用http协议的Content-Length 字段来获取二进制数据,发送的时候同样如此。
    2 如果使用

    movetothread

    movetothread 本身比直接继承要好

    tcp http server

    #include "myhttpserver.h"
    #include 
    
    HttpServer::MyHttpServer(QObject *parent) : QObject(parent)
    {
        server = new QTcpServer(this);
        connect(server, &QTcpServer::newConnection, this, &MyHttpServer::connection);
        if(!server->listen(QHostAddress::Any, 8080))
        {
            qDebug() << "\nerror";
        }
        else
        {
             qDebug() << "\nwait for 8080";
        }
    }
    
    void HttpServer::connection()
    {
        socket = server->nextPendingConnection();
    
        while (!(socket->waitForReadyRead(100))); //等待从浏览器读取数据
    
        char buffer[1024];
        int sv = socket->read(webBrowerRXData, 1000);
        qDebug() << "from =" << QString(webBrowerRXData);
    
        socket->write("HTTP/1.1 200 OK\r\n");       
        socket->write("Content-Type: text/html\r\n");
        socket->write("Connection: close\r\n");
        socket->write("Refresh: 1\r\n\r\n");      
        socket->write("Content-Length: xxxxx")
        //此处写入图片内容字节
        QByteArray str;
    //    read from disk
        //socket->write(.......)
        socket->write(str);
      
        socket->flush();
        connect(socket, &QTcpSocket::disconnected, socket, &QTcpSocket::deleteLater);
        socket->disconnectFromHost();
    
    }
    
    HttpServer::~MyHttpServer()
    {
        socket->close();
    }
    

    rpc方式 python 和 qt通信

    以下再探索一下使用rpc方式来做图片服务

    python 安装thrift

    pip install thrift==0.16

    service testSys{
        string rec_data(1:string data)
        binary imgdata
    }
    thrift --gen python RecSys.thrift
    
    
    import sys
    sys.path.append('./gen-py')
    
    from thrift import Thrift
    from thrift.transport import TSocket
    from thrift.transport import TTransport
    from thrift.protocol import TBinaryProtocol
    
    from testSys import testSys
    
    
    try:
        # 设置端口
        transport = TSocket.TSocket('localhost', port=9090)
    
        # 设置传输层
        transport = TTransport.TBufferedTransport(transport)
    
        # 设置传输协议
        protocol = TBinaryProtocol.TBinaryProtocol(transport)
    
        client = testSys.Client(protocol)
    
        transport.open()
    
        rst = client.rec_data("are you ok!!!")
        print "receive return data: ", rst
    
        transport.close()
    
    except Thrift.TException, ex:
        print "%s" % (ex.message)
    

    py server 代码

    #coding=utf=8
    
    import sys
    sys.path.append('../schema/gen-py')
    
    from thrift.transport import TSocket
    from thrift.transport import TTransport
    from thrift.protocol import TBinaryProtocol
    from thrift.server import TServer
    
    from RecSys import RecSys
    from RecSys.ttypes import *
    
    class RecSysHandler(RecSys.Iface):
        def rec_data(self, a):
            print "Receive: %s" %(a)
            return "I'm OK !!!"
    
    
    if __name__ == "__main__":
    
        # 实例化handler
        handler = RecSysHandler()
    
        # 设置processor
        processor = RecSys.Processor(handler)
    
        # 设置端口
        transport = TSocket.TServerSocket('localhost', port=9090)
    
        # 设置传输层
        tfactory = TTransport.TBufferedTransportFactory()
    
        # 设置传输协议
        pfactory = TBinaryProtocol.TBinaryProtocolFactory()
    
        server = TServer.TThreadedServer(processor, transport, tfactory, pfactory)
    
        print 'Starting the server...'
        server.serve()
        print 'done.'
    

    c++ client

    #include "RecSys.h"
    #include 
    #include 
    
    #include 
    #include 
    #include 
    
    using namespace apache::thrift;
    using namespace apache::thrift::protocol;
    using namespace apache::thrift::transport;
    using namespace std;
    
    
    int main(int argc, char **argv) {
    
        boost::shared_ptr<TSocket> socket(new TSocket("localhost", 9090));
        boost::shared_ptr<TTransport> transport(new TBufferedTransport(socket));
        boost::shared_ptr<TProtocol> protocol(new TBinaryProtocol(transport));
    
        transport->open();
    
        RecSysClient client(protocol);
    
        string send_data = "can you help me ???";
        string recevie_data;
        client.rec_data(recevie_data, send_data);
    
        cout << "Send data:" << send_data << endl;
        cout << "Receive data:" << recevie_data << endl;
    
        transport->close();
    }
    
  • 相关阅读:
    50、Flink 数据源的事件时间和水印详解
    【dubbo3.x trace组件分享】
    ResNet50的猫狗分类训练及预测
    嵌入式Linux驱动开发笔记(未完待续。。。)
    设计模式之解释器模式
    JavaIO流:NIO梳理
    表白墙网站练习【前端+后端+数据库】
    【Qt-17】Qt调用matlab生成的dll库
    【SQL刷题】Day12----SQL汇总数据专项练习
    javascript案例-----拖动模态框
  • 原文地址:https://blog.csdn.net/qianbo042311/article/details/127064113