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 件のコメント:
コメントを投稿