29_创建日志类

日志

将控制台上输出的信息利用任务线程写入到文件中,或自定义写入数据库等容器中

celllog.hpp

#ifndef _CELL_LOG_HPP_
#define _CELL_LOG_HPP_

#include"CELL.hpp"
#include"CELLTask.hpp"
#include<ctime>
class CELLLog
{
private:
    CELLLog()
    {
        _taskServer.Start();
    }

    ~CELLLog()
    {
        _taskServer.Close();
        if (_logFile)
        {
            Info("CELLLog fclose(_logFile)\n");
            fclose(_logFile);
            _logFile = nullptr;
        }
    }

public:
    static CELLLog& Instance()  //单例模式
    {
        static  CELLLog sLog;
        return sLog;
    }

    void setLogPath(const char* logPath, const char* mode)   //设置日志路径
    {
        if (_logFile)
        {
            Info("CELLLog::setLogPath _logFile != nullptr\n");
            fclose(_logFile);
            _logFile = nullptr;
        }


        _logFile = fopen(logPath, mode);
        if (_logFile)
        {
            Info("CELLLog::setLogPath success,<%s,%s>\n", logPath, mode);
        }
        else {
            Info("CELLLog::setLogPath failed,<%s,%s>\n", logPath, mode);
        }
    }

    static void Info(const char* pStr)  //输出日志
    {
        CELLLog* pLog = &Instance();
        pLog->_taskServer.addTask([=]() {
            if (pLog->_logFile)
            {
                auto t = system_clock::now();
                auto tNow = system_clock::to_time_t(t);
                //fprintf(pLog->_logFile, "%s", ctime(&tNow));
                std::tm* now = std::gmtime(&tNow);
                fprintf(pLog->_logFile, "%s", "Info ");
                fprintf(pLog->_logFile, "[%d-%d-%d %d:%d:%d]", now->tm_year + 1900, now->tm_mon + 1, now->tm_mday, now->tm_hour, now->tm_min, now->tm_sec);
                fprintf(pLog->_logFile, "%s", pStr);
                fflush(pLog->_logFile);
            }
            printf("%s", pStr);
            });
    }

    template<typename ...Args>
    static void Info(const char* pformat, Args ... args)  //按照格式输出日志
    {
        CELLLog* pLog = &Instance();
        pLog->_taskServer.addTask([=]() {
            if (pLog->_logFile)
            {
                auto t = system_clock::now();
                auto tNow = system_clock::to_time_t(t);
                //fprintf(pLog->_logFile, "%s", ctime(&tNow));
                std::tm* now = std::gmtime(&tNow);
                fprintf(pLog->_logFile, "%s", "Info ");
                fprintf(pLog->_logFile, "[%d-%d-%d %d:%d:%d]", now->tm_year + 1900, now->tm_mon + 1, now->tm_mday, now->tm_hour, now->tm_min, now->tm_sec);
                fprintf(pLog->_logFile, pformat, args...);
                fflush(pLog->_logFile);
            }
            printf(pformat, args...);
            });
    }
private:
    FILE* _logFile = nullptr;
    CELLTaskServer _taskServer;
};




#endif

其它文件中的控制台输出都调用该日志类的输出

这次修改遇到了头文件循环引用问题,cell.h文件和其它.hpp文件可能需要修改

分离网络环境启动与关闭

可能需要启动多个easytcpserver,不能直接把网络环境的启动和关闭放在easytcpserver类中,那么创建多个easytcpserver时,会进行多次的启动和关闭

cellnetwork.cpp

#ifndef _CELL_NET_WORK_HPP_
#define _CELL_NET_WORK_HPP_

#include"CELL.hpp"

class CELLNetWork
{
private:
    CELLNetWork()
    {
#ifdef _WIN32
        //启动Windows socket 2.x环境
        WORD ver = MAKEWORD(2, 2);
        WSADATA dat;
        WSAStartup(ver, &dat);
#endif

#ifndef _WIN32
        //if (signal(SIGPIPE, SIG_IGN) == SIG_ERR)
        //  return (1);
        //忽略异常信号,默认情况会导致进程终止
        signal(SIGPIPE, SIG_IGN);
#endif
    }

    ~CELLNetWork()
    {
#ifdef _WIN32
        //清除Windows socket环境
        WSACleanup();
#endif
    }
public:
    static void Init()
    {
        static  CELLNetWork obj;   //单例模式,只会创建一个obj对象,同理只会进行一次析构
    }
};

#endif // !_CELL_NET_WORK_HPP_

easytcpserver.hpp的修改

“`c++
#ifndef _EasyTcpServer_hpp_
#define _EasyTcpServer_hpp_

#include"CELL.hpp"
#include"CELLClient.hpp"
#include"CELLServer.hpp"
#include"INetEvent.hpp"
#include"CELLNetWork.hpp"

#include<thread>
#include<mutex>
#include<atomic>

class EasyTcpServer : public INetEvent
{
//初始化Socket
SOCKET InitSocket()
{
CELLNetWork::Init();
if (INVALID_SOCKET != _sock)
{
CELLLog::Info("warning, initSocket close old socket<%d>…\n", (int)_sock);
Close();
}
_sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (INVALID_SOCKET <span class="text-highlighted-inline" style="background-color: #fffd38;"> _sock)
{
CELLLog::Info("error, create socket failed…\n");
}
else {
CELLLog::Info("create socket<%d> success…\n", (int)_sock);
}
return _sock;
}</span>

<pre><code>//关闭Socket
void Close()
{
CELLLog::Info("EasyTcpServer.Close begin\n");
_thread.Close();
if (_sock != INVALID_SOCKET)
{
for (auto s : _cellServers)
{
delete s;
}
_cellServers.clear();
//关闭套节字socket
</code></pre>

#ifdef _WIN32
closesocket(_sock);
#else
close(_sock);
#endif
_sock = INVALID_SOCKET;
}
CELLLog::Info("EasyTcpServer.Close end\n");
}

};

#endif // !<em>EasyTcpServer_hpp</em>

“`

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top