多线程|多进程|高并发网络编程

在这里插入图片描述

一.多进程并发服务器

多进程并发服务器是一种经典的服务器架构,它通过创建多个子进程来处理客户端连接,从而实现并发处理多个客户端请求的能力。

概念:

  1. 服务器启动时,创建主进程,并绑定监听端口。
  2. 当有客户端连接请求时,主进程接受连接,并创建一个子进程来处理该客户端连接。
  3. 子进程与客户端进行通信,处理请求和发送响应。
  4. 主进程继续监听新的连接请求。
  5. 子进程完成任务后,可以选择终止或继续处理其他连接,根据需求选择是否重复循环。

优点:

  1. 高并发处理能力:每个子进程都可以独立地处理一个客户端连接,利用多核处理器的优势,实现高并发处理能力,提高服务器的吞吐量。
  2. 稳定性:每个子进程都是独立的,一个进程出现问题不会影响其他进程,提高了服务器的稳定性和容错能力。
  3. 简单直观:采用多进程模型实现并发服务器相对简单,代码可读性高,易于理解和维护。
  4. 跨平台:多进程并发服务器概念适用于各种操作系统,不仅限于Linux平台。

缺点:

  1. 高资源消耗:每个子进程都需要独立的资源,包括内存、文件描述符等,当并发连接数较高时,会消耗大量的系统资源。
  2. 进程间通信:各个子进程之间的通信需要额外的机制,例如管道、共享内存等,增加了复杂性。
  3. 上下文切换开销:进程间切换的开销相对较大,会影响性能。
  4. 调试困难:由于每个子进程独立执行,调试和定位问题可能会变得复杂。

综上所述,多进程并发服务器能够满足高并发处理需求,并具有稳定性和简单性等优点。然而,它也存在资源消耗较高和调试困难等缺点,根据实际需求和应用场景选择合适的服务器架构是很重要的。

案例

利用多进程,在TCP通信的基础上,实现服务器可以同时连接多个客户端。实现大小写转换。

service.c

#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <arpa/inet.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <sys/wait.h>void handler(int sig)
{if (sig == SIGCHLD){while(waitpid(0,NULL,WNOHANG)>0);}
}
int main(int argc, char const *argv[])
{//1.建立socket套接字int socked = socket(AF_INET, SOCK_STREAM, 0);if (socked < 0){perror("socket is err");return -1;}//2.bind绑定服务器ip和端口号struct sockaddr_in saddr, caddr;saddr.sin_family = AF_INET;saddr.sin_port = htons(atoi(argv[1]));saddr.sin_addr.s_addr = inet_addr("0.0.0.0");int len = sizeof(caddr);int rev = bind(socked, (struct sockaddr *)(&saddr), sizeof(saddr));if (rev < 0){perror("bind is err");return 0;}//3.listen设置最大同时链接数量rev = listen(socked, 32);if (rev < 0){perror("rev is err");return 0;}//4.建立子进程负责服务器给客户端发送消息,并且主进程不结束,此进程不结束char buf[1024] = {0};int size=0;while (1){int acceptfd = accept(socked, (struct sockaddr *)(&caddr), &len);if (acceptfd < 0){perror("accept is err");return 0;}pid_t pid = fork();if (pid < 0){perror("pid is err");return 0;}else if (pid == 0){//子进程,每个子进程维护一个客户端//不许要监听,直接关掉close(socked);while (1){int flage = recv(acceptfd, buf, sizeof(buf), 0);if (flage < 0){perror("recv is err");}else if (flage == 0){printf("ip:%s is close\n", inet_ntoa(caddr.sin_addr));close(acceptfd);break;}else{size = strlen(buf);for (int i = 0; i < size; ++i){if (buf[i] >= 'a' && buf[i] <= 'z')buf[i] = buf[i] + ('A' - 'a');elsebuf[i] = buf[i] + ('a' - 'A');}printf("%d %s\n",getpid(),buf);send(acceptfd, buf, sizeof(buf), 0);}}}else{//主进程回收子线程资源close(acceptfd);//异步节约资源signal(SIGCHLD, handler);}}return 0;
}

client.c

#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <arpa/inet.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>int main(int argc, char const *argv[])
{//1.socket建立文件描述符int fd = socket(AF_INET, SOCK_STREAM, 0);if (fd < 0){perror("socket is err");}//2.connect连接服务器struct sockaddr_in saddr;saddr.sin_family = AF_INET;saddr.sin_port = htons(atoi(argv[2]));saddr.sin_addr.s_addr = inet_addr(argv[1]);int flage = connect(fd, (struct sockaddr *)(&saddr), sizeof(saddr));if (flage < 0){perror("connect is err");}//3.服务器端不断发送数据,接受服务器转化后的数据char buf[1024] = {0};while (1){//memset(buf,0,sizeof(buf));fgets(buf, sizeof(buf), stdin);if (strncmp(buf,"quit#",5)==0){break;}if (buf[strlen(buf) - 1] == '\n')buf[strlen(buf) - 1] = '\0';send(fd, buf, sizeof(buf), 0);flage = recv(fd, buf, sizeof(buf), 0);if (flage < 0){perror("recv is err");}else{fprintf(stdout, "%s\n", buf);}}close(fd);return 0;
}

二.多线程并发服务器

多线程并发服务器是一种服务器架构,通过创建多个线程来处理客户端连接,实现并发处理多个客户端请求的能力。下面是多线程并发服务器的概念和一些优点:

概念:

  1. 服务器启动时,创建主线程,并绑定监听端口。
  2. 当有客户端连接请求时,主线程接受连接,并创建一个或多个线程来处理该客户端连接。
  3. 线程与客户端进行通信,处理请求和发送响应。
  4. 主线程继续监听新的连接请求。
  5. 线程完成任务后,选择终止或继续处理其他连接,根据需求选择是否重复循环。

优点:

  1. 资源效率:线程相比进程,创建和销毁的开销较小,占用的资源较少,特别是共享的资源,如文件描述符,可以在多个连接之间共享,提高了资源的利用效率。
  2. 响应速度:线程之间的切换开销较小,内存空间共享,可以快速响应客户端请求,减少了连接等待时间。
  3. 简单直观:与多进程相比,多线程实现并发服务器更简单直观,代码可读性高,易于理解和维护。
  4. 可扩展性:线程可轻松地添加和删除,适应不断变化的连接数需求,提供更好的可扩展性。
  5. 共享数据简便:线程之间共享的数据结构可以直接访问,不需要像进程间通信一样使用额外的机制。

缺点:

  1. 数据同步问题:多线程共享数据可能导致竞态条件和数据一致性问题,需要使用锁或其他同步机制来保证线程安全。
  2. 调试困难:由于线程之间共享同一进程的内存空间,调试和定位问题可能会变得复杂。
  3. 并行性限制:在某些情况下,多线程服务器的并行性可能受限于系统中可用的CPU核心数量。
  4. 需要考虑线程安全:编写线程安全的代码可能需要更多的开发工作和考虑,避免数据竞争和死锁等问题。

综上所述,多线程并发服务器能够满足高并发处理需求,并具有资源效率、响应速度、简单性和可扩展性等优点。然而,它也存在数据同步问题和调试困难等缺点,根据实际需求和应用场景选择合适的服务器架构是很重要的。

案例

利用多线程,在TCP通信的基础上,实现服务器可以同时连接多个客户端。实现大小写转换。

service.c

#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <arpa/inet.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <sys/wait.h>
#include <pthread.h>struct client
{int acceptfd;struct sockaddr_in caddr;
};void *my_pthread(void *p)
{char buf[1024] = {0};int size = 0;struct client *cl = (struct client *)p;int acceptfd = cl->acceptfd;struct sockaddr_in caddr = cl->caddr;while (1){int flage = recv(acceptfd, buf, sizeof(buf), 0);if (flage < 0){perror("recv is err");}else if (flage == 0){printf("ip:%s is close\n", inet_ntoa(caddr.sin_addr));close(acceptfd);break;}else{size = strlen(buf);for (int i = 0; i < size; ++i){if (buf[i] >= 'a' && buf[i] <= 'z')buf[i] = buf[i] + ('A' - 'a');elsebuf[i] = buf[i] + ('a' - 'A');}send(acceptfd, buf, sizeof(buf), 0);}}close(acceptfd);return 0;
}int main(int argc, char const *argv[])
{//1.建立socket套接字int socked = socket(AF_INET, SOCK_STREAM, 0);if (socked < 0){perror("socket is err");return -1;}//2.bind绑定服务器ip和端口号struct sockaddr_in saddr, caddr;saddr.sin_family = AF_INET;saddr.sin_port = htons(atoi(argv[1]));saddr.sin_addr.s_addr = inet_addr("0.0.0.0");int len = sizeof(caddr);int rev = bind(socked, (struct sockaddr *)(&saddr), sizeof(saddr));if (rev < 0){perror("bind is err");return 0;}//3.listen设置最大同时链接数量rev = listen(socked, 32);if (rev < 0){perror("rev is err");return 0;}//4.建立子进程负责服务器给客户端发送消息,并且主进程不结束,此进程不结束int i = 0;pthread_t tid;struct client ti[1024] = {0};while (1){int acceptfd = accept(socked, (struct sockaddr *)(&caddr), &len);if (acceptfd < 0){perror("accept is err");return 0;}ti[i].acceptfd = acceptfd;ti[i].caddr = caddr;pthread_create(&tid, NULL, my_pthread, (void *)&ti[i]);pthread_detach(tid);++i;}return 0;
}

client.c

#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <arpa/inet.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>int main(int argc, char const *argv[])
{//1.socket建立文件描述符int fd = socket(AF_INET, SOCK_STREAM, 0);if (fd < 0){perror("socket is err");}//2.connect连接服务器struct sockaddr_in saddr;saddr.sin_family = AF_INET;saddr.sin_port = htons(atoi(argv[2]));saddr.sin_addr.s_addr = inet_addr(argv[1]);int flage = connect(fd, (struct sockaddr *)(&saddr), sizeof(saddr));if (flage < 0){perror("connect is err");}//3.服务器端不断发送数据,接受服务器转化后的数据char buf[1024] = {0};while (1){//memset(buf,0,sizeof(buf));fgets(buf, sizeof(buf), stdin);if (strncmp(buf,"quit#",5)==0){break;}if (buf[strlen(buf) - 1] == '\n')buf[strlen(buf) - 1] = '\0';send(fd, buf, sizeof(buf), 0);flage = recv(fd, buf, sizeof(buf), 0);if (flage < 0){perror("recv is err");}else{fprintf(stdout, "%s\n", buf);}}close(fd);return 0;
}

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

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

相关文章

国家网络安全周2023时间是什么时候?有什么特点?谁举办的?

国家网络安全周2023时间是什么时候&#xff1f; 2023年国家网络安全宣传周将于9月11日至17日在全国范围内统一开展。其中开幕式等重要活动将在福建省福州市举行。今年网安周期间&#xff0c;除开幕式外&#xff0c;还将举行网络安全博览会、网络安全技术高峰论坛、网络安全微视…

JavaEE初阶(5)多线程案例(定时器、标准库中的定时器、实现定时器、线程池、标准库中的线程池、实现线程池)

接上次博客&#xff1a;JavaEE初阶&#xff08;4&#xff09;&#xff08;线程的状态、线程安全、synchronized、volatile、wait 和 notify、多线程的代码案例&#xff1a;单例模式——饿汉懒汉、阻塞队列&#xff09;_di-Dora的博客-CSDN博客 目录 多线程案例 定时器 标准…

后端/DFT/ATPG/PCB/SignOff设计常用工具/操作/流程及一些文件类型

目录 1.PD/DFT常用工具及流程 1.1 FC和ICC2 1.2 LC (Library compiler) 1.3 PrimeTime 1.4 Redhawk与PA 1.5 Calibre和物理验证PV 1.6 芯片设计流程 2.后端、DFT、ATPG的一些常见文件 2.1 LEF和DEF 2.2 ATPG的CTL和STIL 2.3 BSDL 2.4 IPXACT 2.5 CDL netlist 3.…

【去除若依首页】有些小项目不需要首页,去除方法

第一步 // // // // // // // // // // // // // // // // // // 修改登录页 Login.vue 中 大概144行 &#xff0c;注释掉原有跳转。替换为自己的跳转路径 // // // // // // // // // // // // // this.$router.push({ path: this.redirect || …

C语言--字符串旋转笔试题

C语言–字符串旋转笔试题 文章目录 C语言--字符串旋转笔试题一、字符串左旋1.1 思路11.2 思路1代码1.3 思路21.4 思路2代码 二、字符串旋转结果判断2.1 思路12.2 思路2 一、字符串左旋 实现一个函数&#xff0c;可以左旋字符串中的k个字符。 例如&#xff1a; ABCD左旋一个字…

SpringBoot+@EnableScheduling使用定时器的常见案例

记录一下SpringBootEnableScheduling使用定时器的常见案例 我的SpringBoot版本 <parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.0.5.RELEASE</version><…

前端设计模式基础笔记

前端设计模式是指在前端开发中经常使用的一些解决问题的模式或思想。它们是经过实践证明的最佳实践&#xff0c;可以帮助我们更好地组织和管理我们的代码。 一、单例模式&#xff08;Singleton Pattern&#xff09; 单例模式是一种创建型模式&#xff0c;它保证一个类只有一个…

脚本:python绘制七夕爱心

文章目录 效果脚本Reference 效果 脚本 import random from math import sin, cos, pi, log from tkinter import *CANVAS_WIDTH 640 # 画布的宽 CANVAS_HEIGHT 640 # 画布的高 CANVAS_CENTER_X CANVAS_WIDTH / 2 # 画布中心的X轴坐标 CANVAS_CENTER_Y CANVAS_HEIGHT /…

照片批量处理 7000张

需求&#xff1a; 有6700照片导入系统&#xff1b; 系统只支持500张/每次&#xff1b; 6700 按机构分类复制提取出来&#xff1b; 分批次导入&#xff1b; 6700 分17份复制到对应文件夹中&#xff1b; 照片按照学号命名的&#xff1b; 20231715401.jpg 开始用bat脚本…

Sui Move智能合约提供更智能和简单的编程

编写区块链和其他计算环境的代码有很多相似之处&#xff0c;但区块链的重点大部分都集中在构建智能合约上。智能合约部署编译后的代码&#xff0c;本质上是在区块链上自动执行交易的apps。Sui网络本地的Sui虚拟机使用Sui Move编程语言编写智能合约。 术语“智能合约”意味着区…

3D数字孪生:从3D数据采集到3D内容分析

数字孪生&#xff08;Digital Twin&#xff09;是物理对象、流程或系统的虚拟复制品&#xff0c;用于监控、分析和优化现实世界的对应物。 这些数字孪生在制造、工程和城市规划等领域变得越来越重要&#xff0c;因为它们使我们能够在现实世界中实施改变之前模拟和测试不同的场景…

【电子元件】常用电子元器件的识别之霍尔元件

目录 1. 霍尔元件的结构与特点1.1 霍尔元件的组成结构1.2 霍尔元件的霍尔效应 2. 霍尔元件的图形符号与型号2.1 1.图形符号2.2 2.型号说明 3. 半导体霍尔效应的原理3.1 半导体中的左手定则3.2 P型半导体霍尔效应的原理3.3 N型半导体霍尔效应的原理 4. 霍尔元件的电势计算与工作…