文档章节

http客户端-基于boost开发

o
 osc_odyg6b92
发布于 2018/07/13 14:54
字数 3535
阅读 11
收藏 0

「深度学习福利」大神带你进阶工程师,立即查看>>>

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\n"), 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\n", 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\n", 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\r\n";
 96     getContent += "Host: " + pTask->_info.host + "\r\n";
 97     getContent += "Connection: keep-alive\r\n";
 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\r\n";
 99     getContent += "Accept-Encoding: gzip, deflate\r\n";
100     getContent += "Accept-Language: zh-CN,zh;q=0.8\r\n\r\n";
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 \n", 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 \n", 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\n, %s \n", pTask->_url.c_str() ,cRnrn));
189         }
190         delete cRnrn;
191     }
192     else
193     {
194         //没有收到\r\n\r\n,则表明头还没收完全
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 \n", 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 != '\0')
 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('\0');
 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  

 

o
粉丝 1
博文 500
码字总数 0
作品 0
私信 提问
加载中
请先登录后再评论。
Netty那点事(三)Channel与Pipeline

Channel是理解和使用Netty的核心。Channel的涉及内容较多,这里我使用由浅入深的介绍方法。在这篇文章中,我们主要介绍Channel部分中Pipeline实现机制。为了避免枯燥,借用一下《盗梦空间》的...

黄亿华
2013/11/24
2W
22
beego API开发以及自动化文档

beego API开发以及自动化文档 beego1.3版本已经在上个星期发布了,但是还是有很多人不了解如何来进行开发,也是在一步一步的测试中开发,期间QQ群里面很多人都问我如何开发,我的业余时间实在...

astaxie
2014/06/25
2.7W
22
树莓派(Raspberry Pi):完美的家用服务器

自从树莓派发布后,所有在互联网上的网站为此激动人心的设备提供了很多有趣和具有挑战性的使用方法。虽然这些想法都很棒,但树莓派( RPi )最明显却又是最不吸引人的用处是:创建你的完美家用...

异次元
2013/11/09
7K
8
代码生成器--Codgen

Codgen是一个基于数据库元数据模型,使用freemarker模板引擎来构建输出的代码生成器。freemarker的数据模型结构通常来说都是一个Map树状结构模型,codgen也不例外,它的数据模型这棵树的根节...

黄天政
2013/01/29
1.4W
2
Web开发组件管理器--Bower

Bower 是一个针对Web开发的包管理器。该工具主要用来帮助用户轻松安装CSS、JavaScript、图像等相关包,并管理这些包之间的依赖。 功能有些类似于Component。不同之处是,Component是围绕Git...

匿名
2013/02/01
1.2W
2

没有更多内容

加载失败,请刷新页面

加载更多

SwaggerUI看烦了,IGeekFan.AspNetCore.Knife4jUI 帮你换个新皮肤

背景 好像是上周四,看到微信群有人说java有轮子swagger-bootstrap-ui,而c#,就是找不到。 于是我一看,就说大话:“这个只是一套UI,他这个有开源地址么” 被@at说:你试试... 当天晚上就把...

张善友
今天
0
0
字符串驻留是个什么鬼!

先看下面这段代码 >>> a = 'apple' >>> b = 'apple' >>> a is b True 返回结果看起来没毛病 再来看这段: >>> a = 'apple!' >>> b = 'apple!' >>> a is b False 这个结果是不是有点诡异 前后......

谭庆波
昨天
0
0
golang包的日常(2)——log包

普通使用 log包定义了Logger类型,该类型提供了一些格式化输出的方法。 log包中预定义了一个标准logger对象std,使我们可以直接调用函数来打印日志,默认是标准错误输出(Stderr),打印到终...

osc_dg21zk4i
7分钟前
0
0
近10年全国高校双青人才排名TOP50,苏州大学表现抢眼

转眼又到了每年的杰青和优青项目评选的日子,作为高校人才水平的重要评判标准,每年高校的自然科学基金项目数都是一个非常重要的指标。当然,由于杰青每年只有200个名额,而国内有3000多所高...

科研菌
昨天
0
0
意派Epub360丨从制作到推广,H5页面如何刷屏?

不是所有H5最终都可以引爆朋友圈,也不是所有未能刷屏的H5都不够优秀。如何找到爆点、如何制作实现、如何传播转化……每一个要点都可能是影响刷屏的关键。即使是再资深的营销专家,也很难在H...

牙牙乐牙牙乐
7分钟前
0
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部