{"id":79940,"date":"2026-03-03T19:50:57","date_gmt":"2026-03-03T11:50:57","guid":{"rendered":"https:\/\/www.wsisp.com\/helps\/79940.html"},"modified":"2026-03-03T19:50:57","modified_gmt":"2026-03-03T11:50:57","slug":"c%e9%a1%b9%e7%9b%ae%ef%bc%9a%e5%9f%ba%e4%ba%8elinux%e7%b3%bb%e7%bb%9f%e5%92%8ctcp%e5%8d%8f%e8%ae%ae%e7%9a%84%e8%bf%9c%e7%a8%8b%e5%91%bd%e4%bb%a4%e8%a1%8c%e7%bb%88%e7%ab%af","status":"publish","type":"post","link":"https:\/\/www.wsisp.com\/helps\/79940.html","title":{"rendered":"C++\u9879\u76ee\uff1a\u57fa\u4e8eLinux\u7cfb\u7edf\u548cTCP\u534f\u8bae\u7684\u8fdc\u7a0b\u547d\u4ee4\u884c\u7ec8\u7aef"},"content":{"rendered":"<p>\u00a0 \u00a0 \u00a0 \u00a0 \u524d\u9762\u6211\u4eec\u57fa\u4e8eTCP\u5b9e\u73b0\u4e86\u7b80\u5355\u4e86\u4e92\u52a8\u670d\u52a1\u5668\u3002\u4f46\u662f\u90a3\u662f\u8fdc\u8fdc\u4e0d\u591f\u7684&#xff0c;\u672c\u671f\u6211\u4eec\u5c06\u5b9e\u73b0\u4e00\u4e2a\u57fa\u4e8eTCP\u7684\u8fdc\u7a0b\u547d\u4ee4\u884c\u7ec8\u7aef<\/p>\n<p>\u00a0 \u00a0 \u00a0 \u00a0 \u76f8\u5173\u4ee3\u7801\u63d0\u4ea4\u81f3\u4f5c\u8005\u7684\u4e2a\u4ebagitee&#xff1a;\u697c\u7530\u8389\u5b50\/Linux\u5b66\u4e60\u559c\u6b22\u8bf7\u70b9\u4e2a\u8d5e\u8c22\u8c22<\/p>\n<p id=\"main-toc\">\u76ee\u5f55<\/p>\n<p id=\"%E6%97%A5%E5%BF%97-toc\" style=\"margin-left:0px\">\u65e5\u5fd7<\/p>\n<p id=\"%E7%BA%BF%E7%A8%8B%E6%B1%A0%E7%9B%B8%E5%85%B3-toc\" style=\"margin-left:0px\">\u7ebf\u7a0b\u6c60\u76f8\u5173<\/p>\n<p id=\"%E7%BD%91%E7%BB%9C%E5%AE%A2%E6%88%B7%E7%AB%AF-toc\" style=\"margin-left:0px\">\u7f51\u7edc\u5ba2\u6237\u7aef<\/p>\n<p id=\"%E5%91%BD%E4%BB%A4-toc\" style=\"margin-left:0px\">\u547d\u4ee4<\/p>\n<p id=\"%E6%9C%8D%E5%8A%A1%E5%99%A8-toc\" style=\"margin-left:0px\">\u670d\u52a1\u5668<\/p>\n<p id=\"%C2%A0%20%C2%A0%20%C2%A0%20%C2%A0%20%E6%9C%8D%E5%8A%A1%E5%99%A8%E4%BB%A3%E7%A0%81-toc\" style=\"margin-left:40px\">\u00a0 \u00a0 \u00a0 \u00a0 \u670d\u52a1\u5668\u4ee3\u7801<\/p>\n<p id=\"%C2%A0%20%C2%A0%20%C2%A0%20%C2%A0%20%E6%9C%8D%E5%8A%A1%E5%99%A8%E8%BF%90%E8%A1%8C-toc\" style=\"margin-left:40px\">\u00a0 \u00a0 \u00a0 \u00a0 \u670d\u52a1\u5668\u8fd0\u884c<\/p>\n<p id=\"%C2%A0%20%C2%A0%20%C2%A0%20%C2%A0%20%E5%AE%A2%E6%88%B7%E7%AB%AF%E8%BF%90%E8%A1%8C-toc\" style=\"margin-left:40px\">\u00a0 \u00a0 \u00a0 \u00a0 \u5ba2\u6237\u7aef\u8fd0\u884c<\/p>\n<p id=\"%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%E6%B5%8B%E8%AF%95-toc\" style=\"margin-left:40px\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u6d4b\u8bd5<\/p>\n<hr id=\"hr-toc\" \/>\n<h2 id=\"%E6%97%A5%E5%BF%97\">\u65e5\u5fd7<\/h2>\n<p>#pragma once<\/p>\n<p>#include &lt;iostream&gt;<br \/>\n#include &lt;pthread.h&gt;<br \/>\n#include &lt;cstdio&gt;<br \/>\n#include &lt;string&gt;<br \/>\n#include &lt;memory&gt;<br \/>\n#include &lt;sstream&gt;<br \/>\n#include &lt;chrono&gt;<br \/>\n#include &lt;iomanip&gt;<br \/>\n#include &lt;ctime&gt;<br \/>\n#include &lt;unistd.h&gt;<br \/>\n#include &lt;filesystem&gt; \/\/ C&#043;&#043;17<br \/>\n#include &lt;fstream&gt;<br \/>\n\/\/RAII\u98ce\u683c\u4ee3\u7801&#xff1a;\u8d44\u6e90\u83b7\u53d6\u5373\u521d\u59cb\u5316<br \/>\n\/\/ \u4e92\u65a5\u9501\u7c7b&#xff0c;\u5c01\u88c5\u4e86pthread_mutex_t<br \/>\nclass Mutex<br \/>\n{<br \/>\n    public:<br \/>\n        Mutex()<br \/>\n        {<br \/>\n            pthread_mutex_init(&amp;_lock, nullptr);<br \/>\n        }<br \/>\n        void Lock()<br \/>\n        {<br \/>\n            pthread_mutex_lock(&amp;_lock);<br \/>\n        }<br \/>\n        pthread_mutex_t *Ptr()<br \/>\n        {<br \/>\n            return &amp;_lock;<br \/>\n        }<br \/>\n        void Unlock()<br \/>\n        {<br \/>\n            pthread_mutex_unlock(&amp;_lock);<br \/>\n        }<br \/>\n        ~Mutex()<br \/>\n        {<br \/>\n            pthread_mutex_destroy(&amp;_lock);<br \/>\n        }<br \/>\n    private:<br \/>\n        pthread_mutex_t _lock;<br \/>\n};<\/p>\n<p>class LockGuard \/\/ RAII\u98ce\u683c\u4ee3\u7801<br \/>\n{<br \/>\n    public:<br \/>\n        LockGuard(Mutex &amp;lock):_lockref(lock)<br \/>\n        {<br \/>\n            _lockref.Lock();<br \/>\n        }<br \/>\n        ~LockGuard()<br \/>\n        {<br \/>\n            _lockref.Unlock();<br \/>\n        }<br \/>\n    private:<br \/>\n        Mutex &amp;_lockref;<br \/>\n};<\/p>\n<p>\/\/\u65e5\u5fd7\u672c\u4f53<br \/>\nnamespace Logger<br \/>\n{<br \/>\n    enum class LogLevel<br \/>\n    {<br \/>\n        INFO,    \/\/\/&lt; \u4fe1\u606f\u6027\u6d88\u606f&#xff0c;\u8bb0\u5f55\u5e94\u7528\u7a0b\u5e8f\u7684\u6b63\u5e38\u8fd0\u884c\u72b6\u6001&#xff08;\u5982\u542f\u52a8\u3001\u914d\u7f6e\u52a0\u8f7d\u7b49&#xff09;<br \/>\n        WARNING, \/\/\/&lt; \u8b66\u544a&#xff0c;\u8868\u793a\u6f5c\u5728\u7684\u95ee\u9898\u6216\u975e\u9884\u671f\u7684\u60c5\u5f62&#xff0c;\u4f46\u5e94\u7528\u7a0b\u5e8f\u4ecd\u80fd\u7ee7\u7eed\u8fd0\u884c<br \/>\n        ERROR,   \/\/\/&lt; \u9519\u8bef&#xff0c;\u8868\u793a\u53d1\u751f\u4e86\u4e25\u91cd\u7684\u64cd\u4f5c\u5931\u8d25&#xff0c;\u4f46\u4e0d\u5f71\u54cd\u6574\u4e2a\u5e94\u7528\u7a0b\u5e8f\u7684\u7ee7\u7eed\u8fd0\u884c<br \/>\n        FATAL,   \/\/\/&lt; \u81f4\u547d\u9519\u8bef&#xff0c;\u8868\u793a\u4e25\u91cd\u7684\u6545\u969c&#xff0c;\u901a\u5e38\u4f1a\u5bfc\u81f4\u5e94\u7528\u7a0b\u5e8f\u7ec8\u6b62<br \/>\n        DEBUG    \/\/\/&lt; \u8c03\u8bd5\u4fe1\u606f&#xff0c;\u7528\u4e8e\u5f00\u53d1\u548c\u6392\u9519\u9636\u6bb5&#xff0c;\u8bb0\u5f55\u8be6\u7ec6\u7684\u5185\u90e8\u72b6\u6001\u6216\u6d41\u7a0b<br \/>\n    };<br \/>\n    std::string LogLevelToString(LogLevel level)<br \/>\n    {<br \/>\n        switch (level)<br \/>\n        {<br \/>\n            case LogLevel::INFO:<br \/>\n                return &#034;INFO&#034;;<br \/>\n            case LogLevel::WARNING:<br \/>\n                return &#034;WARNING&#034;;<br \/>\n            case LogLevel::ERROR:<br \/>\n                return &#034;ERROR&#034;;<br \/>\n            case LogLevel::FATAL:<br \/>\n                return &#034;FATAL&#034;;<br \/>\n            case LogLevel::DEBUG:<br \/>\n                return &#034;DEBUG&#034;;<br \/>\n            default:<br \/>\n                return &#034;UNKNOWN&#034;;<br \/>\n        }<br \/>\n    }<br \/>\n    std::string GetCurrentDateTime()<br \/>\n    {<br \/>\n        auto now &#061; std::chrono::system_clock::now();<br \/>\n        std::time_t now_c &#061; std::chrono::system_clock::to_time_t(now);<\/p>\n<p>        std::tm tm_info;                      \/\/ \u7528\u6237\u63d0\u4f9b\u7684\u7f13\u51b2\u533a<br \/>\n        localtime_r(&amp;now_c, &amp;tm_info);         \/\/ POSIX \u7ebf\u7a0b\u5b89\u5168\u51fd\u6570<\/p>\n<p>        std::ostringstream oss;<br \/>\n        oss &lt;&lt; std::put_time(&amp;tm_info, &#034;%Y-%m-%d %H:%M:%S&#034;);<br \/>\n        return oss.str();<br \/>\n    }<br \/>\n    \/\/ \u8f93\u51fa\u89d2\u5ea6 &#8212; \u5237\u65b0\u7b56\u7565<br \/>\n    \/\/ 1. \u663e\u793a\u5668\u6253\u5370<br \/>\n    \/\/ 2. \u6587\u4ef6\u5199\u5165<\/p>\n<p>    \/\/ \u65e5\u5fd7\u7684\u751f\u6210&#xff1a;<br \/>\n    \/\/ 1. \u6784\u5efa\u65e5\u5fd7\u5b57\u7b26\u4e32<br \/>\n    \/\/ 2. \u6839\u636e\u4e0d\u540c\u7684\u7b56\u7565&#xff0c;\u8fdb\u884c\u5237\u65b0<\/p>\n<p>    \/\/\u7b56\u7565\u6a21\u5f0f\u63a5\u53e3<br \/>\n    class LogStrategy<br \/>\n    {<br \/>\n    public:<br \/>\n        virtual void LogRefresh(const std::string &amp;message) &#061; 0;<br \/>\n        virtual ~LogStrategy() &#061; default;<br \/>\n    };<br \/>\n    \/\/ \u63a7\u5236\u53f0\u65e5\u5fd7\u5237\u65b0\u7b56\u7565, \u65e5\u5fd7\u5c06\u6765\u8981\u5411\u663e\u793a\u5668\u6253\u5370<br \/>\n    class ConsoleStrategy : public LogStrategy<br \/>\n    {<br \/>\n    public:<br \/>\n        \/\/ \u663e\u793a\u5668\u6253\u5370\u7b56\u7565\u5237\u65b0<br \/>\n        void LogRefresh(const std::string &amp;message) override<br \/>\n        {<br \/>\n            LockGuard lockguard(_mutex);<br \/>\n            std::cerr &lt;&lt; message &lt;&lt; std::endl; \/\/ ??<br \/>\n        }<br \/>\n        ~ConsoleStrategy()<br \/>\n        {<br \/>\n        }<\/p>\n<p>    private:<br \/>\n        Mutex _mutex;<br \/>\n    };<\/p>\n<p>    const std::string defaultpath &#061; &#034;.\/log&#034;;<br \/>\n    const std::string defaultfilename &#061; &#034;log.txt&#034;;<br \/>\n    namespace fs &#061; std::filesystem;<\/p>\n<p>    \/\/ \u6587\u4ef6\u7b56\u7565<br \/>\n    class FileLogStrategy : public LogStrategy<br \/>\n    {<br \/>\n    public:<br \/>\n        FileLogStrategy(const std::string &amp;path &#061; defaultpath, const std::string &amp;name &#061; defaultfilename)<br \/>\n            : _logpath(path),<br \/>\n              _logfilename(name)<br \/>\n        {<br \/>\n            if (std::filesystem::exists(_logpath))<br \/>\n                return;<\/p>\n<p>            try<br \/>\n            {<br \/>\n                std::filesystem::create_directories(_logpath);<br \/>\n            }<br \/>\n            catch(const std::filesystem::filesystem_error &amp;e)<br \/>\n            {<br \/>\n                std::cerr &lt;&lt; e.what() &lt;&lt; &#039;\\\\n&#039;;<br \/>\n            }<br \/>\n            if(!_logpath.empty()&amp;&amp;_logpath.back() !&#061; &#039;\/&#039;)<br \/>\n                _logpath &#043;&#061; &#039;\/&#039;;<br \/>\n        }<br \/>\n        \/\/ \u6587\u4ef6\u7b56\u7565\u5237\u65b0<br \/>\n        void LogRefresh(const std::string &amp;message) override<br \/>\n        {<br \/>\n            {<br \/>\n                std::string targetlogfile &#061; _logpath &#043;  _logfilename;<br \/>\n                LockGuard lockguard(_mutex);<br \/>\n                std::ofstream logFile(targetlogfile, std::ios::app);\/\/ \u4ee5\u8ffd\u52a0\u6a21\u5f0f\u6253\u5f00\u6587\u4ef6<br \/>\n                if (!logFile.is_open())<br \/>\n                {<br \/>\n                    std::cerr &lt;&lt; &#034;\u65e0\u6cd5\u6253\u5f00\u65e5\u5fd7\u6587\u4ef6: &#034; &lt;&lt; targetlogfile &lt;&lt; std::endl;<br \/>\n                    return;<br \/>\n                }<br \/>\n                logFile &lt;&lt; message &lt;&lt; &#034;\\\\n&#034;;<br \/>\n                logFile.close();<br \/>\n            }<\/p>\n<p>        }<\/p>\n<p>        ~FileLogStrategy()<br \/>\n        {<br \/>\n        }<\/p>\n<p>    private:<br \/>\n        std::string _logpath;<br \/>\n        std::string _logfilename;<br \/>\n        Mutex _mutex;<br \/>\n    };<\/p>\n<p>    \/\/ \u6839\u636e\u65e5\u5fd7\u7b49\u7ea7\u5206\u7c7b\u4fdd\u5b58\u7684\u7b56\u7565\u7c7b<br \/>\n    class LevelFileLogStrategy : public LogStrategy {<br \/>\n    public:<br \/>\n        \/**<br \/>\n         * &#064;brief \u6784\u9020\u51fd\u6570&#xff0c;\u6307\u5b9a\u65e5\u5fd7\u6839\u76ee\u5f55<br \/>\n         * &#064;param log_dir \u5b58\u653e\u7b49\u7ea7\u65e5\u5fd7\u6587\u4ef6\u7684\u76ee\u5f55&#xff0c;\u9ed8\u8ba4\u4e3a &#034;.\/logs&#034;<br \/>\n         *\/<br \/>\n        LevelFileLogStrategy(const std::string &amp;log_dir &#061; &#034;.\/logs&#034;) : _log_dir(log_dir) {<br \/>\n            \/\/ \u786e\u4fdd\u76ee\u5f55\u5b58\u5728<br \/>\n            if (!std::filesystem::exists(_log_dir)) {<br \/>\n                std::filesystem::create_directories(_log_dir);<br \/>\n            }<br \/>\n            \/\/ \u89c4\u8303\u5316\u76ee\u5f55\u8def\u5f84&#xff0c;\u672b\u5c3e\u6dfb\u52a0 &#039;\/&#039;<br \/>\n            if (!_log_dir.empty() &amp;&amp; _log_dir.back() !&#061; &#039;\/&#039;) {<br \/>\n                _log_dir &#043;&#061; &#039;\/&#039;;<br \/>\n            }<br \/>\n        }<\/p>\n<p>        \/**<br \/>\n         * &#064;brief \u5237\u65b0\u65e5\u5fd7&#xff1a;\u6839\u636e\u7b49\u7ea7\u5199\u5165\u5bf9\u5e94\u6587\u4ef6<br \/>\n         * &#064;param message \u5b8c\u6574\u7684\u65e5\u5fd7\u6d88\u606f&#xff08;\u683c\u5f0f\u7531 Logger::LogMessage \u751f\u6210&#xff09;<br \/>\n         *\/<br \/>\n        void LogRefresh(const std::string &amp;message) override {<br \/>\n            \/\/ 1. \u4ece\u6d88\u606f\u4e2d\u63d0\u53d6\u65e5\u5fd7\u7b49\u7ea7<br \/>\n            LogLevel level &#061; extractLogLevel(message);<br \/>\n            \/\/ 2. \u6784\u9020\u5bf9\u5e94\u7684\u6587\u4ef6\u540d&#xff08;\u4f8b\u5982&#xff1a;INFO.log&#xff09;<br \/>\n            std::string filename &#061; _log_dir &#043; LogLevelToString(level) &#043; &#034;.log&#034;;<\/p>\n<p>            \/\/ 3. \u7ebf\u7a0b\u5b89\u5168\u5730\u8ffd\u52a0\u5199\u5165\u6587\u4ef6<br \/>\n            LockGuard lockguard(_mutex);<br \/>\n            std::ofstream logFile(filename, std::ios::app);<br \/>\n            if (!logFile.is_open()) {<br \/>\n                std::cerr &lt;&lt; &#034;\u65e0\u6cd5\u6253\u5f00\u65e5\u5fd7\u6587\u4ef6: &#034; &lt;&lt; filename &lt;&lt; std::endl;<br \/>\n                return;<br \/>\n            }<br \/>\n            logFile &lt;&lt; message &lt;&lt; &#034;\\\\n&#034;;<br \/>\n            logFile.close();<br \/>\n        }<\/p>\n<p>    private:<br \/>\n        std::string _log_dir;      \/\/ \u65e5\u5fd7\u6839\u76ee\u5f55<br \/>\n        Mutex _mutex;              \/\/ \u6587\u4ef6\u5199\u5165\u4e92\u65a5\u9501<\/p>\n<p>        \/**<br \/>\n         * &#064;brief \u4ece\u65e5\u5fd7\u6d88\u606f\u4e2d\u89e3\u6790\u51fa\u7b49\u7ea7<br \/>\n         * &#064;param msg \u5b8c\u6574\u65e5\u5fd7\u6d88\u606f&#xff0c;\u683c\u5f0f\u4e3a &#034;[\u65f6\u95f4][\u7b49\u7ea7][PID][\u6587\u4ef6:\u884c\u53f7] \u7528\u6237\u5185\u5bb9&#034;<br \/>\n         * &#064;return \u5bf9\u5e94\u7684 LogLevel \u679a\u4e3e\u503c&#xff0c;\u89e3\u6790\u5931\u8d25\u65f6\u9ed8\u8ba4\u8fd4\u56de INFO<br \/>\n         *\/<br \/>\n        LogLevel extractLogLevel(const std::string &amp;msg) {<br \/>\n            \/\/ \u5bfb\u627e\u7b2c\u4e00\u4e2a &#039;]&#039; \u7684\u4f4d\u7f6e<br \/>\n            size_t first_close &#061; msg.find(&#039;]&#039;);<br \/>\n            if (first_close &#061;&#061; std::string::npos) {<br \/>\n                return LogLevel::INFO;   \/\/ \u683c\u5f0f\u9519\u8bef&#xff0c;\u9ed8\u8ba4 INFO<br \/>\n            }<br \/>\n            \/\/ \u5bfb\u627e\u7b2c\u4e8c\u4e2a &#039;[&#039; \u7684\u4f4d\u7f6e<br \/>\n            size_t second_open &#061; msg.find(&#039;[&#039;, first_close);<br \/>\n            if (second_open &#061;&#061; std::string::npos) {<br \/>\n                return LogLevel::INFO;<br \/>\n            }<br \/>\n            \/\/ \u5bfb\u627e\u7b2c\u4e8c\u4e2a &#039;]&#039; \u7684\u4f4d\u7f6e<br \/>\n            size_t second_close &#061; msg.find(&#039;]&#039;, second_open);<br \/>\n            if (second_close &#061;&#061; std::string::npos) {<br \/>\n                return LogLevel::INFO;<br \/>\n            }<br \/>\n            \/\/ \u63d0\u53d6\u7b49\u7ea7\u5b57\u7b26\u4e32&#xff08;\u5982 &#034;INFO&#034;&#xff09;<br \/>\n            std::string level_str &#061; msg.substr(second_open &#043; 1, second_close &#8211; second_open &#8211; 1);<\/p>\n<p>            \/\/ \u6620\u5c04\u5230 LogLevel \u679a\u4e3e<br \/>\n            if (level_str &#061;&#061; &#034;INFO&#034;)    return LogLevel::INFO;<br \/>\n            if (level_str &#061;&#061; &#034;WARNING&#034;) return LogLevel::WARNING;<br \/>\n            if (level_str &#061;&#061; &#034;ERROR&#034;)   return LogLevel::ERROR;<br \/>\n            if (level_str &#061;&#061; &#034;FATAL&#034;)   return LogLevel::FATAL;<br \/>\n            if (level_str &#061;&#061; &#034;DEBUG&#034;)   return LogLevel::DEBUG;<br \/>\n            return LogLevel::INFO;      \/\/ \u672a\u77e5\u7b49\u7ea7&#xff0c;\u9ed8\u8ba4 INFO<br \/>\n        }<br \/>\n    };<br \/>\n    class Logger<br \/>\n    {<br \/>\n        public:<br \/>\n            Logger()<br \/>\n            {}<br \/>\n            void UseConsoleStrategy()<br \/>\n            {<br \/>\n                _strategy &#061; std::make_unique&lt;ConsoleStrategy&gt;();<br \/>\n            }<br \/>\n            void UseFileStrategy()<br \/>\n            {<br \/>\n                _strategy &#061; std::make_unique&lt;FileLogStrategy&gt;();<br \/>\n            }<br \/>\n            void UseLevelFileStrategy(const std::string &amp;log_dir &#061; &#034;.\/logs&#034;)<br \/>\n            {<br \/>\n                _strategy &#061; std::make_unique&lt;LevelFileLogStrategy&gt;(log_dir);<br \/>\n            }<br \/>\n            void Debug(const std::string &amp;message)<br \/>\n            {<br \/>\n                if (_strategy!&#061; nullptr)<br \/>\n                {<br \/>\n                    _strategy-&gt;LogRefresh(&#034;[DEBUG] &#034; &#043; GetCurrentDateTime() &#043; &#034; &#8211; &#034; &#043; message);<br \/>\n                }<br \/>\n            }<br \/>\n            \/\/\u65e5\u5fd7\u5185\u5bb9<br \/>\n            \/\/\u4e00\u6761\u5b8c\u6574\u7684\u65e5\u5fd7\u4fe1\u606f&#061;&gt; [\u65e5\u5fd7\u7ea7\u522b] &#043; \u5f53\u524d\u65f6\u95f4 &#043; \u8fdb\u7a0bID &#043; \u6587\u4ef6\u540d &#043; \u884c\u53f7 &#043; \u65e5\u5fd7\u4fe1\u606f<br \/>\n            \/\/\u6211\u4eec\u60f3\u4ee5RAII\u5f62\u5f0f\u5237\u65b0\u65e5\u5fd7\u4fe1\u606f<br \/>\n            class LogMessage<br \/>\n            {<br \/>\n                public:<br \/>\n                    LogMessage(LogLevel level, const std::string &amp;filename, size_t line, Logger &amp;logger)<br \/>\n                        : _level(level), _filename(filename), _line(line),_logger(logger)<br \/>\n                    {<br \/>\n                        _cur_time &#061; GetCurrentDateTime();<br \/>\n                        _pid&#061;getpid();<br \/>\n                        \/\/ \u6784\u5efa\u65e5\u5fd7\u5de6\u534a\u90e8\u5206\u4fe1\u606f<br \/>\n                        std::stringstream oss;<br \/>\n                        oss &lt;&lt;&#034;[&#034;&lt;&lt;_cur_time&lt;&lt;&#034;]&#034;<br \/>\n                            &lt;&lt;&#034;[&#034;&lt;&lt;LogLevelToString(_level)&lt;&lt;&#034;]&#034;<br \/>\n                            &lt;&lt;&#034;[&#034;&lt;&lt;_pid&lt;&lt;&#034;]&#034;<br \/>\n                            &lt;&lt;&#034;[&#034; &lt;&lt; filename &lt;&lt; &#034;:&#034;<br \/>\n                            &lt;&lt; line &lt;&lt; &#034;]&#034;;<br \/>\n                        _LogInfo &#061; oss.str();<br \/>\n                    }<br \/>\n                    template&lt;typename T&gt;<br \/>\n                    LogMessage&amp; operator&lt;&lt;(const T&amp;info)<br \/>\n                    {<br \/>\n                        std::stringstream oss;<br \/>\n                        oss&lt;&lt; info;<br \/>\n                        _LogInfo &#043;&#061; oss.str();<br \/>\n                        return *this;<br \/>\n                    }<br \/>\n                    ~LogMessage()<br \/>\n                    {<br \/>\n                        if (_logger._strategy !&#061; nullptr)<br \/>\n                        {<br \/>\n                            _logger._strategy-&gt;LogRefresh(_LogInfo);<br \/>\n                        }<br \/>\n                    }<br \/>\n                private:<br \/>\n                    std::string _cur_time;<br \/>\n                    LogLevel _level;<br \/>\n                    pid_t _pid;<br \/>\n                    std::string _filename;<br \/>\n                    size_t _line;<br \/>\n                    std::string _LogInfo;<br \/>\n                    Logger &amp;_logger ;\/\/\u65b9\u4fbf\u8fdb\u884c\u540e\u7eed\u7b56\u7565\u65b9\u5f0f\u5237\u65b0<br \/>\n            };<br \/>\n            \/\/\u5bf9LogMessage\u8fdb\u884c()\u91cd\u8f7d<br \/>\n            \/\/\u5fc5\u987b\u7528\u62f7\u8d1d&#xff0c;\u5426\u5219\u4f1a\u5bfc\u81f4&lt;&lt;\u91cd\u8f7d\u7684\u65f6\u5019\u5185\u5bb9\u6d88\u5931<br \/>\n            LogMessage operator()(LogLevel level, const std::string filename, size_t line)<br \/>\n            {<br \/>\n                return LogMessage(level, filename, line, *this);<br \/>\n            }<br \/>\n            ~Logger()<br \/>\n            {}<br \/>\n        private:<br \/>\n            std::unique_ptr&lt;LogStrategy&gt; _strategy;<br \/>\n    };<br \/>\n    \/\/\u65e5\u5fd7\u5bf9\u8c61\u5168\u5c40\u4f7f\u7528<br \/>\n    Logger logger;<br \/>\n    #define ENABLE_LOG_CONSOLE() logger.UseConsoleStrategy()<br \/>\n    #define ENABLE_LOG_FILE() logger.UseFileStrategy()<br \/>\n    #define Log(level) logger(level, __FILE__, __LINE__)<br \/>\n    #define ENABLE_LOG_LEVEL_FILE(log_dir) logger.UseLevelFileStrategy(log_dir)<br \/>\n}<\/p>\n<h2 id=\"%E7%BA%BF%E7%A8%8B%E6%B1%A0%E7%9B%B8%E5%85%B3\">\u7ebf\u7a0b\u6c60\u76f8\u5173<\/h2>\n<p>\u00a0 \u00a0 \u00a0 \u00a0 Mutex.hpp<\/p>\n<p>#pragma once<\/p>\n<p>#include &lt;iostream&gt;<br \/>\n#include &lt;string&gt;<br \/>\n#include &lt;pthread.h&gt;<br \/>\n#include &#034;..\/Log.h&#034;<br \/>\nnamespace LockModule<br \/>\n{<br \/>\n    \/\/ \u5bf9\u9501\u8fdb\u884c\u5c01\u88c5&#xff0c;\u53ef\u4ee5\u72ec\u7acb\u4f7f\u7528<br \/>\n    class Mutex<br \/>\n    {<br \/>\n    public:<br \/>\n        \/\/ \u5220\u9664\u4e0d\u9700\u8981\u7684\u62f7\u8d1d\u548c\u8d4b\u503c<br \/>\n        Mutex(const Mutex &amp;) &#061; delete;<br \/>\n        const Mutex &amp;operator&#061;(const Mutex &amp;) &#061; delete;<\/p>\n<p>        \/\/ \u6784\u9020\u51fd\u6570<br \/>\n        Mutex()<br \/>\n        {<br \/>\n            int n &#061; pthread_mutex_init(&amp;_mutex, nullptr);<br \/>\n            (void)n;<br \/>\n        }<\/p>\n<p>        \/\/ \u52a0\u9501<br \/>\n        void Lock()<br \/>\n        {<br \/>\n            int n &#061; pthread_mutex_lock(&amp;_mutex);<br \/>\n            (void)n;<br \/>\n        }<\/p>\n<p>        \/\/ \u89e3\u9501<br \/>\n        void Unlock()<br \/>\n        {<br \/>\n            int n &#061; pthread_mutex_unlock(&amp;_mutex);<br \/>\n            (void)n;<br \/>\n        }<\/p>\n<p>        \/\/ \u83b7\u53d6\u539f\u59cb\u6307\u9488<br \/>\n        pthread_mutex_t *GetMutexOriginal()<br \/>\n        {<br \/>\n            return &amp;_mutex;<br \/>\n        }<\/p>\n<p>        \/\/ \u6790\u6784\u51fd\u6570<br \/>\n        ~Mutex()<br \/>\n        {<br \/>\n            int n &#061; pthread_mutex_destroy(&amp;_mutex);<br \/>\n            (void)n;<br \/>\n        }<\/p>\n<p>    private:<br \/>\n        pthread_mutex_t _mutex;<br \/>\n    };<\/p>\n<p>    \/\/ \u91c7\u7528RAII\u98ce\u683c&#xff0c;\u8fdb\u884c\u9501\u7ba1\u7406<br \/>\n    class LockGuard<br \/>\n    {<br \/>\n    public:<br \/>\n        \/\/ \u6784\u9020\u51fd\u6570&#xff0c;\u521b\u5efa\u65f6\u81ea\u52a8\u52a0\u9501<br \/>\n        LockGuard(Mutex &amp;mutex) : _mutex(mutex)<br \/>\n        {<br \/>\n            _mutex.Lock();<br \/>\n        }<\/p>\n<p>        \/\/ \u6790\u6784\u51fd\u6570&#xff0c;\u81ea\u52a8\u89e3\u9501<br \/>\n        ~LockGuard()<br \/>\n        {<br \/>\n            _mutex.Unlock();<br \/>\n        }<\/p>\n<p>    private:<br \/>\n        Mutex &amp;_mutex;  \/\/ \u5f15\u7528\u88ab\u7ba1\u7406\u7684\u4e92\u65a5\u9501<br \/>\n    };<br \/>\n} <\/p>\n<p>\u00a0 \u00a0 \u00a0 \u00a0 Cond.hpp<\/p>\n<p>#pragma once<\/p>\n<p>#include &lt;iostream&gt;<br \/>\n#include &lt;string&gt;<br \/>\n#include &lt;pthread.h&gt;<br \/>\n#include &#034;Mutex.hpp&#034;<\/p>\n<p>namespace CondModule<br \/>\n{<br \/>\n    class Cond<br \/>\n    {<br \/>\n    public:<br \/>\n        Cond()<br \/>\n        {<br \/>\n            pthread_cond_init(&amp;_cond, nullptr);<br \/>\n        }<br \/>\n        void Wait(LockModule::Mutex &amp;mutex)<br \/>\n        {<br \/>\n            int n &#061; pthread_cond_wait(&amp;_cond, mutex.GetMutexOriginal());<br \/>\n            (void)n;<br \/>\n        }<br \/>\n        void Signal()<br \/>\n        {<br \/>\n            int n &#061; pthread_cond_signal(&amp;_cond);<br \/>\n            (void)n;<br \/>\n        }<br \/>\n        void Broadcast()<br \/>\n        {<br \/>\n            int n &#061; pthread_cond_broadcast(&amp;_cond);<br \/>\n            (void)n;<br \/>\n        }<br \/>\n        ~Cond()<br \/>\n        {<br \/>\n            pthread_cond_destroy(&amp;_cond);<br \/>\n        }<br \/>\n    private:<br \/>\n        pthread_cond_t _cond;<br \/>\n    };<br \/>\n}<\/p>\n<p>\u00a0 \u00a0 \u00a0 \u00a0 Thread.cpp<\/p>\n<p>#pragma once<\/p>\n<p>#include &lt;iostream&gt;<br \/>\n#include &lt;string&gt;<br \/>\n#include &lt;functional&gt;<br \/>\n#include &lt;pthread.h&gt;<br \/>\n#include &#034;..\/Log.h&#034;<\/p>\n<p>namespace ThreadPool<br \/>\n{<br \/>\n    using namespace Logger;<br \/>\n    static int gnumber &#061; 1;<br \/>\n    using callback_t &#061; std::function&lt;void()&gt;;<\/p>\n<p>    enum class TSTATUS<br \/>\n    {<br \/>\n        THREAD_NEW,<br \/>\n        THREAD_RUNNING,<br \/>\n        THREAD_STOP<br \/>\n    };<\/p>\n<p>    std::string Status2String(TSTATUS s)<br \/>\n    {<br \/>\n        switch (s)<br \/>\n        {<br \/>\n        case TSTATUS::THREAD_NEW:<br \/>\n            return &#034;THREAD_NEW&#034;;<br \/>\n        case TSTATUS::THREAD_RUNNING:<br \/>\n            return &#034;THREAD_RUNNING&#034;;<br \/>\n        case TSTATUS::THREAD_STOP:<br \/>\n            return &#034;THREAD_STOP&#034;;<br \/>\n        default:<br \/>\n            return &#034;UNKNOWN&#034;;<br \/>\n        }<br \/>\n    }<\/p>\n<p>    std::string IsJoined(bool joinable)<br \/>\n    {<br \/>\n        return joinable ? &#034;true&#034; : &#034;false&#034;;<br \/>\n    }<\/p>\n<p>    class Thread<br \/>\n    {<br \/>\n    private:<br \/>\n        void ToRunning()<br \/>\n        {<br \/>\n            _status &#061; TSTATUS::THREAD_RUNNING;<br \/>\n        }<br \/>\n        void ToStop()<br \/>\n        {<br \/>\n            _status &#061; TSTATUS::THREAD_STOP;<br \/>\n        }<br \/>\n        static void *ThreadRoutine(void *args)<br \/>\n        {<br \/>\n            Thread *self &#061; static_cast&lt;Thread *&gt;(args);<br \/>\n            pthread_setname_np(self-&gt;_tid, self-&gt;_name.c_str());<br \/>\n            self-&gt;_cb();<br \/>\n            self-&gt;ToStop();<br \/>\n            return nullptr;<br \/>\n        }<\/p>\n<p>    public:<br \/>\n        Thread(callback_t cb)<br \/>\n            : _tid(-1), _status(TSTATUS::THREAD_NEW), _joinable(true), _cb(cb), _result(nullptr)<br \/>\n        {<br \/>\n            _name &#061; &#034;New-Thread-&#034; &#043; std::to_string(gnumber&#043;&#043;);<br \/>\n        }<br \/>\n        bool Start()<br \/>\n        {<br \/>\n            int n &#061; pthread_create(&amp;_tid, nullptr, ThreadRoutine, this);<br \/>\n            if (n !&#061; 0)<br \/>\n                return false;<\/p>\n<p>            ToRunning();<br \/>\n            return true;<br \/>\n        }<br \/>\n        void Join()<br \/>\n        {<br \/>\n            if (_joinable)<br \/>\n            {<br \/>\n                int n &#061; pthread_join(_tid, &amp;_result);<br \/>\n                if (n !&#061; 0)<br \/>\n                {<br \/>\n                    std::cerr &lt;&lt; &#034;join error: &#034; &lt;&lt; n &lt;&lt; std::endl;<br \/>\n                    return;<br \/>\n                }<br \/>\n                (void)_result;<br \/>\n                _status &#061; TSTATUS::THREAD_STOP;<br \/>\n                Log(LogLevel::DEBUG) &lt;&lt; _name &lt;&lt; &#034; join success&#034;;<br \/>\n            }<br \/>\n            else<br \/>\n            {<br \/>\n                std::cerr &lt;&lt; &#034;error, thread join status: &#034; &lt;&lt; IsJoined(_joinable) &lt;&lt; std::endl;<br \/>\n            }<br \/>\n        }<br \/>\n        \/\/ \u6682\u505c<br \/>\n        \/\/ void Stop() \/\/ restart()<br \/>\n        \/\/ {<br \/>\n        \/\/     \/\/ \u8ba9\u7ebf\u7a0b\u6682\u505c<br \/>\n        \/\/ }<br \/>\n        void Die()<br \/>\n        {<br \/>\n            if (_status &#061;&#061; TSTATUS::THREAD_RUNNING)<br \/>\n            {<br \/>\n                pthread_cancel(_tid);<br \/>\n                _status &#061; TSTATUS::THREAD_STOP;<br \/>\n            }<br \/>\n        }<br \/>\n        void Detach()<br \/>\n        {<br \/>\n            if (_status &#061;&#061; TSTATUS::THREAD_RUNNING &amp;&amp; _joinable)<br \/>\n            {<br \/>\n                pthread_detach(_tid);<br \/>\n                _joinable &#061; false;<br \/>\n            }<br \/>\n            else<br \/>\n            {<br \/>\n                std::cerr &lt;&lt; &#034;detach &#034; &lt;&lt; _name &lt;&lt; &#034; failed&#034; &lt;&lt; std::endl;<br \/>\n            }<br \/>\n        }<br \/>\n        void PrintInfo()<br \/>\n        {<br \/>\n            std::cout &lt;&lt; &#034;thread name : &#034; &lt;&lt; _name &lt;&lt; std::endl;<br \/>\n            std::cout &lt;&lt; &#034;thread _tid : &#034; &lt;&lt; _tid &lt;&lt; std::endl;<br \/>\n            std::cout &lt;&lt; &#034;thread _status : &#034; &lt;&lt; Status2String(_status) &lt;&lt; std::endl;<br \/>\n            std::cout &lt;&lt; &#034;thread _joinable : &#034; &lt;&lt; IsJoined(_joinable) &lt;&lt; std::endl;<br \/>\n        }<\/p>\n<p>        ~Thread()<br \/>\n        {<br \/>\n        }<\/p>\n<p>    private:<br \/>\n        std::string _name;<br \/>\n        pthread_t _tid;<br \/>\n        TSTATUS _status;<br \/>\n        bool _joinable;<br \/>\n        \/\/ \u7ebf\u7a0b\u8981\u6709\u81ea\u5df1\u7684\u4efb\u52a1\u5904\u7406&#xff0c;\u5373\u56de\u8c03\u51fd\u6570<br \/>\n        callback_t _cb;<\/p>\n<p>        \/\/ \u7ebf\u7a0b\u9000\u51fa\u4fe1\u606f<br \/>\n        void *_result;<br \/>\n    };<br \/>\n} <\/p>\n<p>\u00a0 \u00a0 \u00a0 \u00a0 ThreadPool.hpp<\/p>\n<p>#pragma once<br \/>\n#include &#034;..\/Log.h&#034;<br \/>\n#include &#034;Thread.hpp&#034;<br \/>\n#include &#034;Mutex.hpp&#034;<br \/>\n#include &#034;Cond.hpp&#034;<br \/>\n#include &lt;iostream&gt;<br \/>\n#include &lt;memory&gt;<br \/>\n#include &lt;vector&gt;<br \/>\n#include &lt;queue&gt;<\/p>\n<p>namespace ThreadPool<br \/>\n{<br \/>\n    using namespace Logger;<br \/>\n    const int default_thread_num &#061; 5;<\/p>\n<p>    \/\/ \u6d4b\u8bd5\u7528\u51fd\u6570<br \/>\n    void test()<br \/>\n    {<br \/>\n        while(1)<br \/>\n        {<br \/>\n            Log(LogLevel::DEBUG) &lt;&lt; &#034;\u6211\u662f\u4e00\u4e2a\u65b0\u7ebf\u7a0b,\u6211\u518d\u8fd0\u884cing&#8230;.&#034;;<br \/>\n            sleep(1);<br \/>\n        }<br \/>\n    }<\/p>\n<p>    template&lt;typename T&gt;<br \/>\n    class threadpool<br \/>\n    {<br \/>\n    private:<br \/>\n        void HandlerTask()<br \/>\n        {<br \/>\n            char name[128];<br \/>\n            pthread_getname_np(pthread_self(), name, sizeof(name));<br \/>\n            while (true)<br \/>\n            {<br \/>\n                T task;<br \/>\n                {<br \/>\n                    LockModule::LockGuard lockguard(_mutex);   \/\/ \u4f7f\u7528 RAII \u7ba1\u7406\u9501&#xff0c;\u907f\u514d\u624b\u52a8\u89e3\u9501<br \/>\n                    while (_tasks.empty() &amp;&amp; _isRunning)<br \/>\n                    {<br \/>\n                        _Slaves_Sleep_Count&#043;&#043;;<br \/>\n                        _cond.Wait(_mutex);<br \/>\n                        _Slaves_Sleep_Count&#8211;;<br \/>\n                    }<\/p>\n<p>                    if (!_isRunning &amp;&amp; _tasks.empty())<br \/>\n                    {<br \/>\n                        \/\/ \u9000\u51fa\u524d\u89e3\u9501&#xff08;LockGuard \u6790\u6784\u65f6\u4f1a\u81ea\u52a8\u89e3\u9501&#xff0c;\u65e0\u9700\u624b\u52a8&#xff09;<br \/>\n                        break;<br \/>\n                    }<\/p>\n<p>                    task &#061; _tasks.front();<br \/>\n                    _tasks.pop();<br \/>\n                }<\/p>\n<p>                Log(LogLevel::INFO) &lt;&lt; name &lt;&lt; &#034;\u5904\u7406\u4efb\u52a1:&#034;;<br \/>\n                task();<br \/>\n                \/\/ Log(LogLevel::DEBUG) &lt;&lt; task.Result();<br \/>\n            }<br \/>\n            Log(LogLevel::INFO) &lt;&lt; name &lt;&lt; &#034; quit&#8230;&#034;;<br \/>\n        }<\/p>\n<p>        \/\/ \u6784\u9020\u51fd\u6570\u79c1\u6709&#xff0c;\u7981\u6b62\u5916\u90e8\u76f4\u63a5\u521b\u5efa<br \/>\n        threadpool(int slave_num &#061; default_thread_num)<br \/>\n            : _isRunning(false), _Slavernum(slave_num), _Slaves_Sleep_Count(0)<br \/>\n        {<br \/>\n            _Slaves.reserve(_Slavernum);<br \/>\n            auto fun &#061; std::bind(&amp;threadpool::HandlerTask, this);<br \/>\n            for (size_t i &#061; 0; i &lt; _Slavernum; &#043;&#043;i)<br \/>\n            {<br \/>\n                _Slaves.emplace_back(fun);<br \/>\n            }<br \/>\n        }<\/p>\n<p>        \/\/ \u7981\u6b62\u62f7\u8d1d\u548c\u8d4b\u503c&#xff08;\u4fee\u6b63&#xff1a;\u7c7b\u540d\u5e94\u4e3a threadpool&#xff09;<br \/>\n        threadpool(const threadpool &amp;) &#061; delete;<br \/>\n        threadpool &amp;operator&#061;(const threadpool &amp;) &#061; delete;<\/p>\n<p>    public:<br \/>\n        static threadpool&lt;T&gt;* Instance()<br \/>\n        {<br \/>\n            if (_instance &#061;&#061; nullptr)<br \/>\n            {<br \/>\n                LockModule::LockGuard lockguard(_lock);<br \/>\n                if (_instance &#061;&#061; nullptr)<br \/>\n                {<br \/>\n                    \/\/ \u4f7f\u7528 reset(new &#8230;) \u66ff\u4ee3 std::make_unique&#xff0c;\u56e0\u4e3a\u6784\u9020\u51fd\u6570\u79c1\u6709<br \/>\n                    _instance.reset(new threadpool&lt;T&gt;());<br \/>\n                    _instance-&gt;Init();               \/\/ \u8c03\u7528 Init \u800c\u975e Start<br \/>\n                    Log(LogLevel::INFO) &lt;&lt; &#034;\u7b2c\u4e00\u6b21\u4f7f\u7528\u7ebf\u7a0b\u6c60&#xff0c;\u521b\u5efa\u7ebf\u7a0b\u6c60\u5bf9\u8c61&#034;;<br \/>\n                }<br \/>\n            }<br \/>\n            return _instance.get();<br \/>\n        }<\/p>\n<p>        ~threadpool()<br \/>\n        {<br \/>\n        }<\/p>\n<p>        void Init()<br \/>\n        {<br \/>\n            if (_isRunning)<br \/>\n            {<br \/>\n                Log(LogLevel::WARNING) &lt;&lt; &#034;\u7ebf\u7a0b\u6c60\u5df2\u7ecf\u8fd0\u884c&#034;;<br \/>\n                return;<br \/>\n            }<br \/>\n            _isRunning &#061; true;<br \/>\n            for (auto &amp;slave : _Slaves)<br \/>\n            {<br \/>\n                slave.Start();<br \/>\n            }<br \/>\n        }<\/p>\n<p>        void Stop()<br \/>\n        {<br \/>\n            if (!_isRunning)<br \/>\n            {<br \/>\n                Log(LogLevel::WARNING) &lt;&lt; &#034;\u7ebf\u7a0b\u6c60\u672a\u8fd0\u884c&#034;;<br \/>\n                return;<br \/>\n            }<br \/>\n            \/\/ \u505c\u6b62\u7ebf\u7a0b\u6c60<br \/>\n            _mutex.Lock();<br \/>\n            _isRunning &#061; false;<br \/>\n            if (_Slaves_Sleep_Count &gt; 0)<br \/>\n                _cond.Broadcast();<br \/>\n            _mutex.Unlock();<\/p>\n<p>            \/\/ \u7b49\u5f85\u6240\u6709\u7ebf\u7a0b\u9000\u51fa&#xff08;\u53ef\u9009&#xff09;<br \/>\n            \/\/ Wait();<br \/>\n        }<\/p>\n<p>        void Wait()<br \/>\n        {<br \/>\n            for (auto &amp;slave : _Slaves)<br \/>\n            {<br \/>\n                slave.Join();<br \/>\n            }<br \/>\n        }<\/p>\n<p>        void Enqueue(T in)<br \/>\n        {<br \/>\n            _mutex.Lock();<br \/>\n            _tasks.push(in);<br \/>\n            if (_Slaves_Sleep_Count &gt; 0)<br \/>\n                _cond.Signal();<br \/>\n            _mutex.Unlock();<br \/>\n        }<\/p>\n<p>    private:<br \/>\n        bool _isRunning;<br \/>\n        size_t _Slavernum;<br \/>\n        std::vector&lt;Thread&gt; _Slaves;<br \/>\n        std::queue&lt;T&gt; _tasks;                \/\/ \u4e34\u754c\u8d44\u6e90<br \/>\n        LockModule::Mutex _mutex;<br \/>\n        CondModule::Cond _cond;<br \/>\n        size_t _Slaves_Sleep_Count;          \/\/ \u4f11\u7720\u7684\u7ebf\u7a0b\u6570\u91cf<\/p>\n<p>        \/\/ \u5355\u4f8b\u6a21\u5f0f\u9759\u6001\u6210\u5458<br \/>\n        static std::unique_ptr&lt;threadpool&lt;T&gt;&gt; _instance;<br \/>\n        static LockModule::Mutex _lock;       \/\/ \u7c7b\u578b\u6539\u4e3a LockModule::Mutex<br \/>\n    };<\/p>\n<p>    \/\/ \u9759\u6001\u6210\u5458\u5b9a\u4e49&#xff08;\u5fc5\u987b\u653e\u5728\u547d\u540d\u7a7a\u95f4\u5185&#xff09;<br \/>\n    template&lt;typename T&gt;<br \/>\n    std::unique_ptr&lt;threadpool&lt;T&gt;&gt; threadpool&lt;T&gt;::_instance &#061; nullptr;<\/p>\n<p>    template&lt;typename T&gt;<br \/>\n    LockModule::Mutex threadpool&lt;T&gt;::_lock;<\/p>\n<p>} \/\/ namespace ThreadPool <\/p>\n<h2 id=\"%E7%BD%91%E7%BB%9C%E5%AE%A2%E6%88%B7%E7%AB%AF\">\u7f51\u7edc\u5ba2\u6237\u7aef<\/h2>\n<p>#pragma once<br \/>\n#include&lt;iostream&gt;<br \/>\n#include&lt;string&gt;<br \/>\n#include&lt;cstring&gt;<br \/>\n#include &lt;sys\/socket.h&gt;<br \/>\n#include &lt;netinet\/in.h&gt;<br \/>\n#include &lt;arpa\/inet.h&gt;<br \/>\n\/\/\u7f51\u7edc\u5ba2\u6237\u7aef\u5c01\u88c5<br \/>\nclass InetAddr<br \/>\n{<br \/>\n    private:<br \/>\n        std::string IP_;<br \/>\n        uint16_t port_;<br \/>\n        struct sockaddr_in address_;<br \/>\n        socklen_t len_;<br \/>\n    public:<br \/>\n        InetAddr()&#061;default;<br \/>\n        InetAddr(const struct sockaddr_in&amp; address) : address_(address),len_(sizeof(address))<br \/>\n        {<br \/>\n            IP_ &#061; inet_ntoa(address_.sin_addr);   \/\/ \u5c06\u4e8c\u8fdb\u5236IP\u8f6c\u6362\u4e3a\u5b57\u7b26\u4e32<br \/>\n            port_ &#061; ntohs(address_.sin_port);      \/\/ \u7aef\u53e3\u8f6c\u6362\u6b63\u786e<br \/>\n        }<br \/>\n        InetAddr(uint16_t port,const std::string ip&#061;&#034;0.0.0.0&#034;):IP_(ip),port_(port)<br \/>\n        {<br \/>\n            bzero(&amp;address_, sizeof(address_));<br \/>\n            address_.sin_family &#061; AF_INET;<br \/>\n            address_.sin_addr.s_addr &#061; inet_addr(IP_.c_str());<br \/>\n            address_.sin_port &#061; htons(port_);<br \/>\n            len_&#061;sizeof(address_);<br \/>\n        }<br \/>\n        struct sockaddr_in*GetNetAddress()<br \/>\n        {<br \/>\n            return &amp;address_;<br \/>\n        }<br \/>\n        ~InetAddr()&#061;default;<br \/>\n        socklen_t len()<br \/>\n        {<br \/>\n            return len_;<br \/>\n        }<br \/>\n        bool operator&#061;&#061;(const InetAddr&amp;addrs)<br \/>\n        {<br \/>\n            return (this-&gt; IP_&#061;&#061;addrs.IP_)&amp;&amp;(this-&gt;port_&#061;&#061;addrs.port_);<br \/>\n        }<br \/>\n        std::string ToString()<br \/>\n        {<br \/>\n            return &#034;[&#034; &#043; IP_ &#043; &#034;:&#034; &#043; std::to_string(port_) &#043; &#034;]&#034;;<br \/>\n        }<\/p>\n<p>};<\/p>\n<h2 id=\"%E5%91%BD%E4%BB%A4\">\u547d\u4ee4<\/h2>\n<p>#pragma once<\/p>\n<p>#include &lt;iostream&gt;<br \/>\n#include &lt;cstdio&gt;<br \/>\n#include &lt;vector&gt;<br \/>\n#include &lt;string&gt;<br \/>\n#include &lt;cstdio&gt;<br \/>\n#include &lt;sys\/types.h&gt;<br \/>\n#include &lt;pwd.h&gt;<br \/>\n#include &lt;unistd.h&gt;<\/p>\n<p>class Command<br \/>\n{<br \/>\nprivate:<br \/>\n    void LoadCommand()<br \/>\n    {<br \/>\n        _whitelist.emplace_back(&#034;ls -a -l&#034;);<br \/>\n        _whitelist.emplace_back(&#034;ls -l&#034;);<br \/>\n        _whitelist.emplace_back(&#034;pwd&#034;);<br \/>\n        _whitelist.emplace_back(&#034;whoami&#034;);<br \/>\n        _whitelist.emplace_back(&#034;who&#034;);<br \/>\n        _whitelist.emplace_back(&#034;ps -al&#034;);<br \/>\n        _whitelist.emplace_back(&#034;netstat -nltp&#034;);<br \/>\n        _whitelist.emplace_back(&#034;netstat -nutp&#034;);<br \/>\n        _whitelist.emplace_back(&#034;netstat -natp&#034;);<br \/>\n        _whitelist.emplace_back(&#034;netstat -naup&#034;);<br \/>\n    }<br \/>\n    bool IsSafe(const std::string &amp;cmd)<br \/>\n    {<br \/>\n        for (auto &amp;elem : _whitelist)<br \/>\n        {<br \/>\n            if (elem &#061;&#061; cmd)<br \/>\n                return true;<br \/>\n        }<br \/>\n        return false;<br \/>\n    }<\/p>\n<p>public:<br \/>\n    Command()<br \/>\n    {<br \/>\n        LoadCommand();<br \/>\n    }<br \/>\n    ~Command() {}<br \/>\n    \/\/ rm *.c *.cc *.hpp<br \/>\n    \/\/ rm move<br \/>\n    \/\/ ls -al &amp;&amp; rm -rf \/<br \/>\n    std::string Excute(const std::string &amp;cmd)<br \/>\n    {<br \/>\n        if (!IsSafe(cmd))<br \/>\n        {<br \/>\n            return &#034;bad man!&#034;;<br \/>\n        }<\/p>\n<p>        FILE *fp &#061; popen(cmd.c_str(), &#034;r&#034;);<br \/>\n        if (fp &#061;&#061; nullptr)<br \/>\n            return &#034;execute error!&#034;;<br \/>\n        std::string result;<br \/>\n        char buffer[1024];<br \/>\n        while (fgets(buffer, sizeof(buffer), fp))<br \/>\n        {<br \/>\n            result &#043;&#061; buffer;<br \/>\n        }<\/p>\n<p>        pclose(fp);<\/p>\n<p>        return result;<br \/>\n    }<br \/>\n    std::string GetCommandString()<br \/>\n    {<br \/>\n        \/\/ whb&#064;iv-ye4ege8iyo5i3z3clix9:~$<\/p>\n<p>        struct passwd *pw &#061; getpwuid(getuid());<br \/>\n        std::string username &#061; (pw?pw-&gt;pw_name : &#034;unknown&#034;);<\/p>\n<p>        char hostname[256];<br \/>\n        if (gethostname(hostname, sizeof(hostname)) !&#061; 0)<br \/>\n        {<br \/>\n            snprintf(hostname, sizeof(hostname), &#034;unknown&#034;);<br \/>\n        }<\/p>\n<p>        char cwd[1024];<br \/>\n        if (getcwd(cwd, sizeof(cwd)) &#061;&#061; NULL)<br \/>\n        {<br \/>\n            snprintf(cwd, sizeof(cwd), &#034;unknown&#034;);<br \/>\n        }<\/p>\n<p>        return &#034;[&#034; &#043; username &#043; &#034;&#064;&#034; &#043; hostname &#043; &#034; &#034; &#043; cwd &#043; &#034;]# &#034;;<br \/>\n    }<\/p>\n<p>private:<br \/>\n    std::vector&lt;std::string&gt; _whitelist;<br \/>\n}; <\/p>\n<h2 id=\"%E6%9C%8D%E5%8A%A1%E5%99%A8\">\u670d\u52a1\u5668<\/h2>\n<h3 id=\"%C2%A0%20%C2%A0%20%C2%A0%20%C2%A0%20%E6%9C%8D%E5%8A%A1%E5%99%A8%E4%BB%A3%E7%A0%81\">\u00a0 \u00a0 \u00a0 \u00a0 \u670d\u52a1\u5668\u4ee3\u7801<\/h3>\n<p>#pragma once<\/p>\n<p>#include &#034;Log.h&#034;<br \/>\n#include &#034;InetAddr.h&#034;<br \/>\n#include &#034;ThreadPool\/ThreadPool.hpp&#034;<br \/>\n#include &#034;Command.hpp&#034;          \/\/ \u65b0\u589e&#xff1a;\u5305\u542b Command \u7c7b<br \/>\n#include &lt;unistd.h&gt;<br \/>\n#include &lt;functional&gt;<br \/>\n#include &lt;memory&gt;               \/\/ \u65b0\u589e&#xff1a;std::unique_ptr<\/p>\n<p>using namespace Logger;<br \/>\nusing namespace ThreadPool;<\/p>\n<p>using task_t &#061; std::function&lt;void()&gt;;<br \/>\nusing handler_t &#061; std::function&lt;std::string(std::string)&gt;;<\/p>\n<p>enum<br \/>\n{<br \/>\n    SUCCESS &#061; 0,<br \/>\n    SOCKET_ERR,<br \/>\n    BIND_ERR,<br \/>\n    LISTEN_ERR,<br \/>\n    USAGE_ERR<br \/>\n};<\/p>\n<p>static const int gblocklist &#061; 16;<br \/>\nstatic const uint16_t defaultport &#061; 8080;<\/p>\n<p>class TCPServer<br \/>\n{<br \/>\nprivate:<br \/>\n    uint16_t port_;<br \/>\n    int ListenSocketfd_;<br \/>\n    handler_t hanlder_;<br \/>\n    std::unique_ptr&lt;Command&gt; cmd_;          \/\/ \u65b0\u589e&#xff1a;\u6301\u6709 Command \u5bf9\u8c61<\/p>\n<p>public:<br \/>\n    TCPServer(uint16_t port &#061; defaultport) : port_(port) {}<\/p>\n<p>    void Init()<br \/>\n    {<br \/>\n        ListenSocketfd_ &#061; socket(AF_INET, SOCK_STREAM, 0);<br \/>\n        if (ListenSocketfd_ &lt; 0)<br \/>\n        {<br \/>\n            Log(LogLevel::ERROR) &lt;&lt; &#034;\u670d\u52a1\u5668\u521b\u5efa\u5957\u63a5\u5b57\u5931\u8d25&#034;;<br \/>\n            exit(SOCKET_ERR);<br \/>\n        }<br \/>\n        Log(LogLevel::DEBUG) &lt;&lt; &#034;\u521b\u5efa\u5957\u63a5\u5b57\u6210\u529f&#034; &lt;&lt; ListenSocketfd_;<\/p>\n<p>        struct sockaddr_in local;<br \/>\n        memset(&amp;local, 0, sizeof(local));<br \/>\n        local.sin_family &#061; AF_INET;<br \/>\n        local.sin_port &#061; htons(port_);<br \/>\n        local.sin_addr.s_addr &#061; INADDR_ANY;<\/p>\n<p>        int n &#061; bind(ListenSocketfd_, (struct sockaddr *)&amp;local, sizeof(local));<br \/>\n        if (n &lt; 0)<br \/>\n        {<br \/>\n            Log(LogLevel::ERROR) &lt;&lt; &#034;\u7ed1\u5b9a\u5931\u8d25&#034;;<br \/>\n            exit(BIND_ERR);<br \/>\n        }<br \/>\n        Log(LogLevel::DEBUG) &lt;&lt; &#034;\u7ed1\u5b9a\u6210\u529f&#034;;<\/p>\n<p>        int m &#061; listen(ListenSocketfd_, gblocklist);<br \/>\n        if (m &lt; 0)<br \/>\n        {<br \/>\n            Log(LogLevel::ERROR) &lt;&lt; &#034;\u76d1\u542c\u5931\u8d25&#034;;<br \/>\n            exit(LISTEN_ERR);<br \/>\n        }<br \/>\n        Log(LogLevel::DEBUG) &lt;&lt; &#034;\u76d1\u542c\u6210\u529f&#034;;<br \/>\n    }<\/p>\n<p>    \/\/ \u65b0\u589e&#xff1a;\u8bbe\u7f6e Command \u5bf9\u8c61&#xff08;\u6240\u6709\u6743\u8f6c\u79fb&#xff09;<br \/>\n    void SetCommand(std::unique_ptr&lt;Command&gt; cmd)<br \/>\n    {<br \/>\n        cmd_ &#061; std::move(cmd);<br \/>\n    }<\/p>\n<p>    \/\/ \u65b0\u589e&#xff1a;\u83b7\u53d6\u539f\u59cb\u6307\u9488\u4f9b lambda \u4f7f\u7528<br \/>\n    Command* GetCommand() const<br \/>\n    {<br \/>\n        return cmd_.get();<br \/>\n    }<\/p>\n<p>    void Register(handler_t handler)<br \/>\n    {<br \/>\n        hanlder_ &#061; handler;<br \/>\n    }<\/p>\n<p>    void ServerIO(int fd, InetAddr address)<br \/>\n    {<br \/>\n        Log(LogLevel::DEBUG) &lt;&lt; &#034;\u5ba2\u6237\u7aef\u4fe1\u606f&#034; &lt;&lt; address.ToString();<br \/>\n        while (1)<br \/>\n        {<br \/>\n            \/\/ \u65b0\u589e&#xff1a;\u53d1\u9001\u547d\u4ee4\u63d0\u793a\u7b26<br \/>\n            std::string prompt &#061; cmd_-&gt;GetCommandString();<br \/>\n            ssize_t sent &#061; write(fd, prompt.c_str(), prompt.size());<br \/>\n            if (sent &lt;&#061; 0)<br \/>\n            {<br \/>\n                Log(LogLevel::WARNING) &lt;&lt; &#034;\u53d1\u9001\u63d0\u793a\u7b26\u5931\u8d25&#xff0c;\u5173\u95ed\u8fde\u63a5&#034;;<br \/>\n                break;<br \/>\n            }<\/p>\n<p>            char inbuffer[1024] &#061; {0};<br \/>\n            ssize_t n &#061; read(fd, inbuffer, sizeof(inbuffer) &#8211; 1);<br \/>\n            if (n &gt; 0)<br \/>\n            {<br \/>\n                inbuffer[n] &#061; 0;<br \/>\n                std::string result;<br \/>\n                if (hanlder_ !&#061; nullptr)<br \/>\n                {<br \/>\n                    result &#061; hanlder_(inbuffer);<br \/>\n                }<br \/>\n                else<br \/>\n                {<br \/>\n                    Log(LogLevel::WARNING) &lt;&lt; &#034;\u670d\u52a1\u6ca1\u6709\u51c6\u5907\u597d&#034;;<br \/>\n                    break;<br \/>\n                }<br \/>\n                write(fd, result.c_str(), result.size());<br \/>\n            }<br \/>\n            else if (n &#061;&#061; 0)<br \/>\n            {<br \/>\n                Log(LogLevel::INFO) &lt;&lt; &#034;\u5ba2\u6237\u7aef\u9000\u51fa&#034; &lt;&lt; address.ToString();<br \/>\n                break;<br \/>\n            }<br \/>\n            else<br \/>\n            {<br \/>\n                Log(LogLevel::WARNING) &lt;&lt; &#034;\u5ba2\u6237\u7aef\u51fa\u9519&#034; &lt;&lt; address.ToString();<br \/>\n                break;<br \/>\n            }<br \/>\n        }<br \/>\n    }<\/p>\n<p>    class ThreadData<br \/>\n    {<br \/>\n    public:<br \/>\n        ThreadData(TCPServer *ts, int sockfd, InetAddr addr)<br \/>\n            : _this(ts), _sockfd(sockfd), _addr(addr)<br \/>\n        {}<br \/>\n        ~ThreadData() {}<br \/>\n    public:<br \/>\n        TCPServer *_this;<br \/>\n        int _sockfd;<br \/>\n        InetAddr _addr;<br \/>\n    };<\/p>\n<p>    void Start()<br \/>\n    {<br \/>\n        while (1)<br \/>\n        {<br \/>\n            struct sockaddr_in clientaddr;<br \/>\n            socklen_t len &#061; sizeof(clientaddr);<br \/>\n            int socketfd &#061; accept(ListenSocketfd_, (struct sockaddr *)&amp;clientaddr, &amp;len);<br \/>\n            if (socketfd &lt; 0)<br \/>\n            {<br \/>\n                Log(LogLevel::WARNING) &lt;&lt; &#034;\u76d1\u542c\u5931\u8d25&#034;;<br \/>\n                continue;<br \/>\n            }<br \/>\n            Log(LogLevel::DEBUG) &lt;&lt; &#034;\u76d1\u542c\u6210\u529f&#034;;<\/p>\n<p>            InetAddr clientaddress(clientaddr);<br \/>\n            threadpool&lt;task_t&gt;::Instance()-&gt;Enqueue([this, socketfd, clientaddress]() {<br \/>\n                this-&gt;ServerIO(socketfd, clientaddress);<br \/>\n            });<br \/>\n        }<br \/>\n    }<\/p>\n<p>    ~TCPServer()<br \/>\n    {<br \/>\n        close(ListenSocketfd_);<br \/>\n    }<br \/>\n}; <\/p>\n<h3 id=\"%C2%A0%20%C2%A0%20%C2%A0%20%C2%A0%20%E6%9C%8D%E5%8A%A1%E5%99%A8%E8%BF%90%E8%A1%8C\">\u00a0 \u00a0 \u00a0 \u00a0 \u670d\u52a1\u5668\u8fd0\u884c<\/h3>\n<p>#include &#034;TCPServer.hpp&#034;<br \/>\n#include &#034;Command.hpp&#034;<br \/>\n#include &lt;memory&gt;<br \/>\n#include &lt;cstdlib&gt;<\/p>\n<p>inline static void Usage(const std::string &amp;proc)<br \/>\n{<br \/>\n    std::cerr &lt;&lt; &#034;\u8f93\u5165\u9519\u8bef\\\\n\\\\t&#034;;<br \/>\n    std::cerr &lt;&lt; proc &lt;&lt; &#034;\u4f60\u5e94\u8be5\u544a\u8bc9\u6211\u4f60\u7684\u7aef\u53e3\u53f7&#034; &lt;&lt; std::endl;<br \/>\n}<\/p>\n<p>int main(int argc, char *argv[])<br \/>\n{<br \/>\n    if (argc !&#061; 2)<br \/>\n    {<br \/>\n        Usage(argv[0]);<br \/>\n        exit(USAGE_ERR);<br \/>\n    }<br \/>\n    ENABLE_LOG_CONSOLE();<\/p>\n<p>    uint16_t port &#061; std::atoi(argv[1]);<\/p>\n<p>    \/\/ \u521b\u5efa Command \u5bf9\u8c61<br \/>\n    auto cmd &#061; std::make_unique&lt;Command&gt;();<\/p>\n<p>    \/\/ \u521b\u5efa TCPServer \u5bf9\u8c61<br \/>\n    auto tsvr &#061; std::make_unique&lt;TCPServer&gt;(port);<\/p>\n<p>    \/\/ \u5c06 Command \u6240\u6709\u6743\u8f6c\u79fb\u7ed9 TCPServer<br \/>\n    tsvr-&gt;SetCommand(std::move(cmd));<\/p>\n<p>    \/\/ \u6ce8\u518c\u547d\u4ee4\u5904\u7406\u51fd\u6570&#xff08;\u4f7f\u7528 TCPServer \u5185\u90e8\u7684 Command \u5bf9\u8c61&#xff09;<br \/>\n    tsvr-&gt;Register([cmd_ptr &#061; tsvr-&gt;GetCommand()](std::string command) {<br \/>\n        return cmd_ptr-&gt;Excute(command);<br \/>\n    });<\/p>\n<p>    tsvr-&gt;Init();<br \/>\n    tsvr-&gt;Start();<\/p>\n<p>    return 0;<br \/>\n} <\/p>\n<h3 id=\"%C2%A0%20%C2%A0%20%C2%A0%20%C2%A0%20%E5%AE%A2%E6%88%B7%E7%AB%AF%E8%BF%90%E8%A1%8C\">\u00a0 \u00a0 \u00a0 \u00a0 \u5ba2\u6237\u7aef\u8fd0\u884c<\/h3>\n<p>#include &lt;iostream&gt;<br \/>\n#include &lt;string&gt;<br \/>\n#include &lt;cstdlib&gt;<br \/>\n#include &lt;unistd.h&gt;<br \/>\n#include &lt;sys\/socket.h&gt;<br \/>\n#include &lt;arpa\/inet.h&gt;<br \/>\n#include &lt;netinet\/in.h&gt;<br \/>\n#include &#034;InetAddr.h&#034;<\/p>\n<p>static void Usage(const std::string &amp;name)<br \/>\n{<br \/>\n    std::cerr &lt;&lt; &#034;Usage:\\\\n\\\\t&#034;;<br \/>\n    std::cerr &lt;&lt; name &lt;&lt; &#034; server_ip server_port&#034; &lt;&lt; std::endl;<br \/>\n}<\/p>\n<p>\/\/ .\/client_tcp server_ip server_port<br \/>\nint main(int argc, char *argv[])<br \/>\n{<br \/>\n    if (argc !&#061; 3)<br \/>\n    {<br \/>\n        Usage(argv[0]);<br \/>\n        exit(1);<br \/>\n    }<br \/>\n    std::string server_ip &#061; argv[1];<br \/>\n    uint16_t server_port &#061; std::stoi(argv[2]);<br \/>\n    \/\/ 1. \u521b\u5efatcpsocket\u5957\u63a5\u5b57<br \/>\n    int sockfd &#061; socket(AF_INET, SOCK_STREAM, 0);<br \/>\n    if (sockfd &lt; 0)<br \/>\n    {<br \/>\n        std::cerr &lt;&lt; &#034;socket error&#034; &lt;&lt; std::endl;<br \/>\n        exit(2);<br \/>\n    }<\/p>\n<p>    \/\/ 2. \u8981\u4e0d\u8981\u8fdb\u884cbind&#xff1f;\u9700\u8981<br \/>\n    \/\/ \u8981\u4e0d\u8981\u663e\u793a\u7684bind\u672c\u5730IP\u548c\u7aef\u53e3&#xff1f;\u4e0d\u9700\u8981\u81ea\u5df1\u624b\u52a8\u663e\u793a\u7684\u8fdb\u884cbind&#xff0c;OS\u4f1a\u81ea\u52a8bind\u7684&#xff01;<br \/>\n    \/\/ OS \u5e2e\u52a9\u6211\u4eec\u8fdb\u884c\u968f\u673a\u7aef\u53e3&#xff0c;\u9632\u6b62\u7aef\u53e3\u53f7\u51b2\u7a81<br \/>\n    \/\/ 2. \u5e94\u8be5\u5e72\u4ec0\u4e48&#xff1f;bind\u7aef\u53e3\u53f7ip&#xff0c;\u53d1\u8d77\u5efa\u7acb\u8fde\u63a5\u7684\u5de5\u4f5c<br \/>\n    \/\/ {client ip, client port} &lt;-&gt; {server ip, server port}<br \/>\n    InetAddr serveraddress(server_port, server_ip);<br \/>\n    int n &#061; connect(sockfd, (struct sockaddr *)serveraddress.GetNetAddress(), serveraddress.len());<br \/>\n    if (n &lt; 0)<br \/>\n    {<br \/>\n        std::cerr &lt;&lt; &#034;connect to &#034; &lt;&lt; serveraddress.ToString() &lt;&lt; &#034; failed!&#034;&lt;&lt; std::endl;<br \/>\n        exit(3);<br \/>\n    }<br \/>\n    std::cerr &lt;&lt; &#034;connect to &#034; &lt;&lt; serveraddress.ToString() &lt;&lt; &#034; success!&#034; &lt;&lt; std::endl;<\/p>\n<p>    \/\/ 3. \u901a\u4fe1<br \/>\n    while(true)<br \/>\n    {<br \/>\n        char commandline[1024];<br \/>\n        std::string commandlinestr;<br \/>\n        ssize_t n &#061; read(sockfd, commandline, sizeof(commandline)-1);<br \/>\n        if(n &gt; 0)<br \/>\n        {<br \/>\n            commandline[n] &#061; 0;<br \/>\n            commandlinestr &#061; commandline;<br \/>\n        }<br \/>\n        else{<br \/>\n            commandlinestr &#061; &#034;[unknow&#064;unknown None]# &#034;;<br \/>\n        }<\/p>\n<p>        std::cout &lt;&lt; commandlinestr;<\/p>\n<p>        \/\/ \u5904\u7406\u4e00\u4e2a\u547d\u4ee4<br \/>\n        std::string command;<br \/>\n        std::getline(std::cin, command);<br \/>\n        write(sockfd, command.c_str(), command.size());<\/p>\n<p>        char inbuffer[1024];<br \/>\n        n &#061; read(sockfd, inbuffer, sizeof(inbuffer));<br \/>\n        if(n &gt; 0)<br \/>\n        {<br \/>\n            inbuffer[n] &#061; 0;<br \/>\n            std::cout &lt;&lt; inbuffer &lt;&lt; std::endl;<br \/>\n        }<br \/>\n        else if(n &#061;&#061; 0)<br \/>\n        {<br \/>\n            std::cout &lt;&lt; &#034;read enf of file!&#034; &lt;&lt; std::endl;<br \/>\n            break;<br \/>\n        }<br \/>\n        else<br \/>\n        {<br \/>\n            std::cerr &lt;&lt; &#034;read error!&#034; &lt;&lt; std::endl;<br \/>\n            break;<br \/>\n        }<br \/>\n    }<\/p>\n<p>    return 0;<br \/>\n} <\/p>\n<h3 id=\"%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%E6%B5%8B%E8%AF%95\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u6d4b\u8bd5<\/h3>\n<p>\u00a0 \u00a0 \u00a0 \u00a0 \u8de8\u7f51\u7edc\u8fde\u63a5&#xff0c;\u7ed3\u679c\u4e3a&#xff1a;<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" alt=\"\" height=\"810\" src=\"https:\/\/www.wsisp.com\/helps\/wp-content\/uploads\/2026\/03\/20260303115054-69a6cb1e92dda.png\" width=\"1658\" \/><\/p>\n<\/p>\n<p>\u00a0 \u00a0 \u00a0 \u00a0 \u5173\u4e8eTCP\u7f51\u7edc\u7684\u5185\u5bb9&#xff0c;\u5230\u8fd9\u91cc\u5c31\u7ed3\u675f\u4e86&#xff0c;\u559c\u6b22\u8bf7\u70b9\u4e2a\u8d5e&#xff0c;\u8c22\u8c22<\/p>\n<p>\u5c01\u9762\u56fe\u81ea\u53d6&#xff1a;<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" alt=\"\" height=\"1415\" src=\"https:\/\/www.wsisp.com\/helps\/wp-content\/uploads\/2026\/03\/20260303115055-69a6cb1f32ff8.png\" width=\"1000\" \/><\/p>\n","protected":false},"excerpt":{"rendered":"<p>\u524d\u9762\u6211\u4eec\u57fa\u4e8eTCP\u5b9e\u73b0\u4e86\u7b80\u5355\u4e86\u4e92\u52a8\u670d\u52a1\u5668\u3002\u4f46\u662f\u90a3\u662f\u8fdc\u8fdc\u4e0d\u591f\u7684&#xff0c;\u672c\u671f\u6211\u4eec\u5c06\u5b9e\u73b0\u4e00\u4e2a\u57fa\u4e8eTCP\u7684\u8fdc\u7a0b\u547d\u4ee4\u884c\u7ec8\u7aef \u76f8\u5173\u4ee3\u7801\u63d0\u4ea4\u81f3\u4f5c\u8005\u7684\u4e2a\u4ebagitee&#xff1a;\u697c\u7530\u8389\u5b50\/Linux\u5b66\u4e60\u559c\u6b22\u8bf7\u70b9\u4e2a\u8d5e\u8c22\u8c22<br \/>\n\u76ee\u5f55<br \/>\n\u65e5\u5fd7<br \/>\n\u7ebf\u7a0b\u6c60\u76f8\u5173<br \/>\n\u7f51\u7edc\u5ba2\u6237\u7aef<br \/>\n\u547d\u4ee4<br \/>\n\u670d\u52a1\u5668 \u670d\u52a1\u5668\u4ee3\u7801 \u670d\u52a1\u5668\u8fd0\u884c \u5ba2\u6237\u7aef\u8fd0\u884c \u6d4b\u8bd5 \u65e5\u5fd7<br \/>\n#pragma once#include<br \/>\n#include<br \/>\n#include<br \/>\n#inclu<\/p>\n","protected":false},"author":2,"featured_media":79938,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[55,58,205,371,190,78],"topic":[],"class_list":["post-79940","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-server","tag-c","tag-linux","tag-tcp-ip","tag-371","tag-190","tag-78"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v20.3 - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>C++\u9879\u76ee\uff1a\u57fa\u4e8eLinux\u7cfb\u7edf\u548cTCP\u534f\u8bae\u7684\u8fdc\u7a0b\u547d\u4ee4\u884c\u7ec8\u7aef - \u7f51\u7855\u4e92\u8054\u5e2e\u52a9\u4e2d\u5fc3<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.wsisp.com\/helps\/79940.html\" \/>\n<meta property=\"og:locale\" content=\"zh_CN\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"C++\u9879\u76ee\uff1a\u57fa\u4e8eLinux\u7cfb\u7edf\u548cTCP\u534f\u8bae\u7684\u8fdc\u7a0b\u547d\u4ee4\u884c\u7ec8\u7aef - \u7f51\u7855\u4e92\u8054\u5e2e\u52a9\u4e2d\u5fc3\" \/>\n<meta property=\"og:description\" content=\"\u524d\u9762\u6211\u4eec\u57fa\u4e8eTCP\u5b9e\u73b0\u4e86\u7b80\u5355\u4e86\u4e92\u52a8\u670d\u52a1\u5668\u3002\u4f46\u662f\u90a3\u662f\u8fdc\u8fdc\u4e0d\u591f\u7684&#xff0c;\u672c\u671f\u6211\u4eec\u5c06\u5b9e\u73b0\u4e00\u4e2a\u57fa\u4e8eTCP\u7684\u8fdc\u7a0b\u547d\u4ee4\u884c\u7ec8\u7aef \u76f8\u5173\u4ee3\u7801\u63d0\u4ea4\u81f3\u4f5c\u8005\u7684\u4e2a\u4ebagitee&#xff1a;\u697c\u7530\u8389\u5b50\/Linux\u5b66\u4e60\u559c\u6b22\u8bf7\u70b9\u4e2a\u8d5e\u8c22\u8c22 \u76ee\u5f55 \u65e5\u5fd7 \u7ebf\u7a0b\u6c60\u76f8\u5173 \u7f51\u7edc\u5ba2\u6237\u7aef \u547d\u4ee4 \u670d\u52a1\u5668 \u670d\u52a1\u5668\u4ee3\u7801 \u670d\u52a1\u5668\u8fd0\u884c \u5ba2\u6237\u7aef\u8fd0\u884c \u6d4b\u8bd5 \u65e5\u5fd7 #pragma once#include #include #include #inclu\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.wsisp.com\/helps\/79940.html\" \/>\n<meta property=\"og:site_name\" content=\"\u7f51\u7855\u4e92\u8054\u5e2e\u52a9\u4e2d\u5fc3\" \/>\n<meta property=\"article:published_time\" content=\"2026-03-03T11:50:57+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.wsisp.com\/helps\/wp-content\/uploads\/2026\/03\/20260303115054-69a6cb1e92dda.png\" \/>\n<meta name=\"author\" content=\"admin\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"\u4f5c\u8005\" \/>\n\t<meta name=\"twitter:data1\" content=\"admin\" \/>\n\t<meta name=\"twitter:label2\" content=\"\u9884\u8ba1\u9605\u8bfb\u65f6\u95f4\" \/>\n\t<meta name=\"twitter:data2\" content=\"16 \u5206\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"WebPage\",\"@id\":\"https:\/\/www.wsisp.com\/helps\/79940.html\",\"url\":\"https:\/\/www.wsisp.com\/helps\/79940.html\",\"name\":\"C++\u9879\u76ee\uff1a\u57fa\u4e8eLinux\u7cfb\u7edf\u548cTCP\u534f\u8bae\u7684\u8fdc\u7a0b\u547d\u4ee4\u884c\u7ec8\u7aef - \u7f51\u7855\u4e92\u8054\u5e2e\u52a9\u4e2d\u5fc3\",\"isPartOf\":{\"@id\":\"https:\/\/www.wsisp.com\/helps\/#website\"},\"datePublished\":\"2026-03-03T11:50:57+00:00\",\"dateModified\":\"2026-03-03T11:50:57+00:00\",\"author\":{\"@id\":\"https:\/\/www.wsisp.com\/helps\/#\/schema\/person\/358e386c577a3ab51c4493330a20ad41\"},\"breadcrumb\":{\"@id\":\"https:\/\/www.wsisp.com\/helps\/79940.html#breadcrumb\"},\"inLanguage\":\"zh-Hans\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/www.wsisp.com\/helps\/79940.html\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/www.wsisp.com\/helps\/79940.html#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"\u9996\u9875\",\"item\":\"https:\/\/www.wsisp.com\/helps\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"C++\u9879\u76ee\uff1a\u57fa\u4e8eLinux\u7cfb\u7edf\u548cTCP\u534f\u8bae\u7684\u8fdc\u7a0b\u547d\u4ee4\u884c\u7ec8\u7aef\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/www.wsisp.com\/helps\/#website\",\"url\":\"https:\/\/www.wsisp.com\/helps\/\",\"name\":\"\u7f51\u7855\u4e92\u8054\u5e2e\u52a9\u4e2d\u5fc3\",\"description\":\"\u9999\u6e2f\u670d\u52a1\u5668_\u9999\u6e2f\u4e91\u670d\u52a1\u5668\u8d44\u8baf_\u670d\u52a1\u5668\u5e2e\u52a9\u6587\u6863_\u670d\u52a1\u5668\u6559\u7a0b\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/www.wsisp.com\/helps\/?s={search_term_string}\"},\"query-input\":\"required name=search_term_string\"}],\"inLanguage\":\"zh-Hans\"},{\"@type\":\"Person\",\"@id\":\"https:\/\/www.wsisp.com\/helps\/#\/schema\/person\/358e386c577a3ab51c4493330a20ad41\",\"name\":\"admin\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"zh-Hans\",\"@id\":\"https:\/\/www.wsisp.com\/helps\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/gravatar.wp-china-yes.net\/avatar\/?s=96&d=mystery\",\"contentUrl\":\"https:\/\/gravatar.wp-china-yes.net\/avatar\/?s=96&d=mystery\",\"caption\":\"admin\"},\"sameAs\":[\"http:\/\/wp.wsisp.com\"],\"url\":\"https:\/\/www.wsisp.com\/helps\/author\/admin\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"C++\u9879\u76ee\uff1a\u57fa\u4e8eLinux\u7cfb\u7edf\u548cTCP\u534f\u8bae\u7684\u8fdc\u7a0b\u547d\u4ee4\u884c\u7ec8\u7aef - \u7f51\u7855\u4e92\u8054\u5e2e\u52a9\u4e2d\u5fc3","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.wsisp.com\/helps\/79940.html","og_locale":"zh_CN","og_type":"article","og_title":"C++\u9879\u76ee\uff1a\u57fa\u4e8eLinux\u7cfb\u7edf\u548cTCP\u534f\u8bae\u7684\u8fdc\u7a0b\u547d\u4ee4\u884c\u7ec8\u7aef - \u7f51\u7855\u4e92\u8054\u5e2e\u52a9\u4e2d\u5fc3","og_description":"\u524d\u9762\u6211\u4eec\u57fa\u4e8eTCP\u5b9e\u73b0\u4e86\u7b80\u5355\u4e86\u4e92\u52a8\u670d\u52a1\u5668\u3002\u4f46\u662f\u90a3\u662f\u8fdc\u8fdc\u4e0d\u591f\u7684&#xff0c;\u672c\u671f\u6211\u4eec\u5c06\u5b9e\u73b0\u4e00\u4e2a\u57fa\u4e8eTCP\u7684\u8fdc\u7a0b\u547d\u4ee4\u884c\u7ec8\u7aef \u76f8\u5173\u4ee3\u7801\u63d0\u4ea4\u81f3\u4f5c\u8005\u7684\u4e2a\u4ebagitee&#xff1a;\u697c\u7530\u8389\u5b50\/Linux\u5b66\u4e60\u559c\u6b22\u8bf7\u70b9\u4e2a\u8d5e\u8c22\u8c22 \u76ee\u5f55 \u65e5\u5fd7 \u7ebf\u7a0b\u6c60\u76f8\u5173 \u7f51\u7edc\u5ba2\u6237\u7aef \u547d\u4ee4 \u670d\u52a1\u5668 \u670d\u52a1\u5668\u4ee3\u7801 \u670d\u52a1\u5668\u8fd0\u884c \u5ba2\u6237\u7aef\u8fd0\u884c \u6d4b\u8bd5 \u65e5\u5fd7 #pragma once#include #include #include #inclu","og_url":"https:\/\/www.wsisp.com\/helps\/79940.html","og_site_name":"\u7f51\u7855\u4e92\u8054\u5e2e\u52a9\u4e2d\u5fc3","article_published_time":"2026-03-03T11:50:57+00:00","og_image":[{"url":"https:\/\/www.wsisp.com\/helps\/wp-content\/uploads\/2026\/03\/20260303115054-69a6cb1e92dda.png"}],"author":"admin","twitter_card":"summary_large_image","twitter_misc":{"\u4f5c\u8005":"admin","\u9884\u8ba1\u9605\u8bfb\u65f6\u95f4":"16 \u5206"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"WebPage","@id":"https:\/\/www.wsisp.com\/helps\/79940.html","url":"https:\/\/www.wsisp.com\/helps\/79940.html","name":"C++\u9879\u76ee\uff1a\u57fa\u4e8eLinux\u7cfb\u7edf\u548cTCP\u534f\u8bae\u7684\u8fdc\u7a0b\u547d\u4ee4\u884c\u7ec8\u7aef - \u7f51\u7855\u4e92\u8054\u5e2e\u52a9\u4e2d\u5fc3","isPartOf":{"@id":"https:\/\/www.wsisp.com\/helps\/#website"},"datePublished":"2026-03-03T11:50:57+00:00","dateModified":"2026-03-03T11:50:57+00:00","author":{"@id":"https:\/\/www.wsisp.com\/helps\/#\/schema\/person\/358e386c577a3ab51c4493330a20ad41"},"breadcrumb":{"@id":"https:\/\/www.wsisp.com\/helps\/79940.html#breadcrumb"},"inLanguage":"zh-Hans","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.wsisp.com\/helps\/79940.html"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/www.wsisp.com\/helps\/79940.html#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"\u9996\u9875","item":"https:\/\/www.wsisp.com\/helps"},{"@type":"ListItem","position":2,"name":"C++\u9879\u76ee\uff1a\u57fa\u4e8eLinux\u7cfb\u7edf\u548cTCP\u534f\u8bae\u7684\u8fdc\u7a0b\u547d\u4ee4\u884c\u7ec8\u7aef"}]},{"@type":"WebSite","@id":"https:\/\/www.wsisp.com\/helps\/#website","url":"https:\/\/www.wsisp.com\/helps\/","name":"\u7f51\u7855\u4e92\u8054\u5e2e\u52a9\u4e2d\u5fc3","description":"\u9999\u6e2f\u670d\u52a1\u5668_\u9999\u6e2f\u4e91\u670d\u52a1\u5668\u8d44\u8baf_\u670d\u52a1\u5668\u5e2e\u52a9\u6587\u6863_\u670d\u52a1\u5668\u6559\u7a0b","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.wsisp.com\/helps\/?s={search_term_string}"},"query-input":"required name=search_term_string"}],"inLanguage":"zh-Hans"},{"@type":"Person","@id":"https:\/\/www.wsisp.com\/helps\/#\/schema\/person\/358e386c577a3ab51c4493330a20ad41","name":"admin","image":{"@type":"ImageObject","inLanguage":"zh-Hans","@id":"https:\/\/www.wsisp.com\/helps\/#\/schema\/person\/image\/","url":"https:\/\/gravatar.wp-china-yes.net\/avatar\/?s=96&d=mystery","contentUrl":"https:\/\/gravatar.wp-china-yes.net\/avatar\/?s=96&d=mystery","caption":"admin"},"sameAs":["http:\/\/wp.wsisp.com"],"url":"https:\/\/www.wsisp.com\/helps\/author\/admin"}]}},"_links":{"self":[{"href":"https:\/\/www.wsisp.com\/helps\/wp-json\/wp\/v2\/posts\/79940","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.wsisp.com\/helps\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.wsisp.com\/helps\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.wsisp.com\/helps\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/www.wsisp.com\/helps\/wp-json\/wp\/v2\/comments?post=79940"}],"version-history":[{"count":0,"href":"https:\/\/www.wsisp.com\/helps\/wp-json\/wp\/v2\/posts\/79940\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.wsisp.com\/helps\/wp-json\/wp\/v2\/media\/79938"}],"wp:attachment":[{"href":"https:\/\/www.wsisp.com\/helps\/wp-json\/wp\/v2\/media?parent=79940"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.wsisp.com\/helps\/wp-json\/wp\/v2\/categories?post=79940"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.wsisp.com\/helps\/wp-json\/wp\/v2\/tags?post=79940"},{"taxonomy":"topic","embeddable":true,"href":"https:\/\/www.wsisp.com\/helps\/wp-json\/wp\/v2\/topic?post=79940"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}