1

私は、ブラウザ内のローカルでソケットを使用できるようにする NPAPI プラグインに取り組んでおり、これには Boost ソケットを使用しています。

私の現在の使用法は、ソケットを開いてメッセージを書き、読み取り、終了メッセージを送信し、閉じてから繰り返すだけです(毎回閉じて開くのはばかげていることは知っていますが、それを変更することはできません)。

問題は、2回目のオープン後、ソケットから読み取ることができず、最後の変更まで書き込みを開くことができましたが、情報を取得できず、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();
}

何かが改善される可能性があると確信しています(教えてください)が、2回目に開いた後に機能しない理由を見つけることができません。

処刑の痕跡:

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 は停止していないため、何が起こっているのかわかりません。

4

1 に答える 1

0

OK、エラーが発生したのは、例外をスローしてすべてを停止すると思っていたよりもはるかに簡単でしたが、ブラウザー内で使用していたため、それに気づきませんでした。

それでも問題を解決できないので、次を確認してください:読み取りハンドラーで解放されたバインド オブジェクトをブーストして、いくつかの洞察を共有してください。

于 2013-03-15T18:21:12.200 に答える