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 <QTcpSocket>
#include <QByteArray>
#include <QImage>

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 <QDebug>

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 <iostream>
#include <string>

#include <transport/TSocket.h>
#include <transport/TBufferTransports.h>
#include <protocol/TBinaryProtocol.h>

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();
}

猜你喜欢

转载自blog.csdn.net/qianbo042311/article/details/127064113
今日推荐