以下是为了建立一个图片服务器而作,tcp作为服务端, 接收图片后可以用来做AI识别,因此而做,图片在内存里面,不经过AI存储到磁盘,经过推理后存储到磁盘,传输时需要缩小成AI服务器需要的样品大小。
本次介绍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 本身比直接继承要好
#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方式来做图片服务
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)
#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.'
#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();
}