如何在 PNaCl 中等待 WebSocket 响应
Posted
技术标签:
【中文标题】如何在 PNaCl 中等待 WebSocket 响应【英文标题】:How to wait for WebSocket response in PNaCl 【发布时间】:2015-05-31 03:07:00 【问题描述】:我正在通过 PPAPI 中的pp::WebSocketAPI
在 PNaCl 插件上实现“在继续之前等待 WebSocket 响应”机制。下面是一个简化的版本,将回复的数据存储到一个全局的std::string
中,而函数myecho()
通过WebSocket发送一个字符串并轮询直到全局字符串发生变化。驱动网页与 NaCl SDK 中的 WebSocket 示例相同。
#include <string>
#include "ppapi/cpp/instance.h"
#include "ppapi/cpp/module.h"
#include "ppapi/cpp/var.h"
#include "ppapi/cpp/var_array_buffer.h"
#include "ppapi/utility/websocket/websocket_api.h"
class MyWebSocketReceiveListener
public:
virtual void onWebSocketDataReceived(const std::string& data) = 0;
;
class MyWebSocketAPI : protected pp::WebSocketAPI
public:
MyWebSocketAPI(pp::Instance* ppinstance, MyWebSocketReceiveListener* recvlistener)
: pp::WebSocketAPI(ppinstance), m_onReceiveListener(recvlistener), m_ppinstance(ppinstance)
virtual ~MyWebSocketAPI()
bool isConnected() return pp::WebSocketAPI::GetReadyState() == PP_WEBSOCKETREADYSTATE_OPEN;
void open(const std::string& url) pp::WebSocketAPI::Connect(url, NULL, 0);
void close() pp::WebSocketAPI::Close(PP_WEBSOCKETSTATUSCODE_NORMAL_CLOSURE, "bye");
void sendData(const std::string& data) pp::WebSocketAPI::Send(data);
protected:
virtual void WebSocketDidOpen() m_ppinstance->PostMessage("Connected");
virtual void WebSocketDidClose(bool wasClean, uint16_t code, const pp::Var& reason)
virtual void HandleWebSocketMessage(const pp::Var& message)
if (message.is_array_buffer())
pp::VarArrayBuffer vararybuf(message);
char *data = static_cast<char*>(vararybuf.Map());
std::string datastr(data, data + vararybuf.ByteLength());
vararybuf.Unmap();
m_onReceiveListener->onWebSocketDataReceived(datastr);
else // is string
m_onReceiveListener->onWebSocketDataReceived(message.AsString());
virtual void HandleWebSocketError()
private:
MyWebSocketAPI(const MyWebSocketAPI&);
MyWebSocketAPI& operator=(const MyWebSocketAPI&);
MyWebSocketReceiveListener* const m_onReceiveListener;
pp::Instance * const m_ppinstance;
;
static std::string g_returnval;
class MyPPPluginInstance : public pp::Instance, public MyWebSocketReceiveListener
public:
explicit MyPPPluginInstance(PP_Instance instance)
: pp::Instance(instance), rpcwebsocket_(this, this)
virtual ~MyPPPluginInstance()
virtual void HandleMessage(const pp::Var& var_message);
virtual void onWebSocketDataReceived(const std::string& data)
g_returnval = data;
private:
bool IsConnected() return rpcwebsocket_.isConnected();
void Open(const std::string& url)
rpcwebsocket_.open(url);
PostMessage(pp::Var("connecting..."));
void Close()
if (!IsConnected())
return;
rpcwebsocket_.close();
MyWebSocketAPI rpcwebsocket_;
;
std::string myecho(pp::Instance* inst, MyWebSocketAPI& ws, const std::string& in)
ws.sendData(in);
while (g_returnval.empty())
usleep(1000 * 1000); // 1 sec
inst->PostMessage("Waiting for response...");
return g_returnval;
void MyPPPluginInstance::HandleMessage(const pp::Var& var_message)
if (!var_message.is_string())
return;
std::string message = var_message.AsString();
// This message must contain a command character followed by ';' and
// arguments like "X;arguments".
if (message.length() < 2 || message[1] != ';')
return;
switch (message[0])
case 'o':
// The command 'o' requests to open the specified URL.
// URL is passed as an argument like "o;URL".
Open(message.substr(2));
break;
case 'c':
// The command 'c' requests to close without any argument like "c;"
Close();
break;
case 'b':
case 't':
PostMessage(std::string("Calling remote echo for ") + message.substr(2));
std::string ret(myecho(this, rpcwebsocket_, message.substr(2)));
PostMessage(ret);
break;
// Creates MyPPPluginInstance objects when invoked.
class MyPPPluginModule : public pp::Module
public:
MyPPPluginModule() : pp::Module()
virtual ~MyPPPluginModule()
virtual pp::Instance* CreateInstance(PP_Instance instance)
return new MyPPPluginInstance(instance);
;
// Implement the required pp::CreateModule function that creates our specific
// kind of Module.
namespace pp
Module* CreateModule() return new MyPPPluginModule();
// namespace pp
但是,这种方法不起作用。在连接到 echo 测试服务器ws://echo.websocket.org
并发送“hello”后,我就得到了
connecting...
Connected
Calling remote echo for hello
Waiting for response...
Waiting for response...
Waiting for response...
Waiting for response...
Waiting for response...
(从不回复)
我用另一个手工制作的WebSocket服务器测试,消息成功发送到服务器。除了我附加的 sn-p 中的usleep()
轮询之外,我还尝试使用pthread_cond_wait()
和pthread_cond_signal()
来等待并通知收到的消息。
如何正确“等待pp::WebSocketAPI
接收数据”?
【问题讨论】:
【参考方案1】:函数myecho()
阻止MyPPPluginInstance::HandleMessage()
并反过来阻止从WebSocket 接收。
我添加了一个pp::SimpleThread
作为MyPPPluginInstance
类的新数据成员,并通过pp::SimpleThread::message_loop().PostWork()
将myecho()
分派到另一个线程。它运行顺利。
【讨论】:
以上是关于如何在 PNaCl 中等待 WebSocket 响应的主要内容,如果未能解决你的问题,请参考以下文章
如何在 Cypress.io 中等待 WebSocket STOMP 消息