1. 问题
首先,大背景是C++与js之间的交互(addon),可以是数据,函数等等。其中,js向C++传递一个json数据,这个数据是C++http网络请求,然后C++开辟一个子线程,建立一个tcp连接,然后进行http请求,最后将http请求的响应信息传递给js层,或者回调nodejs处理响应信息也可以。
其中,C++建立tcp连接和http请求是用一个类实现的,过程都是异步的,其中有一个回调函数on_read()会得到服务器的响应信息,并进行加工处理。
C++拿到js的json请求之后,便开始进行网络工作。
问题就是:
a. 不知道响应信息何时返回,无法像同步那样等待响应。
b. 在js的主线程之外不能使用v8的api,也就是说无法在on_read()回调函数中直接向js返回响应信息
2. 代码
class TCP_CLIENT : public IConnectionHandler
{
bool isdone;
public:
TCP_CLIENT(const char* host, int port, const char* data, Isolate *isolate, const FunctionCallbackInfo<Value> args)
{
this->host_ = host;
this->port_ = port;
this->request_data_ = data;
isolate_ = isolate;
}
~TCP_CLIENT()
{
std::cout << "~tcp_client" << std::endl;
}
/*callback handler implement回调接口实现*/
//建立连接的回调
void on_established(IBaseConnection* conn) override_final
{
std::cout << "Connect Successful" << std::endl;
this->send_request(conn);
}
。。。。。。。。。
//服务器响应得到数据的回调
int on_read(int err, int bytes_transfered, IBaseConnection* conn, SharedBufferPtr buffer) override_final
{
if (err == 0 && bytes_transfered)
{
std::cout << "In read, thread id is ----" << GetCurrentThreadId() << std::endl;
buffer->erase(bytes_transfered);
if (conn->is_established())
{
conn->stop();
}
}
return 0;
}
//发送数据的回调
void on_write(int err, int bytes_transferred, IBaseConnection* conn, SharedBufferPtr buffer) override_final
{
if (err == 0 && bytes_transferred > 0)
{
std::cout << "Send Request Successful------>" << buffer->length() << std::endl;
buffer->erase(bytes_transferred);
}
else {}
}
private:
const char* host_;
int port_;
const char* request_data_;
http::ParserPtr response_parser_;
Isolate *isolate_;
};
const char* ToCString(const v8::String::Utf8Value& value)
{
return *value ? *value : "<string conversion failed>";
}
void entry(const FunctionCallbackInfo<Value>& args)
{
std::cout << "In entry, process id is ----" << GetCurrentProcessId() << std::endl;
std::cout << "In entry, thread id is ----" << GetCurrentThreadId() << std::endl;
//启动一个线程执行tcp连接
global_http_transfer_context_pool.run();
Isolate* isolate = args.GetIsolate();
if (args.Length() != 2)
{
isolate->ThrowException(Exception::TypeError(v8::String::NewFromUtf8(isolate, "参数数量必须为二")));
return;
}
if (!args[0]->IsString() || !args[1]->IsNumber())
{
isolate->ThrowException(Exception::TypeError(
v8::String::NewFromUtf8(isolate, "参数类型错误")
));
}
v8::String::Utf8Value str_temp(args[0]);
const char* data = ToCString(str_temp);
TCP_CLIENT* tcp_client;
if (args[1]->NumberValue() == 1)
{
tcp_client = new TCP_CLIENT(cms_host, cms_port, data, isolate, args);
tcp_client->perform(1);
}
else
{
tcp_client = new TCP_CLIENT(liteapp_host, liteapp_port, data, isolate, args);
tcp_client->perform(0);
}
}
void Init(Local<Object> exports)
{
NODE_SET_METHOD(exports, "http_request", entry);
}
NODE_MODULE(NODE_GYP_MODULE_NAME, Init)
尝试的方法:
a. 在主线程中设置while循环等待,子线程在on_read()向js返回数据之后,设置标志表示结束,这样能够正确结束,但是C++的异步请求就变成了一个同步,没有意义。
b. 在网上看到的libuv方法,但是仍然会出现libuv的工作函数无法得到C++异步响应消息的问题,主要就是异步消息与C++向node返回,线程之间如何处理的问题。
跪求各位大神!