24,854
社区成员
发帖
与我相关
我的任务
分享
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;
}
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里调用。
}
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::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());
}
}
#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;
};
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);
}
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()则不会。
}