• http客户端-基于boost开发


    http客户端-基于boost开发

      基于BOOST编写的http客户端,作为BOOST开发学习之用。目前支持功能:

    • http协议,单向链接返回http response code 200
    • 可content type 为text或image下载到本地
    • 仅支持http返回code为200,不支持3XX、4XX等
    • 暂不支持chunk传输,chunk代码待调试
    • 日志文件,提供类ACE的输出方式,如LOG((LOG_DEBUG,"[%T(%t)] test begin %d  %s "), int_num_2, string_test.c_str());
    • 数据缓冲区,当前为new方式,后续可更改为从boost pool获取
    • 。。。

     

      

     1 类关系图

     

    2 核心代码

    2.1 IOServer,提供asio线程环境

     1 #pragma once
     2 #include "boost/serialization/singleton.hpp"
     3 #include "boost/asio.hpp"
     4 #include "boost/thread.hpp"
     5 #include "boost/bind.hpp"
     6 #include "Event.h"
     7 #include "../concurrent/IRunable.h"
     8 #include "SimpleLog.h"
     9 class IO_Server : public IRunable
    10 {
    11 public:
    12     IO_Server(): bExit(false)
    13     {
    14     }
    15     boost::asio::io_service* GetIOS()
    16     {
    17         return &ios;
    18     }
    19     void ActiveIOS()
    20     {
    21         boost::unique_lock<boost::mutex> lock(mu);
    22         if (ios.stopped())
    23         {
    24             cond.notify_one();
    25         }
    26     }
    27     void Exit()
    28     {
    29         ios.stop();
    30         bExit = true;
    31     }
    32 private:
    33     virtual int Run()
    34     {
    35         LOG((LOG_DEBUG,"[%T(%t)] ios server run ,id = %d
    ", boost::this_thread::get_id()));
    36         ios.stop();
    37         while (1)
    38         {
    39             // 设置退出线程
    40             if (bExit)
    41             {
    42                 break;
    43             }
    44             //
    45             {
    46                 boost::unique_lock<boost::mutex> lock(mu);
    47                 if (ios.stopped())
    48                 {
    49                     cond.wait(mu);
    50                 }
    51             }
    52             if (ios.stopped())
    53             {
    54                 ios.reset();
    55                 ios.run();
    56             }
    57         }
    58         return 0;
    59     }
    60 private:
    61     boost::asio::io_service            ios;    //所有的asio都要有个ios
    62     boost::mutex                    mu;
    63     boost::condition_variable_any    cond;
    64     bool                            bExit;
    65 };
    66 typedef boost::serialization::singleton<IO_Server> IOS;
    View Code

    2.2 task及sock资源管理器

      1 #pragma once
      2 #include "ios.h"
      3 #include "handle.h"
      4 #include "ios.h"
      5 #include "SimpleLog.h"
      6 #include "../concurrent/ThreadPool.h"
      7 #include "../concurrent/IRunable.h"
      8 #include "MsgQueue.h"
      9 /************************************************************************/
     10 /* Handle的集合.多线程共享                                       */
     11 /************************************************************************/
     12 typedef boost::shared_ptr<IRunable> IRunablePtr;
     13 typedef CMsgQueue<IRunablePtr> IRunPtrQueue;
     14 template<class CLIENT>
     15 class HandleSet : public IRunable
     16 {
     17 public:
     18     HandleSet()
     19     {
     20         bExit = false;
     21         nHighWaterMark = 5;
     22         nClientUsed = 0;
     23 
     24         m_poThreadPool = boost::shared_ptr<ThreadPool>(new ThreadPool("HandleSet_Pool", 1, boost::thread::hardware_concurrency()));
     25         //启动ioserver线程
     26         IO_Server& ioserver = IOS::get_mutable_instance();
     27         m_poThreadPool->Start(&ioserver);
     28         //启动
     29         m_poThreadPool->Start(this);
     30     }
     31     ~HandleSet(){}
     32     //加入一个task
     33     void AddTask(TaskPtr task)
     34     {
     35         boost::unique_lock<boost::mutex> lock(mu);
     36         ClientHandlePtr client;
     37         if (!GetFreeClient(client))
     38         {
     39             tasks.push_back(task);
     40             return;
     41         }
     42         client->Busy(true);
     43         client->HTTP_Connect(task);
     44         InterlockedIncrement(&nClientUsed);
     45         IOS::get_mutable_instance().ActiveIOS();
     46     }
     47 
     48     //设置client水位标
     49     void HighWaterMark(int mark)
     50     {
     51         nHighWaterMark = mark;
     52     }                    
     53 
     54     void NotifyComplete(ClientHandle* client, const boost::system::error_code& ec, 
     55         CMsgBlock& msg)
     56     {
     57         switch (ec.value())
     58         {
     59         case 0:    //正常退出
     60             {
     61                 boost::unique_lock<boost::mutex> lock(mu);
     62                 client->pTask->Finish(SUCCESS, msg);
     63                 client->Busy(false);
     64                 client->Reset();
     65                 InterlockedDecrement(&nClientUsed);
     66             }
     67             break;
     68         case 2:    //远端关闭连接
     69             {
     70                 
     71             }
     72             break;
     73         }
     74     }
     75 private:
     76     //找出一个空闲的client
     77     bool GetFreeClient(ClientHandlePtr& ptr)
     78     {
     79         if (clients.size() >= nHighWaterMark && nClientUsed >= nHighWaterMark)
     80         {
     81             return false;
     82         }
     83         //空队列,创建一个新的
     84         if (clients.empty())
     85         {
     86             ptr = CreateNewHandle();
     87             clients.push_back(ptr);
     88             return true;
     89         }
     90         //非空则找出一个空闲
     91         LiClientHandlePtr::iterator iter = clients.begin();
     92         for ( ;iter != clients.end(); iter++)
     93         {
     94             ClientHandlePtr client = *iter;
     95             if (!client->Busy())
     96             {
     97                 ptr = client;
     98                 return true;
     99             }
    100         }
    101         //无空闲且饱和
    102         if (nClientUsed < nHighWaterMark)
    103         {
    104             ptr = CreateNewHandle();
    105             clients.push_back(ptr);
    106             return true;
    107         }
    108         return false;
    109     }
    110     ClientHandlePtr CreateNewHandle()
    111     {
    112         return ClientHandlePtr(
    113             new CLIENT(IOS::get_mutable_instance().GetIOS(), boost::bind(&HandleSet::NotifyComplete, this, _1, _2, _3)));
    114     }
    115 private:
    116     virtual int Run()
    117     {
    118         LOG((LOG_DEBUG,"[%T(%t)] handleSet %s thread run
    ", typeid(this).name()));
    119         while (1)
    120         {
    121             // 设置退出线程
    122             if (bExit)
    123             {
    124                 break;
    125             }
    126             {
    127                 boost::unique_lock<boost::mutex> lock(mu);
    128                 if (!tasks.empty())
    129                 {
    130                     ClientHandlePtr client;
    131                     if (GetFreeClient(client))
    132                     {
    133                         TaskPtr task = tasks.front();
    134                         tasks.pop_front();
    135                         client->Busy(true);
    136                         client->HTTP_Connect(task);
    137                         InterlockedIncrement(&nClientUsed);
    138                     }
    139                     IOS::get_mutable_instance().ActiveIOS();
    140                 }
    141             }
    142             boost::this_thread::sleep_for(boost::chrono::milliseconds(10));
    143 
    144             //线程池模式
    145             /*if (queue.empty())
    146             {
    147                 boost::this_thread::sleep_for(boost::chrono::milliseconds(20));
    148                 continue;
    149             }
    150 
    151             IRunablePtr ptrTask;
    152             queue.dequeue_head(ptrTask, 10);
    153 
    154             if (ptrTask)
    155             {
    156                 m_poThreadPool->Start(ptrTask);
    157             }*/
    158         }
    159         return 0;
    160     }
    161 private:
    162     int                    nHighWaterMark;        //并发执行数量为1--nHighWaterMark
    163     LiClientHandlePtr    clients;
    164 
    165     TaskPtrList            tasks;
    166     long                nClientUsed;
    167     bool                bExit;
    168     boost::mutex        mu;
    169 
    170     boost::shared_ptr<ThreadPool> m_poThreadPool; ///<线程池共享指针
    171     IRunPtrQueue        queue;
    172 };
    View Code

    2.3 socket工厂模式虚接口,供资源管理器调用

     1 #pragma once
     2 /************************************************************************/
     3 /* 提供网络行为                                               */
     4 /************************************************************************/
     5 #include <string>
     6 #include "boost/smart_ptr.hpp"
     7 #include "boost/asio.hpp"
     8 #include "boost/date_time/posix_time/posix_time.hpp"
     9 #include "boost/thread.hpp"
    10 #include "MsgBlock.h"
    11 #include "SimpleLog.h"
    12 #include "userTask.h"
    13 using namespace boost;
    14 using namespace boost::asio;
    15 using namespace std;
    16 
    17 class ClientHandle;
    18 typedef boost::shared_ptr<ip::tcp::socket> sock_ptr;
    19 typedef boost::shared_ptr<ClientHandle> ClientHandlePtr;
    20 typedef std::list<ClientHandlePtr>    LiClientHandlePtr;
    21 
    22 typedef boost::function<void(ClientHandle* handle, 
    23     const boost::system::error_code& ec, CMsgBlock&)>    NotifyCompleteFunc;
    24 
    25 class ClientHandle
    26 {
    27 public:
    28     ClientHandle(boost::asio::io_service* ios, NotifyCompleteFunc completeFun);
    29     ~ClientHandle();
    30 public:    //主动请求
    31     void HTTP_Connect(TaskPtr task);
    32     //http send请求
    33     void HTTP_Send(CMsgBlock& block);
    34     //http close
    35     void HTTP_Close();
    36     //http recv,接收到数据后回调
    37     void HTTP_Recv();
    38     bool Busy();
    39     void Busy(bool busy);
    40     void Reset();
    41 public:    //回调函数
    42     //http send,接收到数据后回调
    43     virtual void CB_Send(const boost::system::error_code& ec, size_t len) = 0;
    44     //http recv,接收到数据后回调
    45     virtual void CB_Recv(const boost::system::error_code& ec, size_t len) = 0;
    46     //http connect result,连接结果回调
    47     virtual void CB_HTTP_Connect_Result(const boost::system::error_code& ec) = 0;
    48     //http result, 返回错误码及第一次数据
    49     virtual int CB_HTTP_CODE(int retCode, CMsgBlock& block) = 0;
    50     //连接超时
    51     virtual void CB_HTTP_Timeout() = 0;
    52     //对端关闭连接
    53     virtual void CB_Remote_Close() = 0;
    54 public:
    55     TaskPtr        pTask;
    56 protected:
    57     //写缓冲区和写指针
    58     CMsgBlock    _rdBuf;
    59     CMsgBlock    _wrBuf;
    60     DWORD        lastDataTime;    //活动时间
    61     long        recvSz;            //累计接收数据量
    62     //记录任务
    63     sock_ptr    sock;
    64     boost::asio::ip::tcp::endpoint ep;
    65     bool        bBusy;
    66     NotifyCompleteFunc _completeFun;
    67 };
    View Code

    2.4 socket管理实例

      1 //http recv,接收到数据后回调
      2 void ITsoftware_Index::CB_Send(const boost::system::error_code& ec, size_t len)
      3 {
      4     if (ec)
      5     {
      6         //错误,调用返回
      7         return;
      8     }
      9     if (len == _wrBuf.Size())
     10     {
     11         _rdBuf.Reset();
     12         sock->async_read_some(boost::asio::buffer(_rdBuf.Base() + _rdBuf.WtPtr(), _rdBuf.Space()), 
     13             bind(&ClientHandle::CB_Recv, this, _1, _2));
     14     }
     15     else
     16     {
     17         sock->async_write_some(boost::asio::buffer(_wrBuf.Base() + len, _wrBuf.Size() - len), 
     18             bind(&ClientHandle::CB_Send, this, _1, _2));
     19     }
     20 }
     21 
     22 //http recv,接收到数据后回调
     23 void ITsoftware_Index::CB_Recv(const boost::system::error_code& ec, size_t len)
     24 {
     25     if (ec || !pTask)
     26     {
     27         return;
     28     }
     29     recvSz += len;
     30     _rdBuf.WtPtr(len);
     31 
     32     bool bLastData = (_rdBuf.Space() > 0)? true : false;    //缓冲区未接收满,说明当前数据已经收完
     33 
     34     int ret = 0;
     35     if (!pTask->_head.bReady)
     36     {
     37         ret = ParseHead(_rdBuf);
     38         if (ret == 0)    //头未收完,继续接收
     39         {
     40             sock->async_read_some(boost::asio::buffer(_rdBuf.Base() + _rdBuf.WtPtr(), _rdBuf.Space()), 
     41                 bind(&ClientHandle::CB_Recv, this, _1, _2));
     42             return;
     43         }
     44         // 返回为http的代码
     45         ret = CB_HTTP_CODE(ret, _rdBuf);
     46     }
     47 
     48     switch (ret)
     49     {
     50     case -1:
     51         {
     52             sock->shutdown(ip::tcp::socket::shutdown_both);
     53             sock->close();
     54             _completeFun(this, ec, parseOnlineBlock);
     55             parseOnlineBlock.Reset();
     56         }
     57         break;
     58     case 0:
     59         {
     60             int retWriteData = 0;
     61             if (_rdBuf.Size() > 0)
     62             {
     63                 retWriteData = WriteData(_rdBuf);        //处理数据流
     64             }
     65             _rdBuf.Reset();
     66             if (retWriteData == -1)
     67             {
     68                 sock->shutdown(ip::tcp::socket::shutdown_both);
     69                 sock->close();
     70                 _completeFun(this, ec, parseOnlineBlock);
     71                 parseOnlineBlock.Reset();
     72             }
     73             else
     74             {
     75                 sock->async_read_some(boost::asio::buffer(_rdBuf.Base() + _rdBuf.WtPtr(), _rdBuf.Space()), 
     76                     bind(&ClientHandle::CB_Recv, this, _1, _2));
     77             }
     78         }
     79         break;
     80     case 1:
     81         {
     82 
     83         }
     84         break;
     85     }
     86 }
     87 //http connect result,连接结果回调
     88 void ITsoftware_Index::CB_HTTP_Connect_Result(const boost::system::error_code& ec)
     89 {
     90     if (ec)
     91     {
     92         //错误,调用返回
     93         return;
     94     }
     95     std::string getContent = "GET " + pTask->_info.URI + " HTTP/1.1
    ";
     96     getContent += "Host: " + pTask->_info.host + "
    ";
     97     getContent += "Connection: keep-alive
    ";
     98     getContent += "User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.100 Safari/537.36
    ";
     99     getContent += "Accept-Encoding: gzip, deflate
    ";
    100     getContent += "Accept-Language: zh-CN,zh;q=0.8
    
    ";
    101 
    102     _wrBuf.Reset();
    103     _wrBuf.Write(getContent.c_str(), getContent.length());
    104     HTTP_Send(_wrBuf);
    105 }
    106 
    107 //http recv,收到全部数据后回调,httpcode=200
    108 int ITsoftware_Index::CB_HTTP_CODE(int retCode, CMsgBlock& block)
    109 {
    110     int ret = 0;
    111     //准备文件及缓冲区
    112     if (retCode == 200)        
    113     {
    114         if (pTask->HasFlag(CONTENT_TYPE_DOWNLOAD))            //开启下载
    115         {
    116             if (pTask->_head.nContentType == CONTENT_TYPE_IMAGE ||
    117                 pTask->_head.nContentType == CONTENT_TYPE_TEXT)
    118             {
    119                 char sss[100] = {0};
    120                 sprintf_s(sss, 100, "%d", InterlockedIncrement(&filenameprev));
    121                 pTask->FilePtr(std::string(sss) + pTask->_info.lastName);        //创建文件
    122                 if (!pTask->FilePtr())        //文件创建失败,则接收失败
    123                 {
    124                     ret = -1;
    125                     //LOG((LOG_DEBUG,"[%T(%t)] create file failed, %s 
    ", pTask->_url.c_str()));
    126                 }
    127             }
    128         }
    129         if (pTask->HasFlag(CONTENT_TYPE_PARSEONLINE))        //调用完成后回传给task
    130         {
    131             if (pTask->_head.bContentLength)
    132             {
    133                 parseOnlineBlock.Capacity(pTask->_head.nContentLength);
    134             }
    135             else if (pTask->_head.bChunked)
    136             {
    137                 parseOnlineBlock.Capacity(block.Capacity() * 2);
    138             }
    139             if (parseOnlineBlock.Capacity() == 0)
    140             {
    141                 ret = -1;
    142                 //LOG((LOG_DEBUG,"[%T(%t)] create parseOnlineBlock buffer failed, %s 
    ", pTask->_url.c_str()));
    143             }
    144         }
    145     }
    146     //重定向
    147     else if (300 < retCode && retCode < 399)
    148     {
    149         ret = -1;        //中断当前
    150     }
    151     return ret;
    152 }
    153 
    154 //连接超时
    155 void ITsoftware_Index::CB_HTTP_Timeout()
    156 {
    157 
    158 }
    159 //对端关闭连接
    160 void ITsoftware_Index::CB_Remote_Close()
    161 {
    162 
    163 }
    164 
    165 int ITsoftware_Index::ParseHead(CMsgBlock& _block)
    166 {
    167     int ret = 0;
    168     int rnrn = Tools::KMPFind(_block.Base(), _block.Size(), RNRN, RNRN_SIZE);
    169     if (rnrn != -1)
    170     {
    171         //头收完全,处理http头
    172         char* cRnrn = new char[rnrn + 1 + 2];
    173         ZeroMemory(cRnrn,rnrn+1);
    174         memcpy(cRnrn, _block.Base(), rnrn + 2);
    175         if (pTask->_head.ParseHead(cRnrn ))
    176         {
    177             pTask->_head.bReady = true;
    178             //数据移位,把头去掉,保证缓冲区内都是数据体
    179             int remain = _block.Size() - rnrn -4;        //剩余长度
    180             char* remain_begin_pos = _block.Base() + rnrn + 4;
    181             _block.Reset();                                //读写指针置零
    182             _block.Write(remain_begin_pos, remain);        //重新写入
    183             ret =  pTask->_head.code;
    184         }
    185         else    //文件头出错,关闭连接
    186         {
    187             ret = -1;
    188             //LOG((LOG_DEBUG,"[%T(%t)] recv http head parse error, %s
    , %s 
    ", pTask->_url.c_str() ,cRnrn));
    189         }
    190         delete cRnrn;
    191     }
    192     else
    193     {
    194         //没有收到
    
    ,则表明头还没收完全
    195         ret = 0;
    196     }
    197     return ret;
    198 }
    199 
    200 int ITsoftware_Index::WriteData(CMsgBlock& _block)
    201 {
    202     int ret = 0; 
    203     if(pTask->_head.bContentLength)
    204     {
    205         if (pTask->HasFlag(CONTENT_TYPE_DOWNLOAD) && 
    206             (pTask->_head.nContentType == CONTENT_TYPE_IMAGE ||    pTask->_head.nContentType == CONTENT_TYPE_TEXT))
    207         {
    208             if (!pTask->FilePtr()->bad())
    209             {
    210                 pTask->FilePtr()->write(_block.Base(), _block.Size());
    211             }
    212         }
    213         if (pTask->HasFlag(CONTENT_TYPE_PARSEONLINE))
    214         {
    215             parseOnlineBlock.Write(_block.Base(), _block.Size());
    216         }
    217         if (recvSz >= pTask->_head.nContentLength)
    218         {
    219             if (pTask->HasFlag(CONTENT_TYPE_DOWNLOAD) && 
    220                 (pTask->_head.nContentType == CONTENT_TYPE_IMAGE ||    pTask->_head.nContentType == CONTENT_TYPE_TEXT))
    221             {
    222                 pTask->FilePtr()->close();
    223             }
    224             ret = -1;
    225         }
    226     }
    227     else if (pTask->_head.bChunked)
    228     {
    229         //    //chunk,通过辨识末尾7位是否是HTTP_END,来判断数据是否已接收完整
    230         //    if(_block.RdPtr() > HTTP_END_SIZE)
    231         //    {
    232         //        char cend[HTTP_END_SIZE+1]= {0};
    233         //        memcpy(cend, _block.Base() + _block.Size() - 7, HTTP_END_SIZE);
    234         //        int cmp = strcmp(cend,HTTP_END);
    235         //        if (cmp != 0)
    236         //        {
    237         //            //未接收完整,继续接收
    238         //            return 0;
    239         //        }
    240         //    }
    241         //    //数据接收完全,把chunk的长度字符全部删除
    242         //    int beginPos = rnrn + 4;
    243         //    while (true)
    244         //    {
    245         //        int rnBegin = Tools::KMPFind(_block.Base(), _block.Size(), RN, RN_SIZE, beginPos);
    246         //        if (rnBegin != -1)
    247         //        {
    248         //            char*  tets = _block.Base() + rnBegin;
    249         //            //计算出chunk的长度
    250         //            char* cchunk = new char[rnBegin - rnrn - 4 + 1];
    251         //            ZeroMemory(cchunk, rnBegin - rnrn - 4 + 1);
    252         //            memcpy(cchunk, _block.Base() + rnrn + 4, rnBegin - rnrn - 4);
    253         //            int chunk = strtol(cchunk,NULL,16);
    254         //            delete cchunk;
    255         //            if (chunk ==0)
    256         //                break;
    257         //            //copy chunck的字节到body
    258         //            result.Write(_block.Base() + rnBegin + RN_SIZE, chunk); 
    259         //            beginPos = rnBegin + chunk+RN_SIZE*2;
    260         //        }
    261         //        else
    262         //            break;
    263     }
    264     return ret;
    265 }
    View Code

    2.5 下发任务

     1 #pragma once
     2 #include <string>
     3 #include "boost/bind.hpp"
     4 #include "boost/function.hpp"
     5 #include "boost/smart_ptr.hpp"
     6 #include "SimpleLog.h"
     7 #include "MsgBlock.h"
     8 #include "httphead.h"
     9 #include "Tools.h"
    10 using namespace std;
    11 class Task;
    12 
    13 enum NotifyType{
    14     SUCCESS,
    15     FAILED
    16 };
    17 
    18 typedef boost::function<void(NotifyType,const std::string&)>    NotifyFunc;
    19 typedef boost::shared_ptr<Task> TaskPtr;
    20 typedef std::list<TaskPtr> TaskPtrList;
    21 
    22 class Task
    23 {
    24 public:
    25     static TaskPtr CreateTask(std::string url, long flag = CONTENT_TYPE_NONE, std::string downPath = "")
    26     {
    27         return boost::shared_ptr<Task>(new Task(url, flag, downPath));
    28     }
    29 public:
    30     virtual ~Task()
    31     {
    32         if (_file)
    33         {
    34             _file->close();
    35         }
    36     }
    37     virtual void Finish(NotifyType type, CMsgBlock& retMsg)
    38     {
    39         LOG((LOG_DEBUG, "[%T(%t)] NotifyComplete %d, %s 
    ", type, _url.c_str()));
    40 //         if (type == SUCCESS)
    41 //         {
    42 //             std::vector<std::string> vecs;
    43 //             Tools::HttpStringOpt::ExtractAllUrl(std::string(result.Base(), result.Size()), vecs);
    44 //         }
    45     }
    46     inline ofstreamPtr FilePtr()
    47     {
    48         return _file;
    49     }
    50     inline void FilePtr(std::string filename)
    51     {
    52         if (_file)
    53         {
    54             _file->close();
    55         }
    56         std::string filepath = _downloadPath + std::string("/") + filename;
    57         ofstreamPtr ptr = Tools::GetNewFile(filepath);
    58         _file.swap(ptr);
    59     }
    60     Task(const Task& t)
    61     {
    62         _url = t._url;
    63     }
    64     Task* operator= (const Task& t)
    65     {
    66         _url = t._url;
    67     }
    68     inline bool HasFlag(long flag)
    69     {
    70         return flag & _flag;
    71     }
    72 private:
    73     Task(std::string url, long flag, std::string downPath)
    74         :_url(url),
    75         _flag(flag),
    76         _downloadPath(downPath)
    77     {
    78         _head.Reset();
    79         Tools::HttpStringOpt::SpliterHttpUrl(_url, _info);        
    80     }
    81 public:
    82     std::string _url;
    83     long        _flag;
    84     HttpHead    _head;
    85     std::string _downloadPath;        //下载目录
    86     UrlInfo        _info;
    87 private:
    88     ofstreamPtr _file;
    89 };
    View Code

    2.5 缓冲数据块

      1 #pragma once
      2 #include "boost/smart_ptr.hpp"
      3 #ifndef DEFAULT_BUF_SIZE
      4 #define DEFAULT_BUF_SIZE 1024
      5 #endif
      6 class CMsgBlock;
      7 typedef boost::shared_ptr<CMsgBlock> MsgBlockPtr;
      8 
      9 /************************************************************************/
     10 /* 简易数据缓冲区                                                */
     11 /************************************************************************/
     12 class CMsgBlock
     13 {
     14 public:
     15     CMsgBlock(){
     16         Reset();
     17         _block = NULL;
     18         _capacity = 0;
     19     }
     20     CMsgBlock(int sz){
     21         Reset();
     22         _block = NULL;
     23         _capacity = 0;
     24         Capacity(sz);
     25     }
     26     ~CMsgBlock(){
     27         if (_block != NULL)
     28         {
     29             delete [] _block;
     30             _block = NULL;
     31         }
     32     }
     33     //重置缓冲区,仅移动指针
     34     void Reset()
     35     {
     36         _rdPrt = 0;
     37         _wrPtr = 0;
     38     }
     39     //获取数据块大小
     40     int     Size()
     41     {
     42         return _wrPtr - _rdPrt;
     43     }
     44     //获取缓冲区容量
     45     int     Capacity()    
     46     {
     47         return _capacity;
     48     }
     49     //获取剩余空间
     50     int  Space() 
     51     {
     52         return _capacity - _wrPtr;
     53     }
     54     // 获取基址
     55     char* Base() 
     56     {
     57         return _block;
     58     }
     59     //读地址
     60     int RdPtr() 
     61     {
     62         return _rdPrt;
     63     }
     64     void RdPtr(int ptr) 
     65     { 
     66         _rdPrt += ptr;
     67     }
     68     //写地址
     69     int WtPtr() 
     70     {
     71         return _wrPtr;    
     72     }
     73     void WtPtr(int ptr) 
     74     { 
     75         _wrPtr += ptr;
     76     }
     77     //重置缓冲区大小
     78     bool Capacity(int sz)
     79     {
     80         if (_capacity >= sz)
     81             return true;
     82         else 
     83         {
     84             char* temp = new char[sz];
     85             if (temp == NULL)
     86                 return false;
     87             if (_block)
     88             {
     89                 memcpy(temp,_block,_capacity);
     90                 delete [] _block;
     91             }
     92             _block = temp;
     93             _capacity = sz;
     94         }
     95         return true;
     96     }
     97     //写缓冲区
     98     bool Write(const char* buf,int leng)
     99     {
    100         //缓冲区可写区域不足
    101         if (Space() < leng)
    102         {
    103             //重置缓冲区
    104             if (!Capacity(_capacity + 2*leng + DEFAULT_BUF_SIZE ))
    105                 return false;
    106         }
    107         memcpy(_block + _wrPtr,buf,leng);
    108         _wrPtr += leng;
    109         return true;
    110     }
    111     void Copy(CMsgBlock* block)
    112     {
    113         if (block != this)
    114         {
    115             this->Reset();
    116             this->Write(block->Base(),block->Size());
    117         }
    118     }
    119     void Copy(CMsgBlock& block)
    120     {
    121         Copy(&block);
    122     }
    123 private:
    124     char*    _block;                //数据块
    125     unsigned int _rdPrt;        //读指针
    126     unsigned int _wrPtr;        //写指针
    127     unsigned int _capacity;        //容量
    128 };
    View Code

    2.6 日志输出

      1 //输出日志
      2     void Log(LogType type,const char *format_str, ...)
      3     {
      4 
      5         //调整缓冲区 
      6         _block.Reset();
      7 
      8         va_list argp;
      9         va_start (argp, format_str);
     10         while (*format_str != '')
     11         {
     12             if (*format_str != '%')
     13             {
     14                 _block.Write(format_str,1);
     15             }
     16             else if (format_str[1] == '%') // An "escaped" '%' (just print one '%').
     17             {
     18                 format_str++;    // Store first %
     19             }
     20             else
     21             {
     22                 char format[128] = {0}; // 临时变量,保存%转换的临时结果
     23                 int     len = 0;
     24                 format_str++;   // Copy in the %
     25 
     26                 switch (*format_str)    
     27                 {
     28                 case '-':    case '+':    case '0':    case ' ':    case '#':
     29                 case '1':    case '2':    case '3':    case '4':    case '5':
     30                 case '6':    case '7':    case '8':    case '9':    case '.':
     31                 case 'L':    case 'h':
     32                     //*fp++ = *format_str;
     33                     break;
     34                 case 'l':    // Source file line number
     35                     len = sprintf_s (format,128,"%d",__LINE__);
     36                     _block.Write(format,len);
     37                     break;
     38                 case 'N':             // Source file name
     39                     len = sprintf_s (format,128,"%s",__FILE__);
     40                     _block.Write(format,len);
     41                     break;
     42                 case 'n':             // Program name
     43                     len = sprintf_s (format,128,"%s","<unknown>");
     44                     _block.Write(format,len);
     45                     break;
     46                 case 'P':             // Process ID
     47                     len = sprintf_s (format,128,"%d", (int)getpid());
     48                     _block.Write(format,len);
     49                     break;
     50                 case 'T': // Format the timestamp in hour:minute:sec:usec format.
     51                     {
     52                         std::string strColTime = Tools::GetCurrentTime();
     53                         _block.Write(strColTime.c_str(), strColTime.length());
     54                     }
     55                     break;
     56                 case 't': // Format thread id.
     57                     len = sprintf_s (format,128,"%d", boost::this_thread::get_id());
     58                     _block.Write(format,len);
     59                     break;
     60                 case 's':   
     61                     {// String
     62                         char *str1 = va_arg (argp, char *);
     63                         _block.Write(str1,strlen(str1));
     64                         break;
     65                     }
     66                 case 'd': 
     67                 case 'i': 
     68                 case 'o':
     69                 case 'u': 
     70                 case 'x': 
     71                 case 'X':
     72                     len = sprintf_s (format,128,"%d",va_arg (argp, int));
     73                     _block.Write(format,len);
     74                     break;
     75                 default:
     76                     _block.Write(format_str,1);
     77                     break;
     78                 }
     79             }
     80             ++format_str;
     81         }
     82         //末尾结束符号
     83         char c('');
     84         _block.Write(&c,1);
     85         //输出缓冲区
     86         if (BIT_ENABLED (_flags,STDERR)) // This is taken care of by our caller.
     87         {
     88             int const fwrite_result = fprintf (stderr,"%s",_block.Base());
     89             ::fflush (stderr);
     90         }
     91         if (BIT_ENABLED (_flags,OSTREAM))
     92         {
     93             if (_ostream != NULL)
     94             {
     95                 *_ostream << _block.Base();
     96                 _ostream->flush();
     97             }
     98         }
     99         va_end (argp);
    100     }
    View Code  
  • 相关阅读:
    常用的排序方法
    mongoose 操作
    formidable使用
    cors跨域(支持cookie跨域) node后台 express
    mongoose Schema写法
    vue生命周期钩子 (mounted 加载数据没有缓存用 activated 配合keep-alive组件)
    vue路由跳转 页面回到顶部
    RESTful风格的路由设计
    router-link 绑定事件不生效
    axios的Content-Type类型导致后台无法解析数据
  • 原文地址:https://www.cnblogs.com/hgwang/p/9304944.html
Copyright © 2020-2023  润新知