ithewei / libhv

🔥 比libevent/libuv/asio更易用的网络库。A c/c++ network library for developing TCP/UDP/SSL/HTTP/WebSocket/MQTT client/server.

Home Page:https://github.com/ithewei/libhv/wiki

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

如何正确使用HTTP客户端连接保活

anuragvohraec opened this issue · comments

你好
我查看了您的 HTTP 客户端示例 示例
并尝试将其应用到我的案例中,但似乎不起作用。

python3/Deno 中的同一组示例虽然有效。 libhv 中的保持活动功能似乎存在一些问题。

#include "hv/requests.h"
#include "hv/hthread.h" // import hv_gettid
#include "memory.h"
#include <memory>
#include <iostream>
#include <ostream>
#include <string>

int main(){
    std::cout<<"started"<<std::endl;
    std::shared_ptr<int> resp_cnt(new int);
    *resp_cnt=0;

    std::shared_ptr<hv::HttpClient> cli(new hv::HttpClient);

    auto req = std::make_shared<HttpRequest>();
    req->method = HTTP_POST;
    req->url = "http://localhost:8080/ajax/reql/open-new-connection?cacheBuster=0.654622521604321";
    req->headers["Connection"] = "keep-alive";
    req->body = "";
    req->timeout = 10;
    cli->sendAsync(req, [resp_cnt,cli](const HttpResponsePtr& resp) {

        if(resp==NULL){
            std::cout<<"Request failed"<<std::endl;
        }else{
            std::string token = resp->body.c_str();
            std::cout<<token<<std::endl;
            *resp_cnt += 1;

            std::shared_ptr<HttpRequest> reqForQuery(new HttpRequest);
            reqForQuery->method = HTTP_POST;
            reqForQuery->url ="http://localhost:8080/ajax/reql/?conn_id="+token;
            std::cout<<reqForQuery->url<<std::endl;
            reqForQuery->headers["Connection"] = "keep-alive";
            std::string q ="\u0001\u0000\u0000\u0000\u0000\u0000\u0000\u0000[1,[39,[[15,[\"tv_shows\"]],[69,[[2,[70]],[21,[[170,[[13,[]],\"episodes\"]],100]]]]]],{\"binary_format\":\"raw\",\"time_format\":\"raw\",\"profile\":false}]";
            reqForQuery->body=q;
            reqForQuery->headers["Content-Length"] = std::to_string(q.length());
            reqForQuery->timeout = 2000;

            cli->sendAsync(reqForQuery,[q](const HttpResponsePtr& resp){
                std::cout<<q.length()<<" Final: "<<resp->body<< resp->status_code << resp->GetHeader("Content-Type")<< " Here"<<std::endl;
            });
        }
    });

     // demo wait async finished
    hv_delay(500);
}

这是有效的Python代码 :

import requests

# Send a POST request to get the token
response = requests.post('http://localhost:8080/ajax/reql/open-new-connection?cacheBuster=0.654622521604321')

# Assuming the token is in the text response, extract it
token = response.text

# Prepare the body for the next request
body = "\u0001\u0000\u0000\u0000\u0000\u0000\u0000\u0000[1,[39,[[15,[\"tv_shows\"]],[69,[[2,[70]],[21,[[170,[[13,[]],\"episodes\"]],100]]]]]],{\"binary_format\":\"raw\",\"time_format\":\"raw\",\"profile\":false}]";

# Send another POST request with the token in the URL
response = requests.post('http://localhost:8080/ajax/reql/?conn_id=' + token, data=body)

# Print the response
print(response.text)

这是有效的Deno代码:

const tokenReq = await fetch("http://localhost:8080/ajax/reql/open-new-connection?cacheBuster=0.654622521604321", {
  "headers": {
  },
  "body": null,
  "method": "POST"
});

const token = await tokenReq.text();
console.log("Token: ", token);

let z = "\u0001\u0000\u0000\u0000\u0000\u0000\u0000\u0000[1,[39,[[15,[\"tv_shows\"]],[69,[[2,[70]],[21,[[170,[[13,[]],\"episodes\"]],100]]]]]],{\"binary_format\":\"raw\",\"time_format\":\"raw\",\"profile\":false}]";
console.log(z.length);
const queryData = await fetch(`http://localhost:8080/ajax/reql/?conn_id=${token}`, {
    "headers": {
      "Content-Length":z.length,
      "Connection":"keep-alive"
    },
    "body": z,
    "method": "POST"
  });
  
  const q = await queryData.text();
  console.log(queryData.headers.get("Content-Length"),queryData.status,queryData.statusText, q.length, q);

这段代码都尝试连接到 rethinkdb 并在其中触发查询


抱歉我的中文不好或选词不当,我正在使用翻译

Please try add some print to debug.

diff --git a/http/client/AsyncHttpClient.cpp b/http/client/AsyncHttpClient.cpp
index f20d7cc..024e28d 100644
--- a/http/client/AsyncHttpClient.cpp
+++ b/http/client/AsyncHttpClient.cpp
@@ -51,6 +51,7 @@ int AsyncHttpClient::doTask(const HttpClientTaskPtr& task) {
     if (iter != conn_pools.end()) {
         // hlogd("get from conn_pools");
         iter->second.get(connfd);
+        printf("get from conn_pools %s=>%d\n", strAddr, connfd);
     }

     if (connfd < 0) {
@@ -118,6 +119,7 @@ int AsyncHttpClient::doTask(const HttpClientTaskPtr& task) {
                 // NOTE: add into conn_pools to reuse
                 // hlogd("add into conn_pools");
                 conn_pools[channel->peeraddr()].add(channel->fd());
+                printf("add into conn_pools %s=>%d\n", channel->peeraddr().c_str(), channel->fd());
             } else {
                 channel->close();
             }
@@ -130,6 +132,7 @@ int AsyncHttpClient::doTask(const HttpClientTaskPtr& task) {
         auto iter = conn_pools.find(channel->peeraddr());
         if (iter != conn_pools.end()) {
             iter->second.remove(channel->fd());
+            printf("remove from conn_pools %s=>%d\n", channel->peeraddr().c_str(), channel->fd());
         }

The fd is coming same for these debug points, which I think means its using the same connection.
However the problem still exist the body is coming as empty string. I will investigate from my end on it..
Thank you.