求解惑:boost asio io_service.run在不同位置调用产生的不同结果

Vinc 2013-03-25 03:03:45
A:在main中调用
 
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);
}

...全文
310 2 打赏 收藏 转发到动态 举报
写回复
用AI写文章
2 条回复
切换为时间正序
请发表友善的回复…
发表回复
Vinc 2013-03-25
  • 打赏
  • 举报
回复
iohandle的代码被我放到后面去了,由于长度限制一些其他的代码就不贴了。 主要是

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();//在这里调用第一个session直到io_service.close后才会被释放。
//在main函数里面调用io_service.run()则不会。
 
}

24,854

社区成员

发帖
与我相关
我的任务
社区描述
C/C++ 工具平台和程序库
社区管理员
  • 工具平台和程序库社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧