当前位置: 首页 > wzjs >正文

建设微商城网站软文文案

建设微商城网站,软文文案,建网站租服务器多少钱,wordpress 读取最新文章多进程网络服务端详细说明文档 一、概述 本项目实现了一个基于多进程的 TCP 网络服务端,主要用于处理多个客户端的连接请求。为了提高代码的可维护性和可复用性,分成了头文件(.h)和多个源文件(.cpp)。具体…

多进程网络服务端详细说明文档

一、概述

本项目实现了一个基于多进程的 TCP 网络服务端,主要用于处理多个客户端的连接请求。为了提高代码的可维护性和可复用性,分成了头文件(.h)和多个源文件(.cpp)。具体包含 ctcpserver.hctcpserver.cppmulti_process_network_server.cpp 三个文件。

二、文件结构及功能
1. ctcpserver.h
  • 功能:该头文件主要用于声明 ctcpserver 类,定义了类的成员变量和成员函数接口,起到了对类的功能进行抽象和声明的作用,方便其他源文件引用该类。
  • 关键内容
    • 成员变量
      • m_listenfd:监听的 socket 描述符,-1 表示未初始化。
      • m_clientfd:客户端连接的 socket 描述符,-1 表示客户端未连接。
      • m_clientip:客户端的 IP 地址,以字符串形式存储。
      • m_port:服务端用于通信的端口号。
    • 成员函数声明:包含了构造函数、析构函数以及一系列用于初始化服务端、接受客户端连接、发送和接收数据、关闭 socket 等操作的函数声明。
class ctcpserver {
private:int m_listenfd;int m_clientfd;std::string m_clientip;unsigned short m_port;
public:ctcpserver();~ctcpserver();bool initserver(const unsigned short in_port);bool accept();const std::string & clientip() const;bool send(const std::string &buffer);bool recv(std::string &buffer, const size_t maxlen);bool closelisten();bool closeclient();
};
2. ctcpserver.cpp
  • 功能:该源文件实现了 ctcpserver.h 中声明的 ctcpserver 类的所有成员函数,是类的具体实现部分。
  • 关键函数及实现细节
    • 构造函数 ctcpserver::ctcpserver():初始化 m_listenfdm_clientfd-1,表示初始状态下监听 socket 和客户端 socket 未初始化。
    • 析构函数 ctcpserver::~ctcpserver():调用 closelisten()closeclient() 函数,确保在对象销毁时关闭监听 socket 和客户端 socket,释放资源。
    • initserver 函数
      • 使用 socket() 函数创建一个 TCP 套接字,使用 IPv4 协议(AF_INET)和面向连接的 TCP 协议(SOCK_STREAM)。
      • 填充 sockaddr_in 结构体,设置协议族、端口号(使用 htons() 进行字节序转换)和 IP 地址(INADDR_ANY 表示监听所有可用 IP)。
      • 使用 bind() 函数将套接字绑定到指定的 IP 和端口,若绑定失败则关闭套接字并返回 false
      • 使用 listen() 函数将套接字设置为监听状态,允许最多 5 个客户端连接请求进入队列,若设置失败则关闭套接字并返回 false
    • accept 函数
      • 使用 accept() 函数从监听队列中取出一个客户端连接请求,返回一个新的套接字描述符用于与该客户端通信。
      • 使用 inet_ntoa() 函数将客户端的 IP 地址从大端序转换为字符串格式并存储在 m_clientip 中。
    • send 函数:检查客户端 socket 是否有效,若有效则使用 send() 函数向客户端发送数据。
    • recv 函数
      • 清空接收缓冲区并调整其大小为指定的最大长度。
      • 使用 recv() 函数接收客户端发送的数据,若接收失败则清空缓冲区并返回 false,否则根据实际接收的字节数调整缓冲区大小并返回 true
    • closelisten 函数:关闭监听 socket 并将 m_listenfd 设置为 -1
    • closeclient 函数:关闭客户端 socket 并将 m_clientfd 设置为 -1
3. multi_process_network_server.cpp
  • 功能:该文件是整个服务端程序的入口,包含 main 函数和信号处理函数,负责初始化服务端、处理客户端连接和信号处理。
  • 关键流程及函数说明
    • main 函数
      • 参数检查:检查命令行参数是否正确,若不正确则输出使用说明并退出程序。
      • 信号处理设置
        • 使用 for 循环忽略所有信号,避免程序被不必要的信号干扰,同时解决僵尸进程问题。
        • 设置 SIGTERMSIGINT 信号的处理函数为 FathEXIT,允许通过 kill 命令或 Ctrl + C 正常终止程序。
      • 服务端初始化:调用 tcpserver.initserver() 函数初始化服务端监听 socket,若初始化失败则输出错误信息并退出。
      • 客户端连接处理
        • 使用 while 循环不断接受客户端连接请求,若接受失败则输出错误信息并退出。
        • 调用 fork() 函数创建子进程,父进程关闭客户端 socket 并继续等待下一个客户端连接;子进程关闭监听 socket,重新设置信号处理函数,并与客户端进行通信。
      • 子进程通信处理
        • 循环接收客户端发送的数据,若接收失败则退出循环。
        • 接收到数据后,向客户端发送 “ok” 作为响应,若发送失败则退出循环。
    • 信号处理函数
      • FathEXIT 函数:处理父进程接收到的 SIGTERMSIGINT 信号。首先屏蔽这两个信号,防止信号处理函数被中断;输出父进程退出信息,使用 kill(0, SIGTERM) 向所有子进程发送终止信号;关闭监听 socket 并退出父进程。
      • ChldEXIT 函数:处理子进程接收到的 SIGTERM 信号。屏蔽 SIGINTSIGTERM 信号,输出子进程退出信息,关闭客户端 socket 并退出子进程。
四、注意事项
  • 资源管理:每个子进程在处理完与客户端的通信后必须退出,否则会继续进入 accept 函数,导致错误。同时,要确保在程序结束时正确关闭所有 socket 资源,避免资源泄漏。
  • 信号处理:信号处理函数中屏蔽了 SIGINTSIGTERM 信号,防止信号处理函数被中断,确保程序的稳定性。
  • 高并发场景:该程序使用多进程处理客户端连接,每个客户端连接会创建一个新的子进程,可能会消耗较多的系统资源。在高并发场景下,可以考虑使用多线程或异步 I/O 技术进行优化。

1. ctcpserver.h 头文件

#ifndef CTCP_SERVER_H
#define CTCP_SERVER_H#include <iostream>
#include <string>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <unistd.h>class ctcpserver {
private:int m_listenfd;        // 监听的socket,-1表示未初始化int m_clientfd;        // 客户端连上来的socket,-1表示客户端未连接std::string m_clientip;     // 客户端字符串格式的IPunsigned short m_port; // 服务端用于通讯的端口
public:ctcpserver();~ctcpserver();// 初始化服务端用于监听的socketbool initserver(const unsigned short in_port);// 受理客户端的连接bool accept();// 获取客户端的IP(字符串格式)const std::string & clientip() const;// 向对端发送报文bool send(const std::string &buffer);// 接收对端的报文bool recv(std::string &buffer, const size_t maxlen);// 关闭监听的socketbool closelisten();// 关闭客户端连上来的socketbool closeclient();
};#endif

2. ctcpserver.cpp 源文件

#include "ctcpserver.h"// 构造函数,初始化监听socket和客户端socket为未初始化状态
ctcpserver::ctcpserver() : m_listenfd(-1), m_clientfd(-1) {}// 析构函数,关闭监听socket和客户端socket
ctcpserver::~ctcpserver() {closelisten();closeclient();
}// 初始化服务端用于监听的socket
bool ctcpserver::initserver(const unsigned short in_port) {// 第1步:创建服务端的socket// AF_INET表示使用IPv4协议,SOCK_STREAM表示使用面向连接的TCP协议if ((m_listenfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) return false;m_port = in_port;// 第2步:把服务端用于通信的IP和端口绑定到socket上struct sockaddr_in servaddr;  // 用于存放协议、端口和IP地址的结构体memset(&servaddr, 0, sizeof(servaddr));servaddr.sin_family = AF_INET;  // 协议族,固定填AF_INETservaddr.sin_port = htons(m_port);  // 指定服务端的通信端口,htons用于将主机字节序转换为网络字节序servaddr.sin_addr.s_addr = htonl(INADDR_ANY);  // 如果操作系统有多个IP,全部的IP都可以用于通讯// 绑定服务端的IP和端口(为socket分配IP和端口)if (bind(m_listenfd, (struct sockaddr *)&servaddr, sizeof(servaddr)) == -1) {close(m_listenfd);m_listenfd = -1;return false;}// 第3步:把socket设置为可连接(监听)的状态// 5表示监听队列的最大长度if (listen(m_listenfd, 5) == -1) {close(m_listenfd);m_listenfd = -1;return false;}return true;
}// 受理客户端的连接(从已连接的客户端中取出一个客户端)
// 如果没有已连接的客户端,accept()函数将阻塞等待
bool ctcpserver::accept() {struct sockaddr_in caddr;  // 客户端的地址信息socklen_t addrlen = sizeof(caddr);  // struct sockaddr_in的大小// 从监听队列中取出一个客户端连接if ((m_clientfd = ::accept(m_listenfd, (struct sockaddr *)&caddr, &addrlen)) == -1) return false;m_clientip = inet_ntoa(caddr.sin_addr);  // 把客户端的地址从大端序转换成字符串return true;
}// 获取客户端的IP(字符串格式)
const std::string & ctcpserver::clientip() const {return m_clientip;
}// 向对端发送报文,成功返回true,失败返回false
bool ctcpserver::send(const std::string &buffer) {if (m_clientfd == -1) return false;// 发送报文if ((::send(m_clientfd, buffer.data(), buffer.size(), 0)) <= 0) return false;return true;
}// 接收对端的报文,成功返回true,失败返回false
// buffer - 存放接收到的报文的内容,maxlen - 本次接收报文的最大长度
bool ctcpserver::recv(std::string &buffer, const size_t maxlen) {buffer.clear();  // 清空容器buffer.resize(maxlen);  // 设置容器的大小为maxlen// 直接操作buffer的内存接收数据int readn = ::recv(m_clientfd, &buffer[0], buffer.size(), 0);if (readn <= 0) {buffer.clear();return false;}buffer.resize(readn);  // 重置buffer的实际大小return true;
}// 关闭监听的socket
bool ctcpserver::closelisten() {if (m_listenfd == -1) return false;::close(m_listenfd);m_listenfd = -1;return true;
}// 关闭客户端连上来的socket
bool ctcpserver::closeclient() {if (m_clientfd == -1) return false;::close(m_clientfd);m_clientfd = -1;return true;
}

3. multi_process_network_server.cpp 主源文件

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <unistd.h>
#include <netdb.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include "ctcpserver.h"ctcpserver tcpserver;// 父进程的信号处理函数
void FathEXIT(int sig);
// 子进程的信号处理函数
void ChldEXIT(int sig);int main(int argc, char *argv[]) {// 检查命令行参数if (argc != 2) {std::cout << "Using:./multi_process_network_server 通讯端口\nExample:./multi_process_network_server 5005\n\n";std::cout << "注意:运行服务端程序的Linux系统的防火墙必须要开通5005端口。\n";std::cout << "      如果是云服务器,还要开通云平台的访问策略。\n\n";return -1;}// 忽略全部的信号,不希望被打扰。顺便解决了僵尸进程的问题for (int ii = 1; ii <= 64; ii++) signal(ii, SIG_IGN);// 设置信号,在shell状态下可用 "kill 进程号" 或 "Ctrl+c" 正常终止些进程// 但请不要用 "kill -9 +进程号" 强行终止signal(SIGTERM, FathEXIT);signal(SIGINT, FathEXIT);  // SIGTERM 15 SIGINT 2// 初始化服务端用于监听的socketif (tcpserver.initserver(atoi(argv[1])) == false) {perror("initserver()");return -1;}while (true) {// 受理客户端的连接(从已连接的客户端中取出一个客户端)// 如果没有已连接的客户端,accept()函数将阻塞等待if (tcpserver.accept() == false) {perror("accept()");return -1;}// 创建子进程处理客户端连接int pid = fork();if (pid == -1) {perror("fork()");return -1;}  // 系统资源不足if (pid > 0) {// 父进程tcpserver.closeclient();  // 父进程关闭客户端连接的socketcontinue;  // 父进程返回到循环开始的位置,继续受理客户端的连接}// 子进程tcpserver.closelisten();  // 子进程关闭监听的socket// 子进程需要重新设置信号signal(SIGTERM, ChldEXIT);  // 子进程的退出函数与父进程不一样signal(SIGINT, SIG_IGN);  // 子进程不需要捕获SIGINT信号// 子进程负责与客户端进行通讯std::cout << "客户端已连接(" << tcpserver.clientip() << ")。\n";std::string buffer;while (true) {// 接收对端的报文,如果对端没有发送报文,recv()函数将阻塞等待if (tcpserver.recv(buffer, 1024) == false) {perror("recv()");break;}std::cout << "接收:" << buffer << std::endl;buffer = "ok";if (tcpserver.send(buffer) == false) {  // 向对端发送报文perror("send");break;}std::cout << "发送:" << buffer << std::endl;}return 0;  // 子进程一定要退出,否则又会回到accept()函数的位置}
}// 父进程的信号处理函数
void FathEXIT(int sig) {// 以下代码是为了防止信号处理函数在执行的过程中再次被信号中断signal(SIGINT, SIG_IGN);signal(SIGTERM, SIG_IGN);std::cout << "父进程退出,sig=" << sig << std::endl;kill(0, SIGTERM);  // 向全部的子进程发送15的信号,通知它们退出// 在这里增加释放资源的代码(全局的资源)tcpserver.closelisten();  // 父进程关闭监听的socketexit(0);
}// 子进程的信号处理函数
void ChldEXIT(int sig) {// 以下代码是为了防止信号处理函数在执行的过程中再次被信号中断signal(SIGINT, SIG_IGN);signal(SIGTERM, SIG_IGN);std::cout << "子进程" << getpid() << "退出,sig=" << sig << std::endl;// 在这里增加释放资源的代码(只释放子进程的资源)tcpserver.closeclient();  // 子进程关闭客户端连上来的socketexit(0);
}

代码说明

  • ctcpserver.h:定义了 ctcpserver 类的接口,包括类的成员变量和成员函数的声明。使用了预处理器指令 #ifndef#define#endif 来防止头文件被重复包含。
  • ctcpserver.cpp:实现了 ctcpserver 类的成员函数,包括构造函数、析构函数以及各种操作函数。
  • multi_process_network_server.cpp:主源文件,包含了 main 函数和信号处理函数,使用 ctcpserver 类来实现多进程的网络服务端。

编译和运行

将上述三个文件放在同一目录下,使用以下命令进行编译:

g++ -o multi_process_network_server ctcpserver.cpp multi_process_network_server.cpp

编译成功后,使用以下命令运行服务端程序:

./multi_process_network_server 5005

其中 5005 是服务端监听的端口号,你可以根据需要修改。

http://www.dtcms.com/wzjs/31640.html

相关文章:

  • 做可视化图表的网站google下载安卓版下载
  • 做网站不实名认证可以吗百度统计流量研究院
  • 男人与女人做视频网站关键词优化排名费用
  • 网站运营数据周报表怎么做友情链接模板
  • 做游戏网站要通过什么审核宁波seo公司
  • 最适合穷人开的店成都sem优化
  • 家在深圳龙岗百度seo详解
  • 用java做中小企业网站多策划公司排行榜
  • 注册资金500万的公司需要多少钱深圳网站搜索优化
  • 苏州调查公司有哪些上海抖音seo公司
  • 房产中介网站建设微信平台推广方法
  • 重庆市建设工程信息网官网查询入口上海seo怎么优化
  • 做平面设计的网站重庆百度竞价推广
  • 青岛市有什么网络科技公司英文seo兼职
  • 金坛网站建设公司cnn头条新闻
  • 电商思维做招聘网站什么是推广
  • wild合成版是哪个网站做的seo薪酬
  • 网站框架怎么做自动搜索关键词软件
  • 网站编辑容易做吗免费单页网站在线制作
  • 自适应网站做多大尺寸的好的推广平台
  • 上海知名网站设计保定网站建设方案优化
  • 合肥市建设委员会网站优化seo教程技术
  • 临沂高端网站建设色盲测试图免费测试
  • app网站建设销售石家庄seo关键词
  • 网站导航页设计营销软件app
  • 专业的网站建设服务怎么建个网站
  • 国外平台卖货达州seo
  • 山东网站建设设计百度导航官网
  • 网站上点击图片局部放大如何做优化软件seo排名
  • 网站代码怎么查看武汉网络推广外包公司