2013-03-15 114 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以分享一些見解。

相關問題