2013-03-15 115 views
0

我正在使用NPAPI插件,该插件允许在本地内部浏览器中使用套接字,并且我正在使用这种套接字套接字。Boost io_service停止?

我现在的用法是打开套接字写一个meesage,阅读,发送关闭消息,关闭然后重复(我知道这是愚蠢的关闭和打开每次,但我不能改变)。

问题是,第二次打开后,我无法从套接字读取,直到拉斯修改我能够打开写但从来没有得到的信息回来,现在看来io_service线程刚刚死亡。

我已经阅读了很多教程和信息,但似乎没有人打开几个客户端套接字,因为我正在尝试。

下面是存储插槽信息和处理程序类:

SocketInfo.hpp

class SocketInfo 
{ 
public: 
    void start_read(); 
    void handle_read(const boost::system::error_code& error, std::size_t bytes_transferred); 

    FB::JSObjectPtr m_callback; 
    boost::shared_ptr<boost::asio::ip::tcp::socket> m_socket; 
    char data_[SOCKETS_API_BUFFER]; 
    int key; 
    boost::shared_ptr<SocketsAPI> parent; 
}; 

SocketInfo.cpp

void SocketInfo::start_read() 
{ 
    parent->log("start_read" + boost::lexical_cast<std::string>(key)); 
    m_socket->async_receive(boost::asio::buffer(data_, SOCKETS_API_BUFFER), 
     boost::bind(&SocketInfo::handle_read, this, 
      boost::asio::placeholders::error, 
      boost::asio::placeholders::bytes_transferred)); 
} 

void SocketInfo::handle_read(const boost::system::error_code& error, 
     std::size_t bytes_transferred) 
{ 
    if (!error) { 
     parent->log("handle_read" + boost::lexical_cast<std::string>(key)); 
     std::string str(&data_[0], &data_[0] + bytes_transferred); 
     m_callback->InvokeAsync("processData", FB::variant_list_of(str)); 
     start_read(); 
    } else { 
     parent->log("error closing " + boost::lexical_cast<std::string>(key)); 
     m_callback->InvokeAsync("processCancel", FB::variant_list_of()); 
     parent->do_close(*this); 
    } 
} 

SocketApi.h

class SocketsAPI : public FB::JSAPIAuto 
{ 
public: 
    SocketsAPI(const SocketsPtr& plugin, const FB::BrowserHostPtr& host) : 
     m_plugin(plugin), m_host(host)   
    { 
... FireBreath code here ... 

     //Start thread with work 
     workPtr.reset(new boost::asio::io_service::work(io_service)); 
     ioThreadPtr.reset(new boost::thread(boost::bind(&boost::asio::io_service::run, &io_service))); 

    } 

    virtual ~SocketsAPI() { 
     workPtr.reset(); 
     if (ioThreadPtr) { 
      ioThreadPtr->join(); 
     } 
    }; 

    //Socket Methods 
    int open(const int port, const FB::JSObjectPtr &callback); 
    void close(const int key); 
    void write(const int key, const std::string data); 

    // Method echo 
    FB::variant echo(const FB::variant& msg); 
    void do_close(const SocketInfo socket); 
    void log(const std::string &str); 

private: 

    mapType sockets; 

    boost::asio::io_service io_service; 
    boost::shared_ptr<boost::thread> ioThreadPtr; 
    boost::shared_ptr<boost::asio::io_service::work> workPtr; 

    void checkOpen(const SocketInfo socket); 
    void do_write(const std::string data, const SocketInfo socket); 
    void start_read(const SocketInfo socket); 
    void empty_handle(const boost::system::error_code& error); 
    int getFirstEmpty(); 
    SocketInfo getSocket(const int key); 
}; 

SocketAPI.cpp

int SocketsAPI::open(const int port, const FB::JSObjectPtr &callback) 
{ 
    log("open"); 
    boost::shared_ptr<SocketInfo> socket; 
    socket.reset(new SocketInfo); 
    socket->m_socket.reset(new boost::asio::ip::tcp::socket(io_service)); 
    socket->m_callback = callback; 
    ip::tcp::endpoint tcp(ip::address::from_string("127.0.0.1"), port); 

    boost::system::error_code errorcode; 
    socket->m_socket->connect(tcp, errorcode); 
    if (errorcode) { 
     trace("Connection failed: ", errorcode.message()); 
     return -1; 
    } 
    log("conenected"); 
    boost::asio::socket_base::keep_alive o(true); 
    socket->m_socket->set_option(o); 
    int key = getFirstEmpty(); 
    socket->key = key; 
    socket->parent.reset(this); 
    sockets.insert (std::pair<int,boost::shared_ptr<SocketInfo>>(key,socket)); 
    socket->start_read(); 
    if (io_service.stopped()) { 
     log("Resetting service"); 
     io_service.reset(); 
    } 
    return key; 
} 

void SocketsAPI::close(const int key) 
{ 
    SocketInfo socket = getSocket(key); 
    checkOpen(socket); 
    log("close"); 
    io_service.post(boost::bind(&SocketsAPI::do_close, this, socket)); 
} 

void SocketsAPI::write(const int key, const std::string data) 
{ 
    log("write socket " + boost::lexical_cast<std::string>(key)); 
    SocketInfo socket = getSocket(key); 
    checkOpen(socket); 
    io_service.post(boost::bind(&SocketsAPI::do_write, this, Base64::decode(data), socket)); 
} 

void SocketsAPI::checkOpen(const SocketInfo socket) 
{ 
    log("checkOpen"); 
    if (!socket.m_socket || !socket.m_socket->is_open()) { 
     trace("Socket not opened", ""); 
     throw FB::script_error("There is no open socket"); 
    } 
} 


void SocketsAPI::do_write(const std::string data, 
          const SocketInfo socket) 
{ 
    log("do_write " + boost::lexical_cast<std::string>(socket.key)); 
    if (!socket.m_socket->is_open()) { 
     return; 
    } 
    boost::asio::async_write(*(socket.m_socket.get()), 
     boost::asio::buffer(&data[0], data.size()), 
     boost::bind(&SocketsAPI::empty_handle, this, boost::asio::placeholders::error) 
    ); 
} 

void SocketsAPI::empty_handle(const boost::system::error_code& error) 
{ 
    if (error) { 
     trace("Error writing: ", error.message()); 
    } 
} 

void SocketsAPI::do_close(const SocketInfo socket) 
{ 
    log("do_close"); 
    if (!socket.m_socket || !socket.m_socket->is_open()) { 
     return; 
    } 
    boost::system::error_code errorcode; 
    socket.m_socket->shutdown(boost::asio::ip::tcp::socket::shutdown_both, errorcode); 
    if (errorcode) { 
     trace("Closing failed: ", errorcode.message()); 
    } 
    socket.m_socket->close(errorcode); 
    if (errorcode) { 
     trace("Closing2 failed: ", errorcode.message()); 
    } 
    mapType::iterator iter = sockets.find(socket.key); 
    if (iter != sockets.end()) { 
     sockets.erase (iter); 
    } 
    log("do_close end"); 
} 

int SocketsAPI::getFirstEmpty() { 
    int i = 0; 
    mapType::iterator iter; 
    while(true) { 
     iter = sockets.find(i); 
     if (iter == sockets.end()) { 
      return i; 
     } 
     i++; 
    } 
} 

SocketInfo SocketsAPI::getSocket(const int key) { 
    mapType::iterator iter = sockets.find(key); 
    if (iter == sockets.end()) { 
     trace("Socket not found", ""); 
     throw FB::script_error("Socket not found"); 
    } 
    log("socket " + boost::lexical_cast<std::string>(key) +" found"); 
    return *iter->second.get(); 
} 

我相信有些东西可以改进(请告诉我),但我无法找到错误,为什么在第二次打开后它不起作用。

痕迹excution的:

open 
conenected 
start_read0 
write socket 0 
socket 0 found 
checkOpen 
do_write 0 
handle_read0 
start_read0 
write socket 0 
socket 0 found 
checkOpen 
do_write 0 
socket 0 found 
checkOpen 
close 
do_close 
do_close end 
open 
conenected 
start_read0 
write socket 0 
socket 0 found 
checkOpen 

似乎io_service.run()只是停止,但线程仍在工作,io_service对象没有停止,所以我不知道什么可能会发生。

回答

0

好吧我发现这个错误比我想它只是抛出一个异常,并停止一切,但因为我在浏览器中使用它,我没有注意到这一点。

我仍然无法解决问题,因此您可以查看:Boost bind object freed on read handler以分享一些见解。

相关问题