求解惑:boost asio io_service.run在不同位置调用产生的不同结果
A:在main中调用
B:在自己的iohandler里调用
A在收到一个客户端消息,向服务器发送回应,客户端断开之后的结果是:
main thread run iohandle!
session::session 386588
session::session 3872d8
03/25/13 14:34:56 session::handle_read_header read 2 bytes
03/25/13 14:34:56 session::handle_read_body read f bytes
xxxxxx23421313
03/25/13 14:34:56 write success with byte_transffered = 22
03/25/13 14:34:56 session::handle_read_error line : 8cerr_code : 2746 err_msg:
远程主机强迫关闭了一个现有的连接。
session::~session 386588
B在收到一个客户端消息,向服务器发送回应,客户端断开之后的结果是:
main thread run iohandle!
session::session 386588
session::session 3872d8
03/25/13 14:50:23 session::handle_read_header read 2 bytes
03/25/13 14:50:23 session::handle_read_body read f bytes
xxxxxx23421313
03/25/13 14:50:23 write success with byte_transffered = 22
03/25/13 14:50:24 session::handle_read_error line : 8cerr_code : 2746 err_msg:
远程主机强迫关闭了一个现有的连接。
session386588没有被释放
(不关闭B再运行一次客户端,一下的信息包括上面那一段)
main thread run iohandle!
session::session 386588
session::session 3872d8
03/25/13 14:50:23 session::handle_read_header read 2 bytes
03/25/13 14:50:23 session::handle_read_body read f bytes
xxxxxx23421313
03/25/13 14:50:23 write success with byte_transffered = 22
03/25/13 14:50:24 session::handle_read_error line : 8cerr_code : 2746 err_msg:
远程主机强迫关闭了一个现有的连接。
session::session 38c028
03/25/13 14:52:38 session::handle_read_header read 2 bytes
03/25/13 14:52:38 session::handle_read_body read f bytes
xxxxxx23421313
03/25/13 14:52:38 write success with byte_transffered = 22
03/25/13 14:52:38 session::handle_read_error line : 8cerr_code : 2746 err_msg:
远程主机强迫关闭了一个现有的连接。
session::~session 3872d8
这次的session被释放了!
直到最后io_service.close()的时候session 386588才会被释放。
求大神解惑这是为什么??
-----------------------以下是测试代码--------------------------------------------------------
session.h
session.cpp
iohandler.h
iohanlder.cpp
int _tmain(int argc, _TCHAR* argv[])
{
boost::asio::io_service _io_service;
tcp::endpoint endpoint(tcp::v4(), 6543);
iohandler srv(_io_service,endpoint);
cout << "main thread run iohandle!" << endl;
srv.run();
_io_service.run(); //在Main里面调用
cout << "main thread returned!" << endl;
return 0;
}
B:在自己的iohandler里调用
void iohandler::run()
{
if (_is_run)
return;
_is_run = true;
session_ptr new_session(new session(_io_service,this));
_acceptor.async_accept(new_session->Socket(),boost::bind(&iohandler::handle_accept, this, new_session,placeholders::error));
_io_service.run();//不再在MAIN里面调用,在自己的iohandler里调用。
}
A在收到一个客户端消息,向服务器发送回应,客户端断开之后的结果是:
main thread run iohandle!
session::session 386588
session::session 3872d8
03/25/13 14:34:56 session::handle_read_header read 2 bytes
03/25/13 14:34:56 session::handle_read_body read f bytes
xxxxxx23421313
03/25/13 14:34:56 write success with byte_transffered = 22
03/25/13 14:34:56 session::handle_read_error line : 8cerr_code : 2746 err_msg:
远程主机强迫关闭了一个现有的连接。
session::~session 386588
B在收到一个客户端消息,向服务器发送回应,客户端断开之后的结果是:
main thread run iohandle!
session::session 386588
session::session 3872d8
03/25/13 14:50:23 session::handle_read_header read 2 bytes
03/25/13 14:50:23 session::handle_read_body read f bytes
xxxxxx23421313
03/25/13 14:50:23 write success with byte_transffered = 22
03/25/13 14:50:24 session::handle_read_error line : 8cerr_code : 2746 err_msg:
远程主机强迫关闭了一个现有的连接。
session386588没有被释放
(不关闭B再运行一次客户端,一下的信息包括上面那一段)
main thread run iohandle!
session::session 386588
session::session 3872d8
03/25/13 14:50:23 session::handle_read_header read 2 bytes
03/25/13 14:50:23 session::handle_read_body read f bytes
xxxxxx23421313
03/25/13 14:50:23 write success with byte_transffered = 22
03/25/13 14:50:24 session::handle_read_error line : 8cerr_code : 2746 err_msg:
远程主机强迫关闭了一个现有的连接。
session::session 38c028
03/25/13 14:52:38 session::handle_read_header read 2 bytes
03/25/13 14:52:38 session::handle_read_body read f bytes
xxxxxx23421313
03/25/13 14:52:38 write success with byte_transffered = 22
03/25/13 14:52:38 session::handle_read_error line : 8cerr_code : 2746 err_msg:
远程主机强迫关闭了一个现有的连接。
session::~session 3872d8
这次的session被释放了!
直到最后io_service.close()的时候session 386588才会被释放。
求大神解惑这是为什么??
-----------------------以下是测试代码--------------------------------------------------------
session.h
using namespace boost::asio;
class session : public boost::enable_shared_from_this<session>
{
public:
session(io_service& svic,iohandler* io);
~session(void);
public:
bool Send(unsigned char* pMsg,unsigned short wSize);
void OnRecv( unsigned char *pMsg, unsigned short wSize );
void Start();
void handle_read_header(const boost::system::error_code& error,std::size_t bytes_transferred);
void handle_read_body(const boost::system::error_code& error,std::size_t bytes_transferred);
void handle_write_msg(const boost::system::error_code& error,std::size_t bytes_transferred);
void CloseSession();
ip::tcp::socket& Socket() { return _socket; }
private:
void handle_read_error(const boost::system::error_code& error);
private:
net_packet _packet_for_recv;
net_packet_queue _packets_for_send;
ip::tcp::socket _socket;
iohandler* _io;
boost::recursive_mutex* _mutex_for_write_buffer;
SESSION_FLAGS bool _is_started;
SESSION_FLAGS bool _is_closed;
SESSION_FLAGS bool _is_in_writing;
SESSION_FLAGS bool _is_notify_disconnect;
};
session.cpp
session::session(io_service& svic,iohandler* io)
:_socket(svic),
_is_in_writing(false),
_mutex_for_write_buffer(new boost::recursive_mutex),
_is_closed(false),
_is_started(false),
_io(io),
_is_notify_disconnect(false)
{
std::cout << __FUNCTION__ << " " << std::hex<< (int)this << std::endl;
}
session::~session(void)
{
std::cout << __FUNCTION__ << " " << std::hex <<(int)this << std::endl;
if (_mutex_for_write_buffer)
{
delete _mutex_for_write_buffer;
_mutex_for_write_buffer = NULL;
}
}
void session::Start()
{
if (_is_started){
std::cerr << etr::timestamp << "session already start!" << std::endl;
return;
}
_is_started = true;
boost::asio::async_read(_socket,
boost::asio::buffer(_packet_for_recv.data(),2),
boost::bind(&session::handle_read_header, shared_from_this(), placeholders::error,placeholders::bytes_transferred));
}
void session::handle_read_header(const boost::system::error_code& error,std::size_t bytes_transferred)
{
if (!error)
{
std::cout << "\t" << etr::timestamp << __FUNCTION__ <<" read " << bytes_transferred << " bytes" << std::endl;
unsigned short len = _packet_for_recv.decode_header();
_packet_for_recv.body_length(len);
boost::asio::async_read(_socket,
boost::asio::buffer(_packet_for_recv.body(),_packet_for_recv.body_length()),
boost::bind(&session::handle_read_body, shared_from_this(),placeholders::error,placeholders::bytes_transferred));
}
else
{
handle_read_error(error);
}
}
void session::CloseSession()
{
if (_is_closed)
return;
_is_closed = true;
std::cout << etr::timestamp << "close session " << std::hex << (int)this << std::endl;
//cause we need recv to detective socket closed message;
_socket.shutdown(boost::asio::ip::tcp::socket::shutdown_send);
_socket.close();
return;
}
void session::handle_read_body( const boost::system::error_code& error ,std::size_t bytes_transferred )
{
if (!error)
{
std::cout << "\t" << etr::timestamp << __FUNCTION__ <<" read " << bytes_transferred << " bytes" << std::endl;
std::cout << _packet_for_recv.body() << std::endl;
char szText[32] = "hello wolrd!";
Send((unsigned char*)szText,sizeof(szText));
boost::asio::async_read(_socket,
boost::asio::buffer(_packet_for_recv.data(),2),
boost::bind(&session::handle_read_header, shared_from_this(), placeholders::error,placeholders::bytes_transferred));
}else{
handle_read_error(error);
}
}
bool session::Send( unsigned char* pMsg,unsigned short wSize )
{
net_packet np;
np.encode_header(wSize);
np.body_length(0);
np.body((char*)pMsg,wSize);
{
boost::recursive_mutex::scoped_lock lock(*_mutex_for_write_buffer);
_is_in_writing = !_packets_for_send.empty();
_packets_for_send.push_back(np);
}
if (!_is_in_writing)
{
boost::asio::async_write(_socket,
boost::asio::buffer(_packets_for_send.front().data(),_packets_for_send.front().length()),
boost::bind(&session::handle_write_msg, shared_from_this(), placeholders::error,placeholders::bytes_transferred));
}
return true;
}
void session::handle_write_msg( const boost::system::error_code& error,std::size_t bytes_transferred)
{
if (!error)
{
std::cout << "\t" << etr::timestamp << "write success with byte_transffered = " << bytes_transferred << std::endl;
{
boost::recursive_mutex::scoped_lock lock(*_mutex_for_write_buffer);
_packets_for_send.pop_front();
}
if (!_packets_for_send.empty())
{
std::cout << "\t" << etr::timestamp << "try to post " << _packets_for_send.front().length() << " bytes" << std::endl;
boost::asio::async_write(_socket,
boost::asio::buffer(_packets_for_send.front().data(),_packets_for_send.front().length()),
boost::bind(&session::handle_write_msg,shared_from_this(),placeholders::error,placeholders::bytes_transferred));
}
}else{
std::cerr << etr::timestamp << "error in func :" << __FUNCTION__ << ".Line " << __LINE__ << "with err_code = " << error << std::endl;
CloseSession();
}
}
void session::handle_read_error( const boost::system::error_code& error )
{
std::cout << etr::timestamp << __FUNCTION__ << " line : " << __LINE__ << "err_code : " << error.value() << " err_msg: " << error.message() << std::endl;
if (!_is_closed) //尚未调用_is_closed
{
_is_closed = true;
_socket.shutdown(boost::asio::ip::tcp::socket::shutdown_both);
_socket.close();
}
if (!_is_notify_disconnect)
{
_is_notify_disconnect = true;
_io->rm_session(shared_from_this());
}
}
iohandler.h
#pragma once
class iohandler :
public boost::noncopyable
{
public:
iohandler(boost::asio::io_service& srv,const tcp::endpoint& endpoint);
~iohandler(void);
void run();
void rm_session(session_ptr session);
void stop();
private:
unsigned short _port;
void handle_accept(session_ptr session,const boost::system::error_code& error);
bool _is_run;
io_service& _io_service;
tcp::acceptor _acceptor;
set<session_ptr> _active_session;
};
iohanlder.cpp
iohandler::iohandler(boost::asio::io_service& srv,const tcp::endpoint& endpoint )
:_is_run(false),
_io_service(srv),
_acceptor(_io_service,endpoint)
{
}
iohandler::~iohandler(void)
{
cout << etr::timestamp << __FUNCTION__ << std::endl;
}
void iohandler::run()
{
if (_is_run)
return;
_is_run = true;
session_ptr new_session(new session(_io_service,this));
_acceptor.async_accept(new_session->Socket(),boost::bind(&iohandler::handle_accept, this, new_session,placeholders::error));
_io_service.run();
}
void iohandler::handle_accept(session_ptr ses,const boost::system::error_code& error)
{
if (!error)
{
_active_session.insert(ses);
ses->Start();
session_ptr new_session(new session(_io_service,this));
_acceptor.async_accept(new_session->Socket(),boost::bind(&iohandler::handle_accept, this, new_session,placeholders::error));
}else{
std::cerr << etr::timestamp << "handle_accept error :" << GetLastError()<< error.message() << "\n"
<< "in file:" << __FILE__ << "in line: " << __LINE__ << std::endl;
}
}
void iohandler::rm_session( session_ptr ses )
{
_active_session.erase(ses);
}
...全文
相关推荐
快速了解Boost.Asio 的多线程模型
主要介绍了Boost.Asio 的多线程模型的相关知识,文中代码非常详细,供大家参考和学习,感兴趣的朋友可以了解下
Boost.ASIO源码:deadline_timer源码级解析(三)—— 从源码解释io_service::run()到底发生了什么
上一篇博客讲到了epoll_reactor的scheduler_timer函数,但是这个函数的操作逻辑其实很不明显,后面涉及到更深的逻辑,故在这里展开讲解。 其实这篇文章的主题我也纠结了很久,不知道从何讲起,因为这个逻辑牵扯十分的深,整个io_service的运行逻辑几乎都有牵扯到,于是干脆就借此总结下io_service.run()的大致运行逻辑。 前文回顾 前面讲deadline_timer:...
Boost.Asio C++ 网络编程 中文版
Boost.Asio C++ 网络编程 PDF 高清 非扫描 中文版
C++ Boost Asio 网络库 讲解示例代码
http://blog.csdn.net/csnd_ayo/article/details/61577634 文章讲解的操作源码
boost_asio:如何使用 boost asio 编程
boost_asio 如何使用 boost asio 进行编程。


工具平台和程序库
