2013-03-15 1 views
0

저는 내부 브라우저가있는 소켓을 사용할 수있는 NPAPI 플러그인을 개발 중이며 이에 대한 부스트 소켓을 사용하고 있습니다.io_service를 중단 하시겠습니까?

지금 내 사용법은 그냥 소켓을 열고 meesage를 작성하고 읽은 다음 닫기 메시지를 보내고 닫은 다음 반복한다 (나는 바보로 매 시간마다 닫고 열지 만 변경할 수는 없다).

문제점은 두 번째 오픈 후에 소켓에서 읽을 수 없기 때문에 las가 변경 될 때까지 쓰기를 열 수 있었지만 정보를 얻지 못했고 이제는 io_service 스레드가 죽어 가고있는 것처럼 보입니다.

자습서와 정보를 많이 읽었지만 아무도 여러 클라이언트 소켓을 여는 것처럼 보이지 않습니다. 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); 
}; 

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; 
}; 

: 여기

소켓 정보와 핸들러를 저장하는 클래스입니다 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(); 
} 

나는 개선 될 수 있다고 확신하지만, 두 번째 열면 왜 작동하지 않는지 오류를 찾을 수 없습니다. 큐션의

추적 : 스레드가 여전히 작동하고 io_service 그래서 난 일이있을 수 있는지 확실하지 않다 중지되지 않고

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()를 보인다는 중지됩니다.

답변

0

좋아, 나는 그것이 예외를 던져서 모든 것을 멈추게한다고 생각했던 것보다 훨씬 간단하다는 것을 알았지 만, 브라우저에서 사용하고있는 것처럼 나는 그것을 알아 차리지 못했다.

그래도 문제를 해결할 수 없으므로 확인하려면 Boost bind object freed on read handler을 사용하십시오.

관련 문제