<强>一、服务器端日志与客户端日志的区别强>
在正式讲解之前,我们先来看一个日志类的实现方法,这个日志类也是代表着大多数客户端日志的主流写法:
<代码>/* * * @desc:程序运行日志类,log.h * @author: zhangyl * @date: 2017.01.17 * */的ifndef __LOG_H__ #定义__LOG_H__ # ifdef _ZYL_LOG_ #定义LogInfo (…)日志:GetInstance ()。AddLog(“信息”,__FILE__、__LINE__ __FUNCSIG__, __VA_ARGS__) #定义LogWarning (…)日志:GetInstance ()。AddLog(“警告”,__FILE__、__LINE__ __FUNCSIG__, __VA_ARGS__) #定义LogError (…)日志:GetInstance ()。AddLog(“错误”,__FILE__、__LINE__ __FUNCSIG__, __VA_ARGS__) 其他# #定义LogInfo(…)(0)(空白) #定义LogError(…)(0)(空白) # endif 类日志 { 公众: 静态Log&GetInstance (); bool AddLog (const char * pszLevel, const char * pszFile, int lineNo, const char * pszFuncSig, char * pszFmt,…); 私人: 日志(); ~的日志(); 日志(const Log&); Log&运算符=(const Log&); 私人: 文件* m_file; }; # endif//! __LOG_H__ 代码>
<代码>/* * * @desc:程序运行日志类,log.cpp * @author: zhangyl * @date: 2017.01.17 * */# include & lt; time.h> # include & lt; stdio.h> # include & lt; stdarg.h> # include“Log.h” Log&日志:GetInstance () { 静态日志日志; 返回日志; } bool日志::AddLog (const char * pszLevel, const char * pszFile, int lineNo, const char * pszFuncSig, char * pszFmt,…) { 如果(m_file==NULL) 返回错误; char tmp (8192 * 10)={0}; va_list va;//定义一个va_list型的变量,这个变量是指向参数的指针。 va_start (va pszFmt);//用va_start宏初始化变量,这个宏的第二个参数是第一个可变参数的前一个参数,是一个固定的参数 _vsnprintf (tmp ARRAYSIZE (tmp) pszFmt, va);//注意,不要漏掉前面的_ va_end (va); time_t现在=(空); struct tm * tmstr=本地时间(和现在); 字符内容(8192 * 10 + 256)={0}; sprintf_s(内容、ARRAYSIZE(内容),“[% 04 d - % 2 d - % 2 d % 2 d: % 2 d: % 2 d] [% s] [0 x % 04] [% s % d % s): % s \ r \ n”, tmstr→tm_year + 1900, tmstr→tm_mon + 1, tmstr→tm_mday, tmstr→tm_hour, tmstr→tm_min, tmstr→tm_sec, pszLevel, GetCurrentThreadId (), pszFile, lineNo, pszFuncSig, tmp); 如果(写入文件(内容、strlen(内容)1,m_file) !=1) 返回错误; 。fflush (m_file); 返回true; } 日志:记录() { time_t现在=(空); struct tm * tmstr=本地时间(和现在); char文件名[256]; sprintf_s(文件名,ARRAYSIZE(文件名),“% 04 d % 2 d % 2 d % 2 d % 2 d % 02 d.runlog”, tmstr→tm_year + 1900, tmstr→tm_mon + 1, tmstr→tm_mday, tmstr→tm_hour, tmstr→tm_min, tmstr→tm_sec); m_file=fopen(文件名,“+”); } 日志::~的日志() { 如果(m_file !=NULL) 文件关闭(m_file); }代码>
这个日志类的定义和实现代码节选自我的一款12306刷票软件,如果需要使用这个类的话包含Log.h头文件,然后使用宏:LogInfo/LogWarning LogError这三个宏就可以了。示例如下:
<代码>字符串strResponse; 字符串strCookie=氨?”; strCookie +=m_strCookies; 如果(! HttpRequest (osURL.str () .c_str (), strResponse,真的,strCookie.c_str (), NULL,假的,10)) { LogError (“QueryTickets2失败”); 返回错误; }代码>
这个日志类,每次输出一行,一行中输出时间,日志级别,线程id、文件名,行号,函数签名和自定义的错误信息,演示如下:
<代码>[2017-02-16 17:30:08][信息][0 x0e7c] [f: \ mycode \ hack12306 \ 12306 \ client12306演示。cpp: 1401 bool __thiscall Client12306:: HttpRequest (const char *,类std:: basic_string,类std:: allocator 比;,,bool, const char *, const char *, bool, int)] http响应:{“validateMessagesShowId”:“_validatorMessage”,“状态”:真的,“httpstatus”: 200年,“数据”:{“loginAddress”:“10.1.232.219”、“otherMsg”:“”,“loginCheck”:“Y”},“消息”:[],“validateMessages”: {}} [2017-02-16 17:30:08][信息][0 x0e7c] [f: \ mycode \ hack12306 \ 12306 \ client12306演示。cpp: 1379 bool __thiscall Client12306:: HttpRequest (const char *,类std:: basic_string 服务器编程心得(五)——如何编写高性能日志