【高性能服务器】多线程并发模型

🔥博客主页: 我要成为C++领域大神
🎥系列专栏:【C++核心编程】 【计算机网络】 【Linux编程】 【操作系统】
❤️感谢大家点赞👍收藏⭐评论✍️

本博客致力于知识分享,与更多的人进行学习交流

​​

对于常见的C/S模型,一个服务端通常需要服务多个客户端。如果使用单行的处理模型,当新的客户端请求服务端的服务时,就必须等待比它先到的客户端的请求全部完成。

因此引入多进程并发服务器模型。多进程并发服务器模型的简单流程图如下所示。父进程创建一个套接字,然后与自己的IP地址、端口号进行绑定。之后调用开始监听来自客户端的敲门,当有客户端来敲门时,accept()接收客户端的连接并创建一个新套接字用于与客户端通信。接下来调用fork()函数,当调用fork()函数时,操作系统会复制当前进程的一个副本,包括进程的代码、数据和状态等信息。如果其返回值为负数,表示创建子进程失败。否则他在父子进程中有不同的返回值:如果返回值为0,表示当前代码正在子进程中执行。如果返回值大于0,表示当前代码正在父进程中执行,返回的值是子进程的进程ID。因此可以使用if-else语句来编写子进程的处理代码。

在子进程中,先关闭从父进程中复制下来监听套接字,这个套接字在子进程中没有用了,纯属浪费资源,之后再进行与客户端的通信。而在父进程中,同理关闭accept()创建的新套接字,然后继续监听客户端的连接请求。

而同一进程的所有线程共享相同的内存空间,线程数据共享和通信更加方便,创建和管理线程的资源消耗较少,尤其是内存开销较小。由于线程间通信和进程间通信,多线程模型在处理大量任务时响应速度较快。

在多进程+多线程代码的基础上,将进行accept的进程修改为创建的线程工作,socket通信的功能放在线程工作函数内。

使用服务器测试业务:

客户端向标准输入发送小写字符串,服务端响应回复对应大写字符,"abcAS"->"ABCAS"

客户端向服务端发送关键字localtime,服务端响应回复系统时间、

服务端: 

#include <stdio.h>
#include <stdlib.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <string.h>
#include <time.h>
#include <pthread.h>
#include <signal.h>
#include <errno.h>
#include <sys/wait.h>
#include <ctype.h>
#define _SERVER_IP "xxx.xxx.xxx.xxx"
#define _PORT 8080
#define _BACKLOG 128
#define _SHUTDOWN 1
#define _TRUE 1
#define _FALSE 0
#define _IPSIZE 16
#define _RECVLEN 1500struct client_info
{int client_fd;struct sockaddr_in clientAddr;
};void sig_wait(int n)
{pid_t zpid;while ((zpid = waitpid(-1, NULL, WNOHANG)) > 0){printf("wait Thread Tid [0x%x] Wait Successfully,Zombie %d\n", (unsigned int)pthread_self(), zpid);}
}void *thread_wait(void *arg)
{// 设定信号捕捉pthread_detach(pthread_self());struct sigaction act, oact;act.sa_handler = sig_wait;act.sa_flags = 0;sigemptyset(&act.sa_mask);sigaction(SIGCHLD, &act, &oact);// 解除屏蔽sigprocmask(SIG_SETMASK, &act.sa_mask, NULL);printf("wait Thread [0x%x] is Waiting...\n", (unsigned int)pthread_self());while (1)sleep(1);pthread_exit(NULL);
}
void *thread_recv(void *arg)
{int recvlen;char Result[_RECVLEN];char client_ip[_IPSIZE];time_t tp;char time_buf[100]; // 存放当前系统时间int toupper_flag;struct client_info cinfo = *((struct client_info *)arg);// Socket通信bzero(Result, sizeof(Result));bzero(client_ip, sizeof(client_ip));inet_ntop(AF_INET, &cinfo.clientAddr.sin_addr.s_addr, client_ip, _IPSIZE);printf("Connection From :IP[%s],PORT[%d]\n", client_ip, ntohs(cinfo.clientAddr.sin_port));sprintf(Result, "Hi [%s] Welcome to my TCP test server!service version 1.1.0...", client_ip);send(cinfo.client_fd, Result, strlen(Result), 0);bzero(Result, sizeof(Result));// 读取用户数据,如果用户发的是普通小写字符字符串,转换为大写,如果发送的是local关键字,响应时间// 持续响应,循环读写while ((recvlen = recv(cinfo.client_fd, Result, sizeof(Result), 0)) > 0){ // 处理客户端业务printf("Client Say:%s\n", Result);if (strcmp(Result, "localtime") == 0){tp = time(NULL); // 获取时间种子ctime_r(&tp, time_buf);time_buf[strcspn(time_buf, "\n")] = '\0';printf("[%s]Response SysTime Successfully!\n", client_ip);send(cinfo.client_fd, time_buf, strlen(time_buf) + 1, 0);}else{toupper_flag = 0;while (recvlen > toupper_flag){Result[toupper_flag] = toupper(Result[toupper_flag]);++toupper_flag;}printf("[%s]Response Toupper Successfully!\n", client_ip);send(cinfo.client_fd, Result, recvlen, 0);}}if (recvlen == 0) // 客户端退出{close(cinfo.client_fd);printf("[%s] is Exiting,Kill Child\n", client_ip);exit(0);}close(cinfo.client_fd);
}int main()
{struct sockaddr_in serverAddr, clientAddr;int server_fd;int client_fd;// 主线程设置屏蔽sigset_t set, oldset;sigemptyset(&set);sigaddset(&set, SIGCHLD);sigprocmask(SIG_SETMASK, &set, &oldset);pthread_t tid;pthread_create(&tid, NULL, thread_wait, NULL); // 创建回收线程socklen_t Addrlen;serverAddr.sin_family = AF_INET;serverAddr.sin_port = htons(_PORT);serverAddr.sin_addr.s_addr = htonl(INADDR_ANY);server_fd = socket(AF_INET, SOCK_STREAM, 0);bind(server_fd, (struct sockaddr *)&serverAddr, sizeof(serverAddr));listen(server_fd, _BACKLOG);printf("Test TCP Server Version 1.1.0 is Running...\n");while (_SHUTDOWN){Addrlen = sizeof(clientAddr);if ((client_fd = accept(server_fd, (struct sockaddr *)&clientAddr, &Addrlen)) > 0){struct client_info cinfo;cinfo.client_fd = client_fd;cinfo.clientAddr = clientAddr;pthread_create(&tid, NULL, thread_recv, &cinfo); // 创建工作线程}else{// accept失败,测试中断close(server_fd);if (errno == EINTR){printf("Accept ERROR Eintr...\n");exit(0);}}}close(server_fd);return 0;
}

客户端:

#ifndef _MYSOCK_H_
#define _MYSOCK_H_#include <arpa/inet.h>
#include <ctype.h>
#include <errno.h>
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/select.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <time.h>
#include <unistd.h>int SOCKET(int domain, int type, int protocol);
int BIND(int sockfd, struct sockaddr* addr, socklen_t addrlen);
ssize_t RECV(int sockfd, void* buf, size_t len, int flags);
ssize_t SEND(int sockfd, void* buf, size_t len, int flags);
int CONNECT(int sockfd, struct sockaddr* addr, socklen_t addrlen);
int ACCEPT(int sockfd, struct sockaddr* addr, socklen_t* addrlen);
int LISTEN(int sockfd, int backlog);
char* FGETS(char* s, int size, FILE* stream);
int SELECT(int nfds, fd_set* readfds, fd_set* writefds, fd_set* exceptfds,struct timeval* timeout);
int socket_init();
int return_response(int clientfd, const char* clientip);
//void strDeal(int *client_fd);// 全局变量声明
char recv_buf[1024];
char time_buf[64];
int serverFd, clientFd;
struct sockaddr_in clientAddr;
fd_set set, oset;
int client_array[1020];
int maxfd, ready;
socklen_t addrlen;
char clientip[16];
time_t tp;
ssize_t recvlen;
int toupper_flag;
#define SHUTDOWN 1
#endif
#include "MySock.h"//客户端源码编写,连接服务器成功,服务器反馈信息#define _IP "xxx.xxx.xxx.xxx"
#define _PORT 8080
int main()
{struct sockaddr_in ServerAddr;bzero(&ServerAddr,sizeof(ServerAddr));ServerAddr.sin_family=AF_INET;ServerAddr.sin_port=htons(_PORT);inet_pton(AF_INET,_IP,&ServerAddr.sin_addr.s_addr);int Myfd=SOCKET(AF_INET,SOCK_STREAM,0);//看需求决定是否要绑定char Response[1024];//存放服务端反馈信息ssize_t recvlen;bzero(Response,sizeof(Response));char sendbuf[1024];if((CONNECT(Myfd,(struct sockaddr *)&ServerAddr,sizeof(ServerAddr)))==0){while(1){    if((recvlen=RECV(Myfd,Response,sizeof(Response),0))>0){printf("%s\n",Response);}printf("Please Type Some text:");//读取标准输入发送给服务端FGETS(sendbuf,sizeof(sendbuf),stdin);    sendbuf[strcspn(sendbuf,"\n")]='\0';SEND(Myfd,sendbuf,sizeof(sendbuf),0);}}close(Myfd);printf("Client is Over\n");return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/864578.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

ROS2使用Python开发动作通信

1.创建接口节点 cd chapt4_ws/ ros2 pkg create robot_control_interfaces --build-type ament_cmake --destination-directory src --maintainer-name "joe" --maintainer-email "1027038527qq.com" mkdir -p src/robot_control_interfaces/action touch…

跨模型知识融合:大模型的知识融合

大模型&#xff08;LLMs&#xff09;在多个领域的应用日益广泛&#xff0c;但确保它们的行为与人类价值观和意图一致却充满挑战。传统对齐方法&#xff0c;例如基于人类反馈的强化学习&#xff08;RLHF&#xff09;&#xff0c;虽取得一定进展&#xff0c;仍面临诸多难题&#…

LeetCode Top 100 题目概览及部分题目解答【两数之和,接雨水,最长回文子串,三数之和】

本人详解 作者:王文峰,参加过 CSDN 2020年度博客之星,《Java王大师王天师》 公众号:JAVA开发王大师,专注于天道酬勤的 Java 开发问题中国国学、传统文化和代码爱好者的程序人生,期待你的关注和支持!本人外号:神秘小峯 山峯 转载说明:务必注明来源(注明:作者:王文峰…

django开源电子文档管理系统_Django简介、ORM、核心模块

Django简介 Django是一种开源的大而且全的Web应用框架&#xff0c;是由python语言来编写的。他采用了MVC模式&#xff0c;Django最初是被开发来用于管理劳伦斯出版集团下的一些以新闻为主内容的网站。一款CMS(内容管理系统)软件。并于 2005 年 7 月在 BSD 许可证下发布。这套框…

Pytest+Yaml+Request+Allure+PyMsql+Jenkins+GitLab框架源代码之(二)config配置

config公共配置包 config.yml 公共配置文件&#xff0c;主要配置路径及日志 base:base_info_url: https://XXXX.combase_php_url: http://XXXX.combase_weixin_url: https://XXXX.qq.combase_fenmi_url: http://XXXXX.com # base_czt_url: http://XXXXXbase_czt_url: hhttps:…

自然语言处理:第四十章 如何与大模型交流-Prompt工程

文章链接:Principled Instructions Are All You Need for Questioning LLaMA-1/2, GPT-3.5/4 主页: VILA-Lab/ATLAS: A principled instruction benchmark on formulating effective queries and prompts for large language models (LLMs). Our paper: https://arxiv.org/abs…

Redis 7.x 系列【13】数据类型之地理位置(Geospatial)

有道无术&#xff0c;术尚可求&#xff0c;有术无道&#xff0c;止于术。 本系列Redis 版本 7.2.5 源码地址&#xff1a;https://gitee.com/pearl-organization/study-redis-demo 文章目录 1. 概述2. 常用命令2.1 GEOADD2.2 GEODIST2.3 GEORADIUS2.4 GEOPOS2.5 GEORADIUSBYMEM…

半导体工艺的完美搭档 —— PEEK晶片夹

PEEK&#xff08;聚醚醚酮 Polyetheretherketone&#xff09;是一种高性能的工程塑料&#xff0c;以其耐高温、耐磨性、尺寸稳定性、低释气性和低吸湿性等特性&#xff0c;在电子半导体、光伏及液晶光电工业中得到广泛应用。 PEEK晶片夹作为其中的一种应用&#xff0c;具有以下…

液压件工厂的MES解决方案:智能生产,高效未来

一、引言 虽然我国液压件行业发展迅速&#xff0c;但是大多数液压件生产企业规模小、自主创新能力不足&#xff0c;大部分液压产品处于价值链中低端。且由于技术、工艺、设备及管理等多方面的限制&#xff0c;高端液压件产品研发生产水平不足&#xff0c;无法形成有效的供给&a…

如何在工作中应用六西格玛绿带培训所学的知识和技能?

近年来&#xff0c;六西格玛作为一种被广泛认可的质量管理工具&#xff0c;为企业提供了一种系统的、数据驱动的方法来优化流程、提高产品质量并减少成本。然而&#xff0c;仅仅接受培训是不够的&#xff0c;如何在工作中有效应用六西格玛绿带培训所学的知识和技能&#xff0c;…

录屏软件哪个好用?分享5款(2024最新)

随着网络时代的发展&#xff0c;电脑的使用频率也越来越高&#xff0c;还有近些年出现的网课、直播等&#xff0c;这让电脑的录屏功能显得更重要。随之而来的录屏软件也越来越多样化&#xff0c;选择一款好的软件是录屏至关重要的环节。 在数字浪潮汹涌的时代&#xff0c;录屏…

前端利用vue如何实现导入和导出功能.md

1. 前端利用vue如何实现导入和到处功能 1.1. 导入功能&#xff08;以导入Excel文件为例&#xff09; 1.1.1. 实现步骤: 1.1.1.1. 安装依赖: 首先&#xff0c;你需要安装处理Excel文件的库&#xff0c;如xlsx。1.1.1.2. 创建上传组件: 使用Element UI的<el-upload>组件或其…

绘唐3一键追爆款文刻创作聚星文社

聚星文社是一个中国的文学社交平台&#xff0c;提供了一个让作家和读者相互交流和分享作品的平台。 在聚星文社&#xff0c;作家可以在平台上发布自己的作品&#xff0c;获得读者的阅读和评论&#xff0c;同时也可以与其他作家进行交流与学习。 点击下载即可 读者可以在平台上…

一、安全完善度等级SIL(Safety Integrity Level)介绍

目录 一、背景 二、定义 2.1 相关概念介绍如下&#xff1a; 2.2 扩展 2.3 注意事项 一、背景 在轨道交通行业中&#xff0c;安全完善度等级&#xff08;SIL&#xff0c;Safety Integrity Level&#xff09;是一个至关重要的概念&#xff0c;它用于评估安全相关系统&#x…

Linux基础IO操作详解

C文件IO相关接口 fopen函数 pathname: 要打开的文件名字符串mode: 访问文件的模式 模式描述含义“r”读文件不存在失败返回null“r”读写文件不存在打开失败返回null&#xff0c;文件存在则从头开始覆盖现有的数据&#xff08;不会清空数据&#xff09;“w”写文件不存在创建…

马斯克公布xAI Grok-2大语言模型将于8月推出;GPT-5仍需时日

&#x1f989; AI新闻 &#x1f680; 马斯克公布xAI Grok-2大语言模型将于8月推出 摘要&#xff1a;7月1日&#xff0c;马斯克在X平台宣布&#xff0c;其人工智能初创公司xAI的新大语言模型Grok-2将于8月推出。此前&#xff0c;xAI已发布了Grok-1.5和Grok-1.5 Vision模型。马…

运营商如何通过PCDN技术提高用户服务?

着互联网的快速发展&#xff0c;用户对网络速度和质量的要求越来越高。为了满足这些需求&#xff0c;内容分发网络(CDN)成为了关键的基础设施。而在CDN技术中&#xff0c;PCDN(PersonalCDN)作为一种新兴的技术&#xff0c;为运营商和用户提供了新的解决方案。本文将重点介绍PCD…

Drools开源业务规则引擎(一)- 安装与介绍

文章目录 [toc] Drools开源业务规则引擎&#xff08;一&#xff09;- 安装与介绍0.何为规则引擎1.Drools介绍1.1.依赖模块1.2.规则引擎 2.Drools安装2.1.依赖导入2.2.规则的输入和输出类型输入类型输出类型 2.3.创建规则文件2.4.构建可执行规则库2.5.执行结果&#xff1a; 3.Dr…

自动驾驶---Motion Planning之多段五次多项式

1 前言 在之前的博客系列文章中和读者朋友们聊过Apollo的 Motion Planning方案: 《自动驾驶---Motion Planning之LaneChange》 《自动驾驶---Motion Planning之Path Boundary》 《自动驾驶---Motion Planning之Speed Boundary》 《自动驾驶---Motion Planning之轨迹Path优化》…