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

在这里插入图片描述

一.多进程并发服务器

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

概念:

  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.mzph.cn/news/79945.shtml

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

相关文章

GitLab使用的最简便方式

GitLab介绍 GitLab是一个基于Git版本控制系统的开源平台&#xff0c;用于代码托管&#xff0c;持续集成&#xff0c;以及协作开发。它提供了一套完整的工具&#xff0c;以帮助开发团队协同工作、管理和部署代码。 往往在企业内部使用gitlab管理代码&#xff0c;记录一下将本地代…

VR航天航空巡展VR科技馆航天主题科普设备沉浸遨游太空

每当飞机飞过头顶&#xff0c;我们总是忍不住抬头去仰望。从嫦娥奔月的神话传说&#xff0c;到莱特兄弟实现了上天翱翔的梦想&#xff0c;人类一直在不断探索更辽阔的天空和浩瀚的宇宙。 航空科普 寻梦而行 普乐蛙VR航天航空巡展&#xff0c;正在湖南郴州如火如荼的进行中&…

arm day2(9.15)数据操作指令,跳转指令,特殊功能寄存器指令,

作业 1.求最大公约数&#xff1a; .text .global _start _start:mov r0,#0x9mov r1,#0x15bl Loop Loop:cmp r0,r1 比较r0寄存器和r1寄存器的中的值beq stop 当两数相同时,退出程序subhi r0,r0,r1 r0>r1 r0 r0 - r1subcc r1,r1,r0 r0<r1 r1 r1 - r0mov pc,lr 恢复现…

【算法与数据结构】108、LeetCode将有序数组转换为二叉搜索树

文章目录 一、题目二、解法三、完整代码 所有的LeetCode题解索引&#xff0c;可以看这篇文章——【算法和数据结构】LeetCode题解。 一、题目 二、解法 思路分析&#xff1a;这道题给我们的是一个有序数组&#xff0c;并要求构成一个平衡二叉搜索树&#xff0c;二叉搜索树的很容…

CSS 之 grid 网格布局

一、简介 ​ display: grid;用于设置元素内部的布局类型为网格布局&#xff0c;其外显类型为块级元素。该类型的元素将内部分为行和列&#xff0c;划分成一个个单元格&#xff0c;并通过一系列相关属性控制单元格及其内容的布局和大小。 ​ 该属性值的主要应用场景为&#xf…

这个锂电池保护方案来自TIDA-010030

本篇博客只是作为个人记录&#xff0c;拆锂电池有危险&#xff0c;撬棒刺穿外壳可能爆炸&#xff0c;请勿模仿&#xff0c;误操作电池数据可能失效&#xff0c;请勿模仿。 1、简介 1.1、目的 得到该电池的电量计芯片型号、IIC从机地址、通信的实际波形&#xff1b; 1.2、步…

百度飞浆OCR识别表格入门python实践

1. 百度飞桨&#xff08;PaddlePaddle&#xff09; 百度飞桨&#xff08;PaddlePaddle&#xff09;是百度推出的一款深度学习平台&#xff0c;旨在为开发者提供强大的深度学习框架和工具。飞桨提供了包括OCR&#xff08;光学字符识别&#xff09;在内的多种功能&#xff0c;可…

Linux驱动IO篇——异步通知

文章目录 什么是异步通知异步通知和异步IO的区别信号含义应用层使用信号驱动如何实现异步信号驱动实例 什么是异步通知 异步通知在Linux的实现中是通过信号&#xff0c;而信号是在软件层次上对中断机制的一种模拟。这种机制和中断非常类似&#xff0c;所以可以以中断的思想来理…

重新认识交叉编译

1. 我以前对交叉编译的认知 引用正点原子的话来讲就是: 说得对&#xff0c;但是不全面&#xff0c;直到最近项目中遇到了一个例子我才重新认识什么是交叉编译。 2. build/host/target的概念 参考: Cross-Compilation (automake) 参考: Specifying Target Triplets (Autocon…

Python二级 每周练习题18

练习一: 从键盘输入任意字符串&#xff0c;按照下面要求分离字符串中的字符: 1、分别取出该字符串的第偶数位的元素(提醒注意:是按照从左往右数的方式确定字符串的位置) 2、并依次存储到一个列表中; 3、输出这个列表。 答案: ninput(请输入任意字符串:) #创建变量n存放用户…

数据结构入门 — 树的概念与结构

本文属于数据结构专栏文章&#xff0c;适合数据结构入门者学习&#xff0c;涵盖数据结构基础的知识和内容体系&#xff0c;文章在介绍数据结构时会配合上动图演示&#xff0c;方便初学者在学习数据结构时理解和学习&#xff0c;了解数据结构系列专栏点击下方链接。 博客主页&am…

外包干了2个月,技术退步明显。。。。。

先说一下自己的情况&#xff0c;大专生&#xff0c;18年通过校招进入武汉某软件公司&#xff0c;干了接近4年的功能测试&#xff0c;今年年初&#xff0c;感觉自己不能够在这样下去了&#xff0c;长时间呆在一个舒适的环境会让一个人堕落!而我已经在一个企业干了四年的功能测试…

【多线程】Thread 类 详解

Thread 类 详解 一. 创建线程1. 继承 Thread 类2. 实现 Runnable 接口3. 其他变形4. 多线程的优势-增加运行速度 二. Thread 类1. 构造方法2. 常见属性3. 启动线程-start()4. 中断线程-interrupt()5. 线程等待-join()6. 线程休眠-sleep()7. 获取当前线程引用 三. 线程的状态1. …

Buffer Pool

一.Buffer Pool的含义 Buffer Pool&#xff1a;缓冲池&#xff0c;简称BP&#xff0c;其作用是用来缓存表数据与索引数据&#xff0c;减少磁盘IO操作&#xff0c;提升效率。当Mysql执行查询的sql语句的时候&#xff0c;会先去缓存当中看是否有对应的数据&#xff0c;如果有则直…

显示器显示的画面突然偏红色如何解决

显示器显示的画面突然偏红色如何解决 1. 概述2. 解决方法结束语 1. 概述 显示器显示的画面突然偏红色 &#xff0c;使用向日葵远程电脑&#xff0c;看到的画面是正常的&#xff0c;但是显示器上的画面确还是骗红的&#xff0c;这时候就需要看一下是不是开启了系统也夜间模式&a…

四川百幕晟科技:提升店铺质量方法是什么?

抖店是抖音旗下的移动电子商务平台&#xff0c;为商家提供在线销售和促销的机会。在抖店&#xff0c;经验值是商家评价和信誉的重要指标之一。反映了平台上商户的服务质量和用户满意度。那么&#xff0c;如何查看自己在抖店手机上的体验分数呢&#xff1f; 1、如何查看抖店手机…

Eclipse 安装串口终端工具

Eclipse已集成串口终端显示&#xff0c;只需要我们自己下载安装即可使用。使用SSH连接也差不多。 查看eclipse版本信息 help->About Eclipse 查看version&#xff0c;我的是4.7.3a&#xff0c;记住代号&#xff0c;我的是“Oxygen”,下面有用。 安装eclipse自带的“Termin…

FPGA实现Cordic算法——向量模式

FPGA实现Cordic算法——向量模式 FPGA实现Cordic算法——向量模式1.cordic算法基本原理2.FPGA实现cordic算法向量模式i、FPGA串行实现cordicii、FPGA流水线实现cordiciii、实验结果 FPGA实现Cordic算法——向量模式 1.cordic算法基本原理 FPGA中运算三角函数&#xff0c;浮点数…

初见QT,控件的基本应用,实现简单登录窗口

窗口实现代码 #include "widget.h"Widget::Widget(QWidget *parent): QWidget(parent) {//窗口设置this->setFixedSize(538, 373); //固定窗口大小this->setWindowIcon(QIcon("G:\\QT_Icon\\windos_icon2.png"))…

多图片展示弹窗插件

<!DOCTYPE html> <html><head><meta charset"UTF-8"><title>图片预览完善</title><style>/*** Created by WangCheng on 2020/9/24.*//*背景框*/.mask-layer * {padding: 0;margin: 0;box-sizing: border-box;}.mask-laye…