본문 바로가기
Tools for Dev

boost::asio 를 이용한 asyncronous communication 클래스

by leanu 2008. 10. 7.
소켓 요청이 들어오면 등록한 콜백함수를 호출하게 하는 형식으로 작성하였다. 사용시 참고바람

<사용방법>
   0. handler 함수 구현 (형태는 void (string, socket) 이지만 socketmanager를 변경하면 다른 타입도 가능)
   1. io_service obj 선언
         (예) boost::asio::io_service io_service;
   2. endpoint object 선언
         (예) boost::asio::ip::tcp::endpoint endpoint(boost::asio::ip::tcp::v4(), PortNo);
   3. SocketManager object 선언
         (예) SocketManager socketManager(io_service, endpoint, handler)
   4. accept() 함수 실행
         (예) socketManager.accept();
   5. io_service 구동
         (예) io_service.run();

///
/// @file   SocketManager.h
/// @brief  header file of SocketManager class
/// @author Dohyun Yun
/// @date   2008-10-01
/// @details
/// - Log
///


#ifndef _SOCKET_MANAGER_H_
#define _SOCKET_MANAGER_H_

#include <string>

#include <boost/bind.hpp>
#include <boost/asio.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/enable_shared_from_this.hpp>

//#define DEBUG

class SocketObject : public boost::enable_shared_from_this<SocketObject>
{
public:
    SocketObject(boost::asio::io_service& io_service)
        : socket_(io_service), data_(NULL)
    {
    }

    ~SocketObject()
    {
        if (data_ != NULL)
        {
            delete[] data_;
        }
    }


    boost::asio::ip::tcp::socket& socket() { return socket_; };

    void run(void func1(std::string, boost::asio::ip::tcp::socket&))
    {
#ifdef DEBUG
        std::cout << "run() start" << std::endl;
#endif // DEBUG

        handlerFromOutside_ = func1;
        if (data_ != NULL)
        {
            delete[] data_;
        }
        data_ = new char[HEADER_LENGTH];

        boost::asio::async_read(socket_,
                boost::asio::buffer(data_, HEADER_LENGTH),
                boost::bind(&SocketObject::readData, shared_from_this(),
                    boost::asio::placeholders::error));
    }

    void readData(const boost::system::error_code& error)
    {
#ifdef DEBUG
        std::cout << "readData() start" << std::endl;
#endif // DEBUG

        if (!error)
        {
            dataLength_ = *(reinterpret_cast<unsigned int*>(data_));
            if (data_ != NULL)
            {
                delete[] data_;
                data_ = NULL;
            }
            data_ = new char[dataLength_ + 1];
            boost::asio::async_read(socket_,
                    boost::asio::buffer(data_, dataLength_),
                    boost::bind(&SocketObject::runHandlerFromOutside, shared_from_this(),
                        boost::asio::placeholders::error));
        }
    }

    void runHandlerFromOutside(const boost::system::error_code& error)
    {
#ifdef DEBUG
        std::cout << "runHandlerFromOutside() start" << std::endl;
#endif // DEBUG

        if (!error)
        {
            data_[dataLength_] = '\0';
            std::string queryXML(data_);
            handlerFromOutside_(queryXML, socket_);
        }

#ifdef DEBUG
        std::cout << "runHandlerFromOutside() OK" << std::endl;
#endif // DEBUG

    }
public:
    void (*handlerFromOutside_)(std::string, boost::asio::ip::tcp::socket&);
    static const size_t HEADER_LENGTH = sizeof(int);
    boost::asio::ip::tcp::socket    socket_;

private:
    int dataLength_;

    char* data_;
};

typedef boost::shared_ptr<SocketObject> SocketPointer;

///
/// @brief SocketManager controls socket communications between outside and main process.
/// @details
/// SocketManager gets queryXML from outside and sends the resultXML to the outside.\n
/// It supports:
/// - Async reading from outside.
/// - Async writing to outside.
///
class SocketManager
{
public:
    SocketManager(boost::asio::io_service& io_service,
                  const boost::asio::ip::tcp::endpoint& endpoint,
                  void func(std::string, boost::asio::ip::tcp::socket&))
        : io_service_(io_service),
          acceptor_(io_service, endpoint),
          handlerFromOutside_(boost::ref(func)) {};
    ~SocketManager() {};

    void accept()
    {
#ifdef DEBUG
        std::cout << "accept() start" << std::endl;
#endif // DEBUG
        SocketPointer newSocketPointerObject(new SocketObject(io_service_));
        acceptor_.async_accept(newSocketPointerObject->socket(),
                boost::bind(&SocketManager::handler, this, newSocketPointerObject, boost::asio::placeholders::error));
    } // end - accept()

    void handler(SocketPointer socketPointerObject, const boost::system::error_code& error)
    {
#ifdef DEBUG
        std::cout << "handler() start" << std::endl;
#endif // DEBUG

        if (!error)
        {
            socketPointerObject->run(handlerFromOutside_);

            // Make new socket which gets the next connection request.
            SocketPointer newSocketPointerObject(new SocketObject(io_service_));
            acceptor_.async_accept(newSocketPointerObject->socket(),
                boost::bind(&SocketManager::handler, this, newSocketPointerObject, boost::asio::placeholders::error));
        } // end - if
    } // end - handler
private:
    boost::asio::io_service&        io_service_;
    boost::asio::ip::tcp::acceptor  acceptor_;

public:
    void (*handlerFromOutside_)(std::string, boost::asio::ip::tcp::socket&);


}; // end - class


#endif // _SOCKET_MANAGER_H_

'Tools for Dev' 카테고리의 다른 글

GIT - Fast Version Control System  (9) 2008.11.13
boost::shared_ptr  (0) 2008.10.08
boost asio - 수정중  (0) 2008.10.01
boost::enable_shared_from_this  (0) 2008.10.01
boost test  (0) 2008.09.12

댓글