提升库多线程插座的陌生感

时间:2014-05-17 05:45:33

标签: multithreading boost

我已经被困了一整晚,但无法弄清楚问题。

我正在编写一个接受聊天室应用程序连接的服务器。这个想法是服务器将连接的套接字提供给chat_manager,chat_manager将它们放入等待列表并启动一个线程以不断检查是否有人仍在等待列表中。如果有人在候补名单中,则chat_manager会尝试从客户端读取以确定客户想要加入的房间。

main.cpp看起来像这样:

boost::asio::io_service io_service;
chat_server server(io_service, 8091);
io_service.run();

聊天服务器代码:

chat_server::chat_server(boost::asio::io_service& io_service, int port) : io_service_(io_service), 
    acceptor_(io_service, tcp::endpoint(tcp::v4(), port)) {
    start_accept();
}
void chat_server::start_accept() {
    chat_session_ptr new_session(new chat_session(io_service_));

    acceptor_.async_accept(new_session->socket(), boost::bind(&chat_server::handle_accept, this, new_session, 
        boost::asio::placeholders::error));
}
void chat_server::handle_accept(chat_session_ptr s, const boost::system::error_code& error) {
    if (!error) {       // successfully connected
        chat_manager::Instance().chat_session_join(s);
    }

    start_accept();
}

chat_manager只是

chat_manager() { // constructor
    waitlist_.resize(0);
    manager_thread_ = boost::thread(&chat_manager::run, this);
}

int chat_session_join(chat_session_ptr chat_session) {
    mutex_.lock();
    waitlist_.push_back(chat_session);
    mutex_.unlock();
    return 1;
}

void run() {
    while (1) {
        mutex_.lock();
        for (auto &s : waitlist_) {
            std::string roomname;
            if (s->wait_for_join(roomname)) {
                ...
            }

            break;
        }
        mutex_.unlock();

        boost::this_thread::sleep( boost::posix_time::milliseconds(10) );
    }
}

和session.cpp:

jsoncons::json chat_session::receive_request(boost::system::error_code& error) {

    buffer_.consume(buffer_.size());

    size_t bytes_transferred;
    boost::system::error_code ec = boost::asio::error::would_block;

    boost::asio::async_read_until(socket_, buffer_, "\n", 
            boost::bind(&chat_session::handle_read, shared_from_this(), _1, _2, &ec, &bytes_transferred ));

    deadline_.expires_from_now(boost::posix_time::seconds(2));
    deadline_.async_wait(boost::bind(&chat_session::check_deadline, shared_from_this()));

    do pio_service_->run_one(); while (ec == boost::asio::error::would_block);

    std::cout << "got it" << std::endl;

    if ( ec || !socket_.is_open() ) {
        std::cout << ec.message() << std::endl;
        return jsoncons::json();
    }

    std::istream is(&buffer_);

    return jsoncons::json::parse(is);
}

int chat_session::wait_for_join(std::string &roomname) {
    boost::system::error_code error;
    jsoncons::json request = receive_request(error);
    ...
}

void chat_session::handle_read(const boost::system::error_code& error, size_t bytes_transferred, 
    boost::system::error_code* out_error, size_t* out_bytes_transferred) {

    deadline_.expires_at(boost::posix_time::pos_infin);

    *out_error = error;
    *out_bytes_transferred = bytes_transferred;

    if (!error) {
    } else {
        std::cout << "handle_read error:" << error.message() << std::endl;
    }
}

会发生什么, 1.当客户端连接并且不发送任何内容时,服务器在2秒后关闭连接。哪个是对的。但 2.如果客户端在连接到期之前发送了一个字符串,那么服务器就会进入handle_read,但永远不会超过pio_service-&gt; run_one(); 3.如果客户端发送另一个字符串,则wait_for_join将完成,run()过程开始循环。

对我来说,似乎在这里使用io_services很好,因为check_deadline和handle_read工作正常,但如果真的有效,它会修改ec!= would_block,并且应该返回do-while循环。这里发生了什么事?我真的很困惑。

0 个答案:

没有答案