class ServerModule : private boost::noncopyable
今回は、接続後のやり取りを分けてみたいと思います。行うことはシンプルで、非同期処理関数をクラスにまとめて分けます。
ソースコードは以下です。
ServerModule.hpp
#pragma once
#ifndef __ASIO_SERVER_MODULE__
#define __ASIO_SERVER_MODULE__
#include <iostream>
#include <boost/asio.hpp>
#include <boost/bind.hpp>
namespace thorny_road{
using namespace boost::asio ;
class ServerSession : private boost::noncopyable
{
private:
io_service& io ;
ip::tcp::socket socket ;
boost::asio::streambuf buf ;
public:
ServerSession(io_service& io) : io(io),socket(io) {}
~ServerSession() {}
void start()
{
// Enqueue Read Handler
async_read_until(
socket,
buf,
'\n',
boost::bind(&ServerSession::read_ok,this,_1) ) ;
}
private:
void read_ok(const boost::system::error_code e)
{
if (!e)
{
std::iostream ios(&buf) ;
std::string tmp ;
ios >> tmp ; // get input stream
if (tmp == "end") { delete this; return; }
ios << tmp <<std::endl ; // retrun as it is
// Enqueue Write Handler
async_write(
socket,
buf,
boost::bind(&ServerSession::write_ok,this,_1) ) ;
}
}
void write_ok(const boost::system::error_code e)
{
if (!e)
{
start() ; // Restart
}
}
public:
ip::tcp::socket& getSocket()
{
return (socket) ;
}
} ;
class ServerModule : private boost::noncopyable
{
private:
io_service& io ;
ip::tcp::acceptor accept ;
ServerSession* session ;
public:
ServerModule(io_service& io, const short port)
:io(io),accept(io,ip::tcp::endpoint(ip::tcp::v4(),port))
{
start_accept() ;
}
void start_accept()
{
session = new ServerSession(io) ;
// Enqueue Accept Handler
accept.async_accept(
session->getSocket(),
boost::bind(&ServerModule::accept_ok,this,_1) ) ;
}
void accept_ok(const boost::system::error_code e)
{
if (!e)
{
session->start() ;
start_accept() ;
}
else
{
// error
delete session ;
session = NULL ;
return ;
}
}
} ;
} // namespace thorny_road
#endif //__ASIO_SERVER_MODULE__メインは変更はありません。接続後の処理はServerSessionクラスで行うようになりました。このため、SocketはServerSessionが管理するようになります。
ServerModuleでは接続完了後(accept_ok(...)が呼ばれると)、start_accept()を呼び、新たにSessionを作成し接続待ち状態になります。
ServerSessionでは前回同様入力をそのままエコーバックします。ただし、入力が"end"の場合、ServerSessionオブジェクトを破棄され、接続を切断します。
if (tmp == "end") { delete this; return; }
また、今回は簡単なboost::system::error_codeの処理をいれています。ハンドラーの引数であるboost::system::error_codeは正常の場合、0になります。
ようやく「らしく」なってきました。次はどうしようか考え中です。
ソースコードは自由にご使用ください。ただし問題が起きても責任はとれません。また、ソースコードに対する著作権は放棄していません。
0 件のコメント:
コメントを投稿