中文亚洲精品无码_熟女乱子伦免费_人人超碰人人爱国产_亚洲熟妇女综合网

當(dāng)前位置: 首頁(yè) > news >正文

手機(jī)網(wǎng)站永久免費(fèi)制作seo如何優(yōu)化排名

手機(jī)網(wǎng)站永久免費(fèi)制作,seo如何優(yōu)化排名,梅州企業(yè)網(wǎng)站,大誠(chéng)設(shè)計(jì)網(wǎng)站建設(shè)文章目錄 1. Log.hpp-日志記錄器2. Daemon.hpp-守護(hù)進(jìn)程工具3. Protocol.hpp-通信協(xié)議解析器4. ServerCal.hpp-計(jì)算器服務(wù)處理器5. Socket.hpp-Socket通信封裝類(lèi)6. TcpServer.hpp-TCP服務(wù)器框架7. ClientCal.cc-計(jì)算器客戶端8. ServerCal.cc-計(jì)算器服務(wù)器9. 代碼時(shí)序1. 服務(wù)器啟…

文章目錄

    • 1. Log.hpp-日志記錄器
    • 2. Daemon.hpp-守護(hù)進(jìn)程工具
    • 3. Protocol.hpp-通信協(xié)議解析器
    • 4. ServerCal.hpp-計(jì)算器服務(wù)處理器
    • 5. Socket.hpp-Socket通信封裝類(lèi)
    • 6. TcpServer.hpp-TCP服務(wù)器框架
    • 7. ClientCal.cc-計(jì)算器客戶端
    • 8. ServerCal.cc-計(jì)算器服務(wù)器
    • 9. 代碼時(shí)序
      • 1. 服務(wù)器啟動(dòng)時(shí)序
      • 2. 客戶端連接時(shí)序
      • 3. 請(qǐng)求處理時(shí)序
      • 4. 完整的請(qǐng)求-響應(yīng)時(shí)序
      • 5. 數(shù)據(jù)處理時(shí)序
      • 6. 日志記錄時(shí)序
      • 7. 資源釋放時(shí)序


1. Log.hpp-日志記錄器

Log.hpp

// 1. 頭文件和宏定義
#pragma once  // 防止頭文件重復(fù)包含// 系統(tǒng)頭文件
#include <iostream>    // 標(biāo)準(zhǔn)輸入輸出
#include <time.h>      // 時(shí)間相關(guān)函數(shù)
#include <stdarg.h>    // 可變參數(shù)函數(shù)
#include <sys/types.h> // 基本系統(tǒng)數(shù)據(jù)類(lèi)型
#include <sys/stat.h>  // 文件狀態(tài)
#include <fcntl.h>     // 文件控制
#include <unistd.h>    // POSIX系統(tǒng)調(diào)用
#include <stdlib.h>    // 標(biāo)準(zhǔn)庫(kù)函數(shù)// 緩沖區(qū)大小
#define SIZE 1024// 日志級(jí)別定義
#define Info 0      // 普通信息
#define Debug 1     // 調(diào)試信息
#define Warning 2   // 警告信息
#define Error 3     // 錯(cuò)誤信息
#define Fatal 4     // 致命錯(cuò)誤// 日志輸出方式
#define Screen 1     // 輸出到屏幕
#define Onefile 2    // 輸出到單個(gè)文件
#define Classfile 3  // 根據(jù)日志級(jí)別輸出到不同文件// 默認(rèn)日志文件名
#define LogFile "log.txt"// 2. 日志類(lèi)定義
class Log {
private:int printMethod;      // 日志輸出方式std::string path;     // 日志文件路徑public:// 2.1 構(gòu)造函數(shù):設(shè)置默認(rèn)輸出方式Log() {printMethod = Screen;  // 默認(rèn)輸出到屏幕path = "./log/";       // 默認(rèn)日志目錄}// 2.2 設(shè)置日志輸出方式void Enable(int method) {printMethod = method;}// 2.3 日志級(jí)別轉(zhuǎn)字符串std::string levelToString(int level) {switch (level) {case Info:    return "Info";case Debug:   return "Debug";case Warning: return "Warning";case Error:   return "Error";case Fatal:   return "Fatal";default:      return "None";}}// 2.4 日志輸出函數(shù)void printLog(int level, const std::string &logtxt) {switch (printMethod) {case Screen:    // 輸出到屏幕std::cout << logtxt << std::endl;break;case Onefile:   // 輸出到單個(gè)文件printOneFile(LogFile, logtxt);break;case Classfile: // 根據(jù)日志級(jí)別輸出到不同文件printClassFile(level, logtxt);break;}}// 2.5 輸出到單個(gè)文件void printOneFile(const std::string &logname, const std::string &logtxt) {std::string _logname = path + logname;// 打開(kāi)文件:寫(xiě)入、創(chuàng)建(如果不存在)、追加模式int fd = open(_logname.c_str(), O_WRONLY | O_CREAT | O_APPEND, 0666);if (fd < 0) return;write(fd, logtxt.c_str(), logtxt.size());close(fd);}// 2.6 根據(jù)日志級(jí)別輸出到不同文件void printClassFile(int level, const std::string &logtxt) {std::string filename = LogFile;filename += ".";filename += levelToString(level); // 例如: "log.txt.Debug"printOneFile(filename, logtxt);}// 2.7 重載函數(shù)調(diào)用運(yùn)算符void operator()(int level, const char *format, ...) {// 1. 獲取當(dāng)前時(shí)間time_t t = time(nullptr);struct tm *ctime = localtime(&t);// 2. 格式化時(shí)間和日志級(jí)別信息char leftbuffer[SIZE];snprintf(leftbuffer, sizeof(leftbuffer), "[%s][%d-%d-%d %d:%d:%d]", levelToString(level).c_str(),ctime->tm_year + 1900, ctime->tm_mon + 1, ctime->tm_mday,ctime->tm_hour, ctime->tm_min, ctime->tm_sec);// 3. 處理可變參數(shù)va_list s;va_start(s, format);char rightbuffer[SIZE];vsnprintf(rightbuffer, sizeof(rightbuffer), format, s);va_end(s);// 4. 組合完整的日志信息char logtxt[SIZE * 2];snprintf(logtxt, sizeof(logtxt), "%s %s", leftbuffer, rightbuffer);// 5. 輸出日志printLog(level, logtxt);}
};// 3. 創(chuàng)建全局日志對(duì)象
Log lg;

2. Daemon.hpp-守護(hù)進(jìn)程工具

Daemon.hpp

將進(jìn)程轉(zhuǎn)換為守護(hù)進(jìn)程的工具類(lèi)

#pragma once  // 防止頭文件重復(fù)包含#include <iostream>    // 標(biāo)準(zhǔn)輸入輸出
#include <cstdlib>     // exit()函數(shù)
#include <unistd.h>    // fork(), setsid(), chdir()等系統(tǒng)調(diào)用
#include <signal.h>    // 信號(hào)處理
#include <string>      // 字符串類(lèi)
#include <sys/types.h> // 基本系統(tǒng)數(shù)據(jù)類(lèi)型
#include <sys/stat.h>  // 文件狀態(tài)
#include <fcntl.h>     // 文件控制選項(xiàng)// 定義空設(shè)備文件路徑
const std::string nullfile = "/dev/null";// 守護(hù)進(jìn)程化函數(shù),參數(shù)cwd為工作目錄
void Daemon(const std::string &cwd = "")
{// 1. 忽略一些可能的干擾信號(hào)signal(SIGCLD, SIG_IGN);  // 忽略子進(jìn)程狀態(tài)改變信號(hào)signal(SIGPIPE, SIG_IGN); // 忽略管道破裂信號(hào)signal(SIGSTOP, SIG_IGN); // 忽略停止進(jìn)程信號(hào)// 2. 創(chuàng)建守護(hù)進(jìn)程if (fork() > 0)  // 父進(jìn)程退出exit(0);setsid();        // 創(chuàng)建新會(huì)話,使進(jìn)程成為會(huì)話組長(zhǎng)// 3. 改變工作目錄if (!cwd.empty())              // 如果指定了工作目錄chdir(cwd.c_str());        // 切換到指定目錄// 4. 重定向標(biāo)準(zhǔn)輸入輸出到/dev/nullint fd = open(nullfile.c_str(), O_RDWR); // 以讀寫(xiě)方式打開(kāi)/dev/nullif(fd > 0){dup2(fd, 0);  // 重定向標(biāo)準(zhǔn)輸入dup2(fd, 1);  // 重定向標(biāo)準(zhǔn)輸出dup2(fd, 2);  // 重定向標(biāo)準(zhǔn)錯(cuò)誤close(fd);    // 關(guān)閉文件描述符}
}

3. Protocol.hpp-通信協(xié)議解析器

Protocol.hpp

定義客戶端服務(wù)器間通信協(xié)議,處理消息的序列化和反序列化

#pragma once#include <iostream>
#include <string>
#include <jsoncpp/json/json.h>  // JSON序列化支持// #define MySelf 1  // 自定義協(xié)議開(kāi)關(guān)// 定義分隔符
const std::string blank_space_sep = " ";  // 空格分隔符
const std::string protocol_sep = "\n";    // 協(xié)議分隔符// 協(xié)議編碼函數(shù):將內(nèi)容封裝成格式化的報(bào)文
std::string Encode(std::string &content)
{std::string package = std::to_string(content.size());  // 內(nèi)容長(zhǎng)度package += protocol_sep;   // 添加分隔符package += content;        // 添加內(nèi)容package += protocol_sep;   // 添加分隔符return package;
}// 協(xié)議解碼函數(shù):從報(bào)文中提取內(nèi)容
// 格式:"len"\n"x op y"\nXXXXXX
bool Decode(std::string &package, std::string *content)
{// 查找第一個(gè)分隔符位置std::size_t pos = package.find(protocol_sep);if(pos == std::string::npos) return false;// 獲取長(zhǎng)度字符串并轉(zhuǎn)換std::string len_str = package.substr(0, pos);std::size_t len = std::stoi(len_str);// 計(jì)算完整報(bào)文長(zhǎng)度std::size_t total_len = len_str.size() + len + 2;if(package.size() < total_len) return false;// 提取內(nèi)容*content = package.substr(pos+1, len);// 移除已處理的報(bào)文package.erase(0, total_len);return true;
}// 請(qǐng)求類(lèi):處理計(jì)算請(qǐng)求
class Request
{
public:// 構(gòu)造函數(shù)Request(int data1, int data2, char oper) : x(data1), y(data2), op(oper) {}Request() {}public:// 序列化:將請(qǐng)求對(duì)象轉(zhuǎn)換為字符串bool Serialize(std::string *out){
#ifdef MySelf// 自定義協(xié)議格式:"x op y"std::string s = std::to_string(x);s += blank_space_sep;s += op;s += blank_space_sep;s += std::to_string(y);*out = s;
#else// JSON格式Json::Value root;root["x"] = x;root["y"] = y;root["op"] = op;Json::StyledWriter w;*out = w.write(root);
#endifreturn true;}// 反序列化:將字符串解析為請(qǐng)求對(duì)象bool Deserialize(const std::string &in){
#ifdef MySelf// 解析自定義協(xié)議格式std::size_t left = in.find(blank_space_sep);if (left == std::string::npos) return false;std::string part_x = in.substr(0, left);std::size_t right = in.rfind(blank_space_sep);if (right == std::string::npos) return false;std::string part_y = in.substr(right + 1);if (left + 2 != right) return false;op = in[left + 1];x = std::stoi(part_x);y = std::stoi(part_y);
#else// 解析JSON格式Json::Value root;Json::Reader r;r.parse(in, root);x = root["x"].asInt();y = root["y"].asInt();op = root["op"].asInt();
#endifreturn true;}void DebugPrint(){std::cout << "新請(qǐng)求構(gòu)建完成: " << x << op << y << "=?" << std::endl;}public:int x;      // 第一個(gè)操作數(shù)int y;      // 第二個(gè)操作數(shù)char op;    // 運(yùn)算符
};// 響應(yīng)類(lèi):處理計(jì)算響應(yīng)
class Response
{// [響應(yīng)類(lèi)的實(shí)現(xiàn)與Request類(lèi)似,只是處理result和code兩個(gè)字段]// result: 計(jì)算結(jié)果// code: 狀態(tài)碼,0表示成功,非0表示各種錯(cuò)誤
};

4. ServerCal.hpp-計(jì)算器服務(wù)處理器

ServerCal.hpp

實(shí)現(xiàn)服務(wù)器端的核心計(jì)算邏輯

#pragma once
#include <iostream>
#include "Protocol.hpp"// 定義錯(cuò)誤碼枚舉
enum
{Div_Zero = 1,    // 除零錯(cuò)誤Mod_Zero,        // 取模零錯(cuò)誤Other_Oper       // 未知運(yùn)算符錯(cuò)誤
};// 服務(wù)器端計(jì)算器類(lèi)
class ServerCal
{
public:ServerCal() {}// 核心計(jì)算功能輔助函數(shù)Response CalculatorHelper(const Request &req){Response resp(0, 0);  // 初始化響應(yīng)對(duì)象,默認(rèn)結(jié)果0,狀態(tài)碼0// 根據(jù)運(yùn)算符進(jìn)行相應(yīng)計(jì)算switch (req.op){case '+':    // 加法運(yùn)算resp.result = req.x + req.y;break;case '-':    // 減法運(yùn)算resp.result = req.x - req.y;break;case '*':    // 乘法運(yùn)算resp.result = req.x * req.y;break;case '/':    // 除法運(yùn)算{if (req.y == 0)   // 處理除零錯(cuò)誤resp.code = Div_Zero;elseresp.result = req.x / req.y;}break;case '%':    // 取模運(yùn)算{if (req.y == 0)   // 處理取模零錯(cuò)誤resp.code = Mod_Zero;elseresp.result = req.x % req.y;}break;default:     // 未知運(yùn)算符resp.code = Other_Oper;break;}return resp;}// 主計(jì)算函數(shù):處理完整的請(qǐng)求-響應(yīng)流程// 輸入格式示例:"len"\n"10 + 20"\nstd::string Calculator(std::string &package){// 1. 解碼請(qǐng)求包std::string content;bool r = Decode(package, &content);  // 解析出實(shí)際內(nèi)容if (!r)return "";// 2. 反序列化請(qǐng)求內(nèi)容Request req;r = req.Deserialize(content);  // 將內(nèi)容轉(zhuǎn)換為請(qǐng)求對(duì)象if (!r)return "";// 3. 執(zhí)行計(jì)算content = "";  // 清空content準(zhǔn)備存儲(chǔ)響應(yīng)Response resp = CalculatorHelper(req);  // 調(diào)用計(jì)算輔助函數(shù)// 4. 構(gòu)建響應(yīng)包resp.Serialize(&content);   // 序列化響應(yīng)對(duì)象content = Encode(content);  // 編碼響應(yīng)內(nèi)容return content;  // 返回完整的響應(yīng)包}~ServerCal() {}
};

5. Socket.hpp-Socket通信封裝類(lèi)

Socket.hpp

封裝底層Socket網(wǎng)絡(luò)通信功能

#pragma once#include <iostream>
#include <string>
#include <unistd.h>     // Unix標(biāo)準(zhǔn)函數(shù)
#include <cstring>      // memset等字符串操作
#include <sys/types.h>  // 基本系統(tǒng)數(shù)據(jù)類(lèi)型
#include <sys/stat.h>   // 文件狀態(tài)
#include <sys/socket.h> // Socket接口
#include <arpa/inet.h>  // IP地址轉(zhuǎn)換函數(shù)
#include <netinet/in.h> // IPv4地址結(jié)構(gòu)
#include "Log.hpp"      // 日志功能// 錯(cuò)誤碼枚舉
enum
{SocketErr = 2,  // Socket創(chuàng)建錯(cuò)誤BindErr,        // 綁定錯(cuò)誤ListenErr,      // 監(jiān)聽(tīng)錯(cuò)誤
};// 監(jiān)聽(tīng)隊(duì)列長(zhǎng)度
const int backlog = 10;// Socket封裝類(lèi)
class Sock
{
public:Sock() {}~Sock() {}public:// 創(chuàng)建Socketvoid Socket(){// 創(chuàng)建TCP Socketsockfd_ = socket(AF_INET, SOCK_STREAM, 0);if (sockfd_ < 0){// 創(chuàng)建失敗,記錄錯(cuò)誤并退出lg(Fatal, "socker error, %s: %d", strerror(errno), errno);exit(SocketErr);}}// 綁定端口void Bind(uint16_t port){struct sockaddr_in local;memset(&local, 0, sizeof(local));local.sin_family = AF_INET;          // IPv4local.sin_port = htons(port);        // 主機(jī)字節(jié)序轉(zhuǎn)網(wǎng)絡(luò)字節(jié)序local.sin_addr.s_addr = INADDR_ANY;  // 綁定所有網(wǎng)卡// 綁定地址和端口if (bind(sockfd_, (struct sockaddr *)&local, sizeof(local)) < 0){lg(Fatal, "bind error, %s: %d", strerror(errno), errno);exit(BindErr);}}// 開(kāi)始監(jiān)聽(tīng)void Listen(){if (listen(sockfd_, backlog) < 0){lg(Fatal, "listen error, %s: %d", strerror(errno), errno);exit(ListenErr);}}// 接受新連接int Accept(std::string *clientip, uint16_t *clientport){struct sockaddr_in peer;socklen_t len = sizeof(peer);// 接受客戶端連接int newfd = accept(sockfd_, (struct sockaddr*)&peer, &len);if(newfd < 0){lg(Warning, "accept error, %s: %d", strerror(errno), errno);return -1;}// 獲取客戶端IP和端口char ipstr[64];inet_ntop(AF_INET, &peer.sin_addr, ipstr, sizeof(ipstr));*clientip = ipstr;*clientport = ntohs(peer.sin_port);return newfd;}// 連接服務(wù)器bool Connect(const std::string &ip, const uint16_t &port){struct sockaddr_in peer;memset(&peer, 0, sizeof(peer));peer.sin_family = AF_INET;peer.sin_port = htons(port);inet_pton(AF_INET, ip.c_str(), &(peer.sin_addr));// 連接服務(wù)器int n = connect(sockfd_, (struct sockaddr*)&peer, sizeof(peer));if(n == -1) {std::cerr << "connect to " << ip << ":" << port << " error" << std::endl;return false;}return true;}// 關(guān)閉Socketvoid Close(){close(sockfd_);}// 獲取文件描述符int Fd(){return sockfd_;}private:int sockfd_;  // Socket文件描述符
};

6. TcpServer.hpp-TCP服務(wù)器框架

TcpServer.hpp

實(shí)現(xiàn)TCP服務(wù)器的主框架

#pragma once
#include <functional>
#include <string>
#include <signal.h>
#include "Log.hpp"
#include "Socket.hpp"// 定義回調(diào)函數(shù)類(lèi)型:接收字符串參數(shù),返回字符串
using func_t = std::function<std::string(std::string &package)>;// TCP服務(wù)器類(lèi)
class TcpServer
{
public:// 構(gòu)造函數(shù):初始化端口和回調(diào)函數(shù)TcpServer(uint16_t port, func_t callback) : port_(port), callback_(callback){}// 初始化服務(wù)器bool InitServer(){listensock_.Socket();      // 創(chuàng)建Socketlistensock_.Bind(port_);   // 綁定端口listensock_.Listen();      // 開(kāi)始監(jiān)聽(tīng)lg(Info, "init server .... done");return true;}// 啟動(dòng)服務(wù)器void Start(){// 忽略子進(jìn)程退出和管道破裂信號(hào)signal(SIGCHLD, SIG_IGN);signal(SIGPIPE, SIG_IGN);// 主循環(huán)while (true){// 接受新的客戶端連接std::string clientip;uint16_t clientport;int sockfd = listensock_.Accept(&clientip, &clientport);if (sockfd < 0)continue;// 記錄新連接信息lg(Info, "accept a new link, sockfd: %d, clientip: %s, clientport: %d", sockfd, clientip.c_str(), clientport);// 創(chuàng)建子進(jìn)程處理客戶端請(qǐng)求if (fork() == 0){listensock_.Close();  // 子進(jìn)程關(guān)閉監(jiān)聽(tīng)socketstd::string inbuffer_stream;  // 輸入緩沖區(qū)// 處理客戶端數(shù)據(jù)while (true){// 讀取客戶端數(shù)據(jù)char buffer[1280];ssize_t n = read(sockfd, buffer, sizeof(buffer));if (n > 0)  // 讀取成功{buffer[n] = 0;  // 字符串結(jié)束符inbuffer_stream += buffer;  // 追加到輸入緩沖區(qū)// 調(diào)試日志lg(Debug, "debug:\n%s", inbuffer_stream.c_str());// 處理所有完整的請(qǐng)求while (true){// 調(diào)用回調(diào)函數(shù)處理請(qǐng)求std::string info = callback_(inbuffer_stream);if (info.empty())  // 沒(méi)有完整請(qǐng)求則退出循環(huán)break;// 調(diào)試日志lg(Debug, "debug, response:\n%s", info.c_str());lg(Debug, "debug:\n%s", inbuffer_stream.c_str());// 發(fā)送響應(yīng)給客戶端write(sockfd, info.c_str(), info.size());}}else if (n == 0)  // 客戶端關(guān)閉連接break;else  // 讀取錯(cuò)誤break;}exit(0);  // 子進(jìn)程退出}close(sockfd);  // 父進(jìn)程關(guān)閉客戶端socket}}~TcpServer(){}private:uint16_t port_;      // 服務(wù)器端口Sock listensock_;    // 監(jiān)聽(tīng)socketfunc_t callback_;    // 處理請(qǐng)求的回調(diào)函數(shù)
};

7. ClientCal.cc-計(jì)算器客戶端

ClientCal.cc

實(shí)現(xiàn)客戶端程序,發(fā)送計(jì)算請(qǐng)求

#include <iostream>
#include <string>
#include <ctime>
#include <cassert>
#include <unistd.h>
#include "Socket.hpp"
#include "Protocol.hpp"// 打印使用方法
static void Usage(const std::string &proc)
{std::cout << "\nUsage: " << proc << " serverip serverport\n"<< std::endl;
}// 客戶端主程序:./clientcal ip port
int main(int argc, char *argv[])
{// 檢查命令行參數(shù)if (argc != 3){Usage(argv[0]);exit(0);}// 獲取服務(wù)器IP和端口std::string serverip = argv[1];uint16_t serverport = std::stoi(argv[2]);// 創(chuàng)建并連接SocketSock sockfd;sockfd.Socket();bool r = sockfd.Connect(serverip, serverport);if(!r) return 1;// 初始化隨機(jī)數(shù)種子(使用時(shí)間和進(jìn)程ID)srand(time(nullptr) ^ getpid());int cnt = 1;// 定義可用的運(yùn)算符const std::string opers = "+-*/%=-=&^";// 輸入緩沖區(qū)std::string inbuffer_stream;// 進(jìn)行10次測(cè)試while(cnt <= 10){std::cout << "===============第" << cnt << "次測(cè)試....., " << "===============" << std::endl;// 隨機(jī)生成測(cè)試數(shù)據(jù)int x = rand() % 100 + 1;usleep(1234);  // 微秒級(jí)延遲int y = rand() % 100;usleep(4321);char oper = opers[rand()%opers.size()];  // 隨機(jī)選擇運(yùn)算符// 創(chuàng)建請(qǐng)求對(duì)象Request req(x, y, oper);req.DebugPrint();  // 打印請(qǐng)求信息// 序列化請(qǐng)求std::string package;req.Serialize(&package);// 編碼請(qǐng)求包package = Encode(package);// 發(fā)送請(qǐng)求到服務(wù)器write(sockfd.Fd(), package.c_str(), package.size());// 讀取服務(wù)器響應(yīng)char buffer[128];ssize_t n = read(sockfd.Fd(), buffer, sizeof(buffer));if(n > 0){buffer[n] = 0;  // 字符串結(jié)束符inbuffer_stream += buffer;  // 追加到輸入緩沖區(qū)std::cout << inbuffer_stream << std::endl;// 解碼響應(yīng)std::string content;bool r = Decode(inbuffer_stream, &content);assert(r);  // 確保解碼成功// 反序列化響應(yīng)Response resp;r = resp.Deserialize(content);assert(r);  // 確保反序列化成功// 打印響應(yīng)結(jié)果resp.DebugPrint();}std::cout << "=================================================" << std::endl;sleep(1);  // 延時(shí)1秒cnt++;}// 關(guān)閉連接sockfd.Close();return 0;
}

8. ServerCal.cc-計(jì)算器服務(wù)器

ServerCal.cc

實(shí)現(xiàn)服務(wù)器程序,處理客戶端請(qǐng)求

#include "TcpServer.hpp"
#include "ServerCal.hpp"
#include <unistd.h>
// #include "Daemon.hpp"// 打印使用方法
static void Usage(const std::string &proc)
{std::cout << "\nUsage: " << proc << " port\n" << std::endl; 
}// 服務(wù)器主程序:./servercal 8080
int main(int argc, char *argv[])
{// 檢查命令行參數(shù)if(argc != 2){Usage(argv[0]);exit(0);}// 獲取端口號(hào)uint16_t port = std::stoi(argv[1]);// 創(chuàng)建計(jì)算器服務(wù)對(duì)象ServerCal cal;// 創(chuàng)建TCP服務(wù)器對(duì)象// 使用std::bind綁定Calculator方法作為回調(diào)函數(shù)TcpServer *tsvp = new TcpServer(port, std::bind(&ServerCal::Calculator, &cal, std::placeholders::_1));// 初始化服務(wù)器tsvp->InitServer();// 將進(jìn)程變成守護(hù)進(jìn)程// Daemon();  // 自定義守護(hù)進(jìn)程函數(shù)daemon(0, 0); // 系統(tǒng)提供的守護(hù)進(jìn)程函數(shù)// 第一個(gè)參數(shù)0:切換工作目錄到根目錄// 第二個(gè)參數(shù)0:關(guān)閉標(biāo)準(zhǔn)輸入輸出和錯(cuò)誤流// 啟動(dòng)服務(wù)器tsvp->Start();/* 以下是測(cè)試代碼,已注釋// 測(cè)試響應(yīng)序列化和反序列化Response resp(1000, 0);std::string content;resp.Serialize(&content);std::cout << content << std::endl;std::string package = Encode(content);std::cout << package;content = "";bool r = Decode(package, &content);std::cout << content << std::endl;Response temp;temp.Deserialize(content);std::cout << temp.result << std::endl;std::cout << temp.code << std::endl;// 測(cè)試請(qǐng)求序列化和反序列化Request req(12364566, 43454356, '+');std::string s;req.Serialize(&s);s = Encode(s);std::cout << s;std::string content;bool r = Decode(s, &content);std::cout << content << std::endl;Request temp;temp.Deserialize(content);std::cout << temp.x << std::endl;std::cout << temp.op << std::endl;std::cout << temp.y << std::endl;*/return 0;
}

9. 代碼時(shí)序

1. 服務(wù)器啟動(dòng)時(shí)序

ServerCal.cc (主程序)↓
1. 解析命令行參數(shù)(端口號(hào))↓
2. 創(chuàng)建ServerCal對(duì)象↓
3. 創(chuàng)建TcpServer對(duì)象|→ 綁定Calculator回調(diào)函數(shù)↓
4. 初始化服務(wù)器(InitServer)|→ 創(chuàng)建Socket|→ 綁定端口|→ 開(kāi)始監(jiān)聽(tīng)↓
5. 守護(hù)進(jìn)程化|→ 后臺(tái)運(yùn)行|→ 重定向標(biāo)準(zhǔn)IO↓
6. 啟動(dòng)服務(wù)器(Start)|→ 注冊(cè)信號(hào)處理|→ 進(jìn)入主循環(huán)

2. 客戶端連接時(shí)序

TcpServer::Start (主循環(huán))↓
1. Accept等待連接↓
2. 收到新連接|→ 獲取客戶端信息(IP/端口)|→ 記錄連接日志↓
3. Fork子進(jìn)程|→ 子進(jìn)程:處理客戶端請(qǐng)求|→ 父進(jìn)程:繼續(xù)Accept新連接

3. 請(qǐng)求處理時(shí)序

子進(jìn)程處理流程↓
1. 讀取客戶端數(shù)據(jù)|→ 追加到輸入緩沖區(qū)↓
2. 解析協(xié)議(Protocol::Decode)|→ 提取消息長(zhǎng)度|→ 檢查完整性↓
3. 調(diào)用回調(diào)函數(shù)(Calculator)|→ 反序列化請(qǐng)求|→ 執(zhí)行計(jì)算|→ 序列化響應(yīng)↓
4. 發(fā)送響應(yīng)|→ 編碼響應(yīng)包|→ 寫(xiě)入socket

4. 完整的請(qǐng)求-響應(yīng)時(shí)序

客戶端                    服務(wù)器                    子進(jìn)程|                        |                         ||------ 連接請(qǐng)求 ------>|                         ||                        |--- fork() ------------->||                        |                         ||------ 計(jì)算請(qǐng)求 ----------------------→          ||                        |                         ||                        |        1. 解析請(qǐng)求      ||                        |        2. 執(zhí)行計(jì)算      ||                        |        3. 構(gòu)造響應(yīng)      ||                        |                         ||<----- 計(jì)算結(jié)果 ----------------------           ||                        |                         ||------ 關(guān)閉連接 ------>|                         ||                        |                         |

5. 數(shù)據(jù)處理時(shí)序

Request數(shù)據(jù)流↓
1. 序列化(Serialize)|→ JSON格式或自定義格式↓
2. 協(xié)議封裝(Encode)|→ 添加長(zhǎng)度和分隔符↓
3. 網(wǎng)絡(luò)傳輸|→ write/read↓
4. 協(xié)議解析(Decode)|→ 提取有效載荷↓
5. 反序列化(Deserialize)|→ 還原對(duì)象數(shù)據(jù)

6. 日志記錄時(shí)序

Log系統(tǒng)↓
1. 生成日志內(nèi)容|→ 時(shí)間戳|→ 日志級(jí)別|→ 具體信息↓
2. 根據(jù)配置輸出|→ 屏幕顯示|→ 單一文件|→ 分級(jí)文件

7. 資源釋放時(shí)序

程序退出流程↓
1. 子進(jìn)程退出|→ 關(guān)閉客戶端socket|→ exit(0)↓
2. 父進(jìn)程清理|→ SIGCHLD信號(hào)處理|→ 僵尸進(jìn)程回收

這種時(shí)序設(shè)計(jì)的優(yōu)點(diǎn):

  1. 多進(jìn)程并發(fā)處理請(qǐng)求
  2. 父子進(jìn)程職責(zé)明確
  3. 協(xié)議設(shè)計(jì)清晰
  4. 資源管理完善
  5. 錯(cuò)誤處理周到

主要的時(shí)序特點(diǎn)是采用了經(jīng)典的多進(jìn)程并發(fā)服務(wù)器模型,每個(gè)客戶端連接由獨(dú)立的子進(jìn)程處理,保證了請(qǐng)求處理的隔離性和可靠性。

http://www.risenshineclean.com/news/11456.html

相關(guān)文章:

  • 企業(yè)專(zhuān)業(yè)網(wǎng)站建設(shè)搜索引擎推廣簡(jiǎn)稱(chēng)
  • 建站快車(chē)打電話百度云鏈接
  • 湖南微信網(wǎng)站建設(shè)百度地圖推廣電話
  • 網(wǎng)站開(kāi)發(fā)環(huán)境有什么網(wǎng)店?duì)I銷(xiāo)
  • 網(wǎng)站制作協(xié)議書(shū)阿里數(shù)據(jù)
  • 哈爾濱網(wǎng)站建設(shè)價(jià)格市場(chǎng)營(yíng)銷(xiāo)方案范文5篇
  • 前端學(xué)習(xí)手機(jī)網(wǎng)站開(kāi)發(fā)嗎網(wǎng)絡(luò)營(yíng)銷(xiāo)的企業(yè)有哪些
  • 做網(wǎng)站開(kāi)發(fā)的公司哪家好search搜索引擎
  • wordpress手機(jī)類(lèi)主題東莞seo優(yōu)化案例
  • 怎么做網(wǎng)站賺錢(qián)放廣告互聯(lián)網(wǎng)營(yíng)銷(xiāo)師報(bào)名入口官網(wǎng)
  • 網(wǎng)站頁(yè)面字體設(shè)置剛剛地震最新消息今天
  • 內(nèi)部網(wǎng)站做域名解析到端口發(fā)布軟文
  • 怎么建設(shè)批量模板網(wǎng)站搜索引擎優(yōu)化是做什么
  • 網(wǎng)站強(qiáng)制字體wordpress百度推廣基木魚(yú)
  • 廣州做網(wǎng)站的長(zhǎng)春網(wǎng)站建設(shè)制作
  • 做網(wǎng)站的機(jī)構(gòu)免費(fèi)域名解析平臺(tái)
  • 淄博外貿(mào)網(wǎng)站建設(shè)公司網(wǎng)站seo排名優(yōu)化軟件
  • 北京定制網(wǎng)站開(kāi)發(fā)公司軍事新聞今日最新消息
  • 找人做網(wǎng)站需要注意網(wǎng)絡(luò)營(yíng)銷(xiāo)的現(xiàn)狀分析
  • 集團(tuán)做網(wǎng)站方案制作包含哪些方面如何制作自己的鏈接
  • wordpress 調(diào)用分類(lèi)目錄描述金華seo扣費(fèi)
  • 一個(gè)網(wǎng)站按鈕怎么做圖片優(yōu)化
  • 網(wǎng)站優(yōu)化工作怎么樣seo和點(diǎn)擊付費(fèi)的區(qū)別
  • 可以做皮膚測(cè)試的網(wǎng)站關(guān)鍵詞排名優(yōu)化如何
  • 網(wǎng)站建設(shè)找蓋亞科技營(yíng)銷(xiāo)網(wǎng)站模板
  • 證件照制作免費(fèi)版優(yōu)化網(wǎng)站seo策略
  • 如何提高網(wǎng)站點(diǎn)擊率怎么做合肥百度seo代理
  • 中國(guó)建設(shè)銀行余額查詢?nèi)肟趕eo推廣人員
  • 網(wǎng)站在香港能備案嗎沈陽(yáng)seo關(guān)鍵詞
  • 杭州品牌網(wǎng)站開(kāi)發(fā)東莞網(wǎng)站推廣的公司