基于BOOST::ASIO封装的异步套接字

周末实在无聊啊
好吧,作为屌丝程序员,还是干点跟自己本行有关的东东

以前封装过scoket异步的程序。是基于linux下select写的,但是select效率比较低
所以最近想重新写下.
然后想写个跨平台的,正好试试自学的boost吧

boost是准C++标准库,非常强大的东西(是不是有点废话 ),底层ASIO 套接字通讯在linux环境下使用epoll,windows下使用IOPC效率是没有问题的。

当然,网上有很多大神些的代码,我只是无聊练练手,跟大神门相差甚远。嘿嘿

好了,我懒人一个,直接贴代码算了
/*
 * socket_session.h
 *
 *  Created on: 2014-11-1
 *      Author: JingJing
 */

#ifndef _SOCKET_SESSION_H_
#define _SOCKET_SESSION_H_

#include <string>
#include <boost/asio.hpp>
#include <boost/smart_ptr.hpp>
#include <boost/bind.hpp>
#include <boost/function.hpp>
#include<boost/enable_shared_from_this.hpp>


using namespace boost;
using namespace boost::asio;
using boost::system::error_code;
using ip::tcp;


#define max_len (1024 * 4)
typedef boost::shared_array<char> SharedArrayPtr;
typedef boost::function<void(const boost::system::error_code&,char*,const size_t)> OnRecvCallBack;
typedef boost::function<void()> OnErrorCallBack;
typedef boost::function<void(const boost::system::error_code&)> OnWriteCallBack;

class CSocketSession;
typedef boost::shared_ptr<CSocketSession>  SocketSessionPtr;

class CSocketSession : public boost::enable_shared_from_this<CSocketSession>
{
public:
    CSocketSession(io_service &ioSev);
    ~CSocketSession(void);

    void SendData(const SharedArrayPtr pData,size_t nDataSize);
    ip::tcp::socket& GetSocket();
    void StartRead(size_t recvSize = 0);

    void RegisterHanleRead(OnRecvCallBack callback);
    void UnRegisterHanleRead();

    void RegisterOnError(OnErrorCallBack callback);
    void UnRegisterOnError();

    void RegisterHandleWrite(OnWriteCallBack callback);
    void UnRegisterHandleWrite();
protected:
    void HandleReadSome(const boost::system::error_code& error, const size_t bytes_transferred);
    void HandleRead(const boost::system::error_code& error, const size_t bytes_transferred, boost::shared_array<char> pSzRecvBuf);
    void HandleWrite(const boost::system::error_code& error,const SharedArrayPtr pData);

    ip::tcp::socket m_socket;
    io_service &m_ioService;
    OnRecvCallBack m_callBack;
private:
    char m_dataRecvBuff[max_len];
    int m_errExit;
    OnRecvCallBack m_recvCallBack;
    OnErrorCallBack m_errorCallBack;
    OnWriteCallBack m_writeCallBack;
};

#endif

/*
 * socket_session.cpp
 *
 *  Created on: 2014-11-1
 *      Author: JingJing
 */

#include "StdAfx.h"
#include "SocketSession.h"
#include "Log.h"


CSocketSession::CSocketSession(io_service &ioSev) 
    :m_ioService(ioSev),
    m_recvCallBack(NULL),
    m_errorCallBack(NULL),
    m_writeCallBack(NULL),
    m_errExit(0),
    m_socket(ioSev)
{
}

CSocketSession::~CSocketSession(void)
{
    m_socket.close();
}
void CSocketSession::RegisterHanleRead(OnRecvCallBack callback)
{
    LOG_TRACE("[CSocketSession]Register recv call back function!");
    m_recvCallBack = callback;
}
void CSocketSession::UnRegisterHanleRead()
{
    LOG_TRACE("[CSocketSession]Unregister recv call back function!");
    m_recvCallBack = NULL;
}

void CSocketSession::RegisterOnError(OnErrorCallBack callback)
{
    LOG_TRACE("[CSocketSession]Register on error call back function!");
    m_errorCallBack = callback;
}

void CSocketSession::UnRegisterOnError()
{
    LOG_TRACE("[CSocketSession]Unregister on error call back function!");
    m_errorCallBack = NULL;
}

void CSocketSession::RegisterHandleWrite(OnWriteCallBack callback)
{
    LOG_TRACE("[CSocketSession]Register handle write call back function!");
    m_writeCallBack = callback;
}
void CSocketSession::UnRegisterHandleWrite()
{
    m_writeCallBack = NULL;
}

void CSocketSession::HandleReadSome(const error_code& error, const size_t bytes_transferred)
{
    if (error)
    {
        m_errExit = 1;
        if(m_errorCallBack != NULL)
        {
            m_errorCallBack();
        }else
        {
            LOG_WARN("[CSocketSession]Not set on error call back function!");
        }
    }

    if(NULL != m_recvCallBack)
    {
        m_recvCallBack(error,(char*)m_dataRecvBuff,bytes_transferred);
    }else
    {
        LOG_WARN("[CSocketSession]Not set on recv call back function!");
    }
}

void CSocketSession::HandleRead(const boost::system::error_code& error, const size_t bytes_transferred, boost::shared_array<char> pSzRecvBuf)
{
    if (error)
    {
        m_errExit = 1;
        if(m_errorCallBack != NULL)
        {
            m_errorCallBack();
        }else
        {
            LOG_WARN("[CSocketSession]Not set on error call back function!");
        }
    }

    if(NULL != m_recvCallBack)
    {
        m_recvCallBack(error, pSzRecvBuf.get(), bytes_transferred);
    }else
    {
        LOG_WARN("[CSocketSession]Not set on recv call back function!");
    }
}


void CSocketSession::HandleWrite(const error_code& error, const SharedArrayPtr pData)
{
    if(m_writeCallBack != NULL)
    {
        m_writeCallBack(error);
    }else
    {
        LOG_WARN("[CSocketSession]Not set handle write call back function!");
    }
}

void CSocketSession::SendData(const SharedArrayPtr pData,size_t nDataSize)
{
    boost::asio::async_write(m_socket,
        boost::asio::buffer(pData.get(), nDataSize),
        boost::bind(&CSocketSession::HandleWrite, shared_from_this(),
        boost::asio::placeholders::error,pData));
}

void CSocketSession::StartRead(size_t recvSize)
{
    if(m_errExit)
    {
        return;
    }

    memset(m_dataRecvBuff, 0, max_len);
    if(recvSize == 0)
    {
        m_socket.async_read_some(boost::asio::buffer(m_dataRecvBuff, max_len),
            boost::bind(&CSocketSession::HandleReadSome, shared_from_this(),
            boost::asio::placeholders::error,
            boost::asio::placeholders::bytes_transferred));
    }else
    {
        try
        {
            boost::shared_array<char>  pSzRecvBuf = boost::shared_array<char>(new char[recvSize + 1]);
            memset(pSzRecvBuf.get(), 0, recvSize + 1);

            boost::asio::async_read(m_socket,boost::asio::buffer(pSzRecvBuf.get(), recvSize),
                boost::bind(&CSocketSession::HandleRead, shared_from_this(),
                boost::asio::placeholders::error,
                boost::asio::placeholders::bytes_transferred, pSzRecvBuf));
        }
        catch (...)
        {
            LOG_WARN("[CSocketSession]StartRead faield!");
        }    
    }
}

ip::tcp::socket& CSocketSession::GetSocket()
{
    return m_socket;
}



/*
 * client_session.h
 *
 *  Created on: 2014-11-1
 *      Author: JingJing
 */

#ifndef _CLIENT_SESSION_H_
#define _CLIENT_SESSION_H_

#include "socketsession.h"

typedef boost::function<void(SocketSessionPtr,const boost::system::error_code&)> OnConnectCallBack;
class CClientSession : public boost::enable_shared_from_this<CClientSession>
{
public:
    CClientSession(io_service &ioSev);
    virtual ~CClientSession(void);

    void Connect(const char* address,const USHORT port);
    void SendData(SharedArrayPtr pData,size_t nDataSize);

    void RegisterHandleRead(OnRecvCallBack callBack);
    void UnRegisterHandleRead();
    
    SocketSessionPtr GetSockertPtr();
    
    void UnRegisterHandleConnect();
    void RegisterHandleConnect(OnConnectCallBack callBack);
    void StartRead();
private:
    void HandleConnect(SocketSessionPtr socketPtr, const boost::system::error_code& error);
    SocketSessionPtr m_pSocketSession;
    OnConnectCallBack m_onConnectCallBack;
};
#endif /* CLIENT_SESSION_H_ */

/*
 * client_session.cpp
 *
 *  Created on: 2014-11-1
 *      Author: JingJing
 */

#include "StdAfx.h"
#include "ClientSession.h"
#include "Log.h"

#include <iostream>
using boost::asio::ip::tcp;
using boost::asio::ip::address;

CClientSession::CClientSession(io_service &ioSev):m_onConnectCallBack(NULL)
{
    m_pSocketSession = boost::make_shared<CSocketSession>(ioSev);
}

CClientSession::~CClientSession(void)
{

}

SocketSessionPtr CClientSession::GetSockertPtr()
{
    return m_pSocketSession;
}

void CClientSession::HandleConnect(SocketSessionPtr socketPtr, const error_code& error)
{
    if(m_onConnectCallBack != NULL)
    {
        m_onConnectCallBack(m_pSocketSession,error);
        //LOG_WARN();
        return;
    }
    LOG_WARN("[CClientSession]Not set on connect call back function!");
}
void CClientSession::RegisterHandleConnect(OnConnectCallBack callBack)
{
    LOG_TRACE("[CClientSession]Register on connect call back function!");
    m_onConnectCallBack = callBack;
}

void CClientSession::UnRegisterHandleConnect()
{
    m_onConnectCallBack = NULL;
}


void CClientSession::RegisterHandleRead(OnRecvCallBack callBack)
{
    LOG_TRACE("[CClientSession]Register on read data call back function!");
    m_pSocketSession->RegisterHanleRead(callBack);
}

void CClientSession::UnRegisterHandleRead()
{
    LOG_TRACE("[CClientSession]UnRegister on read data call back function!");
    m_pSocketSession->UnRegisterHanleRead();
}

void CClientSession::StartRead()
{
    m_pSocketSession->StartRead();
}

void CClientSession::Connect(const char* address,const USHORT port)
{
    //LOG_TRACE("[CClientSession]Connect to address [" <<address << "] port["<< port << "]");
    try
    {
        tcp::endpoint endpoint(address::from_string(address), port);
        m_pSocketSession->GetSocket().async_connect(endpoint,boost::bind(&CClientSession::HandleConnect,shared_from_this(),m_pSocketSession,
            boost::asio::placeholders::error));
    }
    catch (std::exception &e)
    {
        LOG_ERROR("[CClientSession] Connect error:" << e.what());
    }    
}

void CClientSession::SendData(SharedArrayPtr pData,size_t nDataSize)
{
    m_pSocketSession->SendData(pData,nDataSize);
}

/*
 * server_session.h
 *
 *  Created on: 2014-11-1
 *      Author: JingJing
 */

#ifndef _SERVER_SESSION_H_
#define _SERVER_SESSION_H_

#include "socketsession.h"

#include <boost/shared_ptr.hpp>
#include <boost/bind.hpp>
#include <boost/function.hpp>

typedef boost::function<void (boost::shared_ptr<CSocketSession>, const std::string)> OnNewConnectCallBack;

class CServerSession : public boost::enable_shared_from_this<CServerSession>
{
public:
    CServerSession(io_service &ioSev);
    virtual ~CServerSession(void);

    void Accept(const unsigned short port);
    void SendData(SocketSessionPtr pSocketSession, SharedArrayPtr pData,size_t nDataSize);
    void RegisterOnNewConnect(OnNewConnectCallBack callBack);
    
    void StartRead(SocketSessionPtr pSocketSession);
private:
    void StartAccept();
    void HandleAccept(SocketSessionPtr pSocketSession, const boost::system::error_code& error);

    boost::shared_ptr<tcp::acceptor> m_pAcceptor;
    OnNewConnectCallBack m_onConnectCallBack;
    io_service& m_ioService;
};

#endif /* SERVER_SESSION_H_ */

/*
 * server_session.cpp
 *
 *  Created on: 2014-11-1
 *      Author: JingJing
 */

#include "StdAfx.h"
#include "ServerSession.h"
#include "Log.h"

CServerSession::CServerSession(io_service &ioSev) : m_onConnectCallBack(NULL),m_ioService(ioSev)
{
}

CServerSession::~CServerSession(void)
{
}

void CServerSession::HandleAccept(boost::shared_ptr<CSocketSession> pSocketSession, const error_code& error)
{
    if(m_onConnectCallBack != NULL)
    {
        std::string dstaddr = pSocketSession->GetSocket().remote_endpoint().address().to_string();
        m_onConnectCallBack(pSocketSession, dstaddr);
    }else
    {
        LOG_WARN("[CServerSession]Not set on connect call back function!");
    }
    StartAccept();
}

void CServerSession::RegisterOnNewConnect(OnNewConnectCallBack callBack)
{
    LOG_TRACE("[CServerSession]ServerSession register on new connect call back function!");
    m_onConnectCallBack = callBack;
}

void CServerSession::StartRead(SocketSessionPtr pSocketSession)
{
    pSocketSession->StartRead();
}

void CServerSession::Accept(const unsigned short port)
{
    LOG_TRACE("[CServerSession]Accept start : port[" << port << "]");
    m_pAcceptor = boost::make_shared<tcp::acceptor>(m_ioService,tcp::endpoint(ip::tcp::v4(),port));
    StartAccept();
}

void CServerSession::StartAccept()
{
    boost::shared_ptr<CSocketSession> pSocketSession = boost::make_shared<CSocketSession>(m_ioService);
    m_pAcceptor->async_accept(pSocketSession->GetSocket(),
        boost::bind(&CServerSession::HandleAccept,shared_from_this(),pSocketSession,boost::asio::placeholders::error));
}

void CServerSession::SendData(boost::shared_ptr<CSocketSession> pSocketSession, SharedArrayPtr pData,size_t nDataSize)
{
    if(pSocketSession)
    {
        pSocketSession->SendData(pData,nDataSize);
    }
}

额 由于写完时间有点紧,所以没有编译,也没有测试
等有空我会测试下的

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值