在使用C ++ 11标准替换最初在 boost 中的所有内容之后,我使用ASIO根据此server示例构建了一个演示应用程序。服务器可以显示只有在客户端连接后才调用类成员tcp_session::start()
,这表明服务器接受来自客户端的连接。
然而,当客户端发送大量数据时,我没有看到handle_read
收到任何内容。最后,我发现stopped()
始终为真,这意味着socket_.isOpen
为假。
所以我想知道我是否需要做任何事情来将socket_
设置为isOpen
start()
,或者socket_
应该自动“打开”(意味着已连接) )?或者我的理解或假设是错误的?
我正在使用VS2015并在localhost上进行测试。
我将默认的30秒超时更改为1秒。因此,当服务器连接时,在客户端发送数据之前,服务器是否可能超时并关闭套接字?
我在handle_read中得到了一些std :: cout并停止了。我现在将超时时间设为6秒,并发现:
在客户端连接后立即调用start
,然后没有任何内容表明调用handle_read
,但在6秒后调用stop()
,然后调用handle_read
我猜测handlers
配置错误。
然后我发现,如果我将async_read
更改为async_read_until
最初由我发表评论,则handle_read
将继续,因为socket_.isopen
为真。
因此,结论是,async_read无法调用handle_read,但是async_read_until可以,这变为another question。在超时停止会话之前socket_.is_open()
为真。
以下是一些相关代码:
class tcp_session : public subscriber, public std::enable_shared_from_this<tcp_session> {
public:
void start() {
std::cout<<"started"<<std::endl;
channel_.join(shared_from_this());
start_read();
input_deadline_.async_wait(
std::bind(&tcp_session::check_deadline, shared_from_this(), &input_deadline_)
);
await_output();
output_deadline_.async_wait(
std::bind(&tcp_session::check_deadline, shared_from_this(), &output_deadline_)
);
}
private:
bool stopped() const {
return !socket_.is_open();// weird that it is still not open
}
void start_read() {
// Set a deadline for the read operation.
input_deadline_.expires_from_now(timeout_); //was std::chrono::seconds(30) in example
char a = 0x7F;
// Start an asynchronous operation to read a 0x7F-delimited message or read all
//asio::async_read_until(socket_, input_buffer_, a, std::bind(&TCP_Session::handle_read, shared_from_this(), std::placeholders::_1));
asio::async_read(socket_, input_buffer_,
std::bind(&TCP_Session::handle_read, shared_from_this(), std::placeholders::_1));
}
void handle_read(const asio::error_code& ec) {
if (stopped()) // it thinks it stopped and returned without processing
return;
答案 0 :(得分:2)
打开套接字不会暗示其连接状态,并且连接状态不会影响套接字的打开或关闭状态。两者之间的唯一保证是封闭的套接字没有连接。
客户流程示例:
using boost::asio::ip::tcp;
tcp::socket socket(io_service); // closed state -- no connection
socket.open(...); // opened state -- no connection
socket.bind(...);
socket.connect(...); // opened state -- connection
... connection established ...
... remote peer terminates/closes connection ... // opened state -- no connection
assert(socket.is_open());
socket.close(); // closed state -- no connection
assert(!socket.is_open());
示例服务器流程:
using boost::asio::ip::tcp;
tcp::acceptor acceptor_(io_service); // acceptor closed state
acceptor.open(...); // acceptor opened state
acceptor.bind(...);
acceptor.listen(); // acceptor listening state
tcp::socket socket(io_service); // closed state -- no connection
acceptor.accept(socket); // opened state -- connection
... connection established ...
... remote peer terminates/closes connection ... // opened state -- no connection
assert(socket.is_open());
socket.close(); // closed state -- no connection
assert(!socket.is_open());
assert(acceptor.is_open();
acceptor.close(); // acceptor closed state
assert(!acceptor.is_open());
在您的服务器中,socket_.is_open()
正在返回false
,然后在socket_.close()
内的套接字上显式调用了tcp_session::stop()
。要更深入地了解调用它的原因,请考虑:
BOOST_ASIO_ENABLE_HANDLER_TRACKING
以启用handler tracking。定义它时,Boost.Asio将有关异步操作和处理程序关系的信息写入标准错误流。tcp_session::stop()
。