我的编程空间,编程开发者的网络收藏夹
学习永远不晚

计算机网络编程 | 并发服务器代码实现(多进程/多线程)

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

计算机网络编程 | 并发服务器代码实现(多进程/多线程)

在这里插入图片描述

欢迎关注博主 Mindtechnist 或加入【Linux C/C++/Python社区】一起学习和分享Linux、C、C++、Python、Matlab,机器人运动控制、多机器人协作,智能优化算法,滤波估计、多传感器信息融合,机器学习,人工智能等相关领域的知识和技术。



专栏:《网络编程》


什么是并发服务器

当涉及到构建高性能的服务器应用程序时,我们通常会考虑使用并发服务器来处理多个客户端请求。在并发服务器中,多进程和多线程是两种常见的并发模型,它们都有各自的优点和适用场景。本文将介绍多进程和多线程并发服务器的基础知识。

多进程并发服务器
多进程并发服务器通过创建多个子进程来处理客户端请求。每个子进程是操作系统中独立运行的单位,拥有自己的内存空间和资源。当有新的客户端连接请求到达时,服务器创建一个新的子进程来处理该请求。子进程负责与客户端通信并提供所需的服务。
多进程并发服务器的优点是稳定性高。由于每个子进程都是相互独立的,一个子进程的崩溃或错误不会影响其他子进程的执行。这种独立性使得多进程并发服务器能够有效地隔离错误,提高服务器的可靠性。
然而,多进程并发服务器也有一些缺点。创建和管理多个进程需要消耗更多的系统资源,包括内存和CPU时间。进程间的通信也需要特殊的机制,例如管道或共享内存,以便在不同进程之间传递数据。此外,由于每个进程都有自己的内存空间,进程间的数据共享和同步可能会变得复杂。

多线程并发服务器
多线程并发服务器通过创建多个线程来处理客户端请求。线程是在进程内部运行的独立执行流,共享同一个进程的内存空间和资源。与多进程不同,多线程服务器不需要创建新的进程来处理请求,而是在同一个进程中创建多个线程。
多线程并发服务器的优点是资源消耗较少。与进程相比,线程的创建和切换开销更小,因为它们共享进程的资源。这使得多线程并发服务器更加轻量级,能够更高效地利用系统资源。
然而,多线程并发服务器也存在一些问题。首先,线程共享进程的内存空间,因此在多线程环境中访问共享数据需要特殊的同步机制,以避免竞态条件和数据不一致。其次,由于线程共享相同的地址空间,一个线程的错误可能会影响整个进程,导致服务器崩溃或不稳定。

选择适合的并发模型
在选择多进程还是多线程并发服务器时,需要根据具体的应用需求和性能要求进行权衡。以下是一些建议:

  • 如果稳定性和容错性是首要考虑因素,多进程并发服务器可能是更好的选择。每个子进程的独立性可以有效地隔离错误,提高服务器的可靠性。
  • 如果服务器需要处理大量的并发连接并需要更高的性能和资源利用率,多线程并发服务器可能更适合。线程的创建和切换开销相对较小,可以更高效地处理并发请求。
  • 如果同时需要稳定性和性能,可以考虑使用混合模型,即在每个进程中创建多个线程,以实现更好的负载平衡和资源利用率。

无论选择多进程还是多线程并发服务器,都需要注意正确处理并发访问共享数据的问题,使用适当的同步机制(如锁、信号量)来保证数据的一致性和正确性。

总结起来,多进程和多线程并发服务器是实现高性能服务器的常见方式。它们各有优劣,选择合适的并发模型需要考虑应用需求和性能要求,并注意处理并发访问共享数据的问题。

多进程并发服务器代码实现

使用多进程并发服务器时要考虑以下几点:

  • 父进程最大文件描述个数(父进程中需要close关闭accept返回的新文件描述符);
  • 系统内创建进程个数(与内存大小相关);
  • 进程创建过多是否降低整体服务性能(进程调度);

server

#include #include #include #include #include #include #include #include "wrap.h"#define MAXLINE 80#define SERV_PORT 800void do_sigchild(int num){while (waitpid(0, NULL, WNOHANG) > 0);}int main(void){struct sockaddr_in servaddr, cliaddr;socklen_t cliaddr_len;int listenfd, connfd;char buf[MAXLINE];char str[INET_ADDRSTRLEN];int i, n;pid_t pid;struct sigaction newact;newact.sa_handler = do_sigchild;sigemptyset(&newact.sa_mask);newact.sa_flags = 0;sigaction(SIGCHLD, &newact, NULL);listenfd = Socket(AF_INET, SOCK_STREAM, 0);bzero(&servaddr, sizeof(servaddr));servaddr.sin_family = AF_INET;servaddr.sin_addr.s_addr = htonl(INADDR_ANY);servaddr.sin_port = htons(SERV_PORT);Bind(listenfd, (struct sockaddr *)&servaddr, sizeof(servaddr));Listen(listenfd, 20);printf("Accepting connections ...\n");while (1) {cliaddr_len = sizeof(cliaddr);connfd = Accept(listenfd, (struct sockaddr *)&cliaddr, &cliaddr_len);pid = fork();if (pid == 0) {Close(listenfd);while (1) {n = Read(connfd, buf, MAXLINE);if (n == 0) {printf("the other side has been closed.\n");break;}printf("received from %s at PORT %d\n",inet_ntop(AF_INET, &cliaddr.sin_addr, str, sizeof(str)),ntohs(cliaddr.sin_port));for (i = 0; i < n; i++)buf[i] = toupper(buf[i]);Write(connfd, buf, n);}Close(connfd);return 0;} else if (pid > 0) {Close(connfd);} elseperr_exit("fork");}Close(listenfd);return 0;}

client

#include #include #include #include #include "wrap.h"#define MAXLINE 80#define SERV_PORT 6666int main(int argc, char *argv[]){struct sockaddr_in servaddr;char buf[MAXLINE];int sockfd, n;sockfd = Socket(AF_INET, SOCK_STREAM, 0);bzero(&servaddr, sizeof(servaddr));servaddr.sin_family = AF_INET;inet_pton(AF_INET, "127.0.0.1", &servaddr.sin_addr);servaddr.sin_port = htons(SERV_PORT);Connect(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr));while (fgets(buf, MAXLINE, stdin) != NULL) {Write(sockfd, buf, strlen(buf));n = Read(sockfd, buf, MAXLINE);if (n == 0) {printf("the other side has been closed.\n");break;} elseWrite(STDOUT_FILENO, buf, n);}Close(sockfd);return 0;}

多线程并发服务器代码实现

在使用线程模型开发服务器时需考虑以下问题:

  • 调整进程内最大文件描述符上限;
  • 线程如有共享数据,考虑线程同步;
  • 服务于客户端线程退出时,退出处理(退出值,分离态);
  • 系统负载,随着链接客户端增加,导致其它线程不能及时得到CPU;

server

#include #include #include #include #include #include "wrap.h"#define MAXLINE 80#define SERV_PORT 6666struct s_info {struct sockaddr_in cliaddr;int connfd;};void *do_work(void *arg){int n,i;struct s_info *ts = (struct s_info*)arg;char buf[MAXLINE];char str[INET_ADDRSTRLEN];pthread_detach(pthread_self());while (1) {n = Read(ts->connfd, buf, MAXLINE);if (n == 0) {printf("the other side has been closed.\n");break;}printf("received from %s at PORT %d\n",inet_ntop(AF_INET, &(*ts).cliaddr.sin_addr, str, sizeof(str)),ntohs((*ts).cliaddr.sin_port));for (i = 0; i < n; i++)buf[i] = toupper(buf[i]);Write(ts->connfd, buf, n);}Close(ts->connfd);}int main(void){struct sockaddr_in servaddr, cliaddr;socklen_t cliaddr_len;int listenfd, connfd;int i = 0;pthread_t tid;struct s_info ts[256];listenfd = Socket(AF_INET, SOCK_STREAM, 0);bzero(&servaddr, sizeof(servaddr));servaddr.sin_family = AF_INET;servaddr.sin_addr.s_addr = htonl(INADDR_ANY);servaddr.sin_port = htons(SERV_PORT);Bind(listenfd, (struct sockaddr *)&servaddr, sizeof(servaddr));Listen(listenfd, 20);printf("Accepting connections ...\n");while (1) {cliaddr_len = sizeof(cliaddr);connfd = Accept(listenfd, (struct sockaddr *)&cliaddr, &cliaddr_len);ts[i].cliaddr = cliaddr;ts[i].connfd = connfd;pthread_create(&tid, NULL, do_work, (void*)&ts[i]);i++;}return 0;}

client

#include #include #include #include #include "wrap.h"#define MAXLINE 80#define SERV_PORT 6666int main(int argc, char *argv[]){struct sockaddr_in servaddr;char buf[MAXLINE];int sockfd, n;sockfd = Socket(AF_INET, SOCK_STREAM, 0);bzero(&servaddr, sizeof(servaddr));servaddr.sin_family = AF_INET;inet_pton(AF_INET, "127.0.0.1", &servaddr.sin_addr);servaddr.sin_port = htons(SERV_PORT);Connect(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr));while (fgets(buf, MAXLINE, stdin) != NULL) {Write(sockfd, buf, strlen(buf));n = Read(sockfd, buf, MAXLINE);if (n == 0)printf("the other side has been closed.\n");elseWrite(STDOUT_FILENO, buf, n);}Close(sockfd);return 0;}

618图书推荐

书籍是知识的海洋,计算机好书推荐
在这里插入图片描述
🔥🔥🔥618,清华社 IT BOOK 多得图书活动开始啦!活动时间为2023 年6 月7 日至6 月18 日,清华社为您精选多款高分好书,涵盖了 C++、Java、Python、前端、后端、数据库、算法与机器学习等多个IT 开发领域,适合不同层次的读者。全场5 折,扫码领券更有优惠哦!快来京东点击链接 IT BOOK多得查看详情吧!


在这里插入图片描述
在这里插入图片描述


来源地址:https://blog.csdn.net/qq_43471489/article/details/131117250

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

计算机网络编程 | 并发服务器代码实现(多进程/多线程)

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

计算机网络编程 | 并发服务器代码实现(多进程/多线程)

欢迎关注博主 Mindtechnist 或加入【Linux C/C++/Python社区】一起学习和分享Linux、C、C++、Python、Matlab,机器人运动控制、多机器人协作,智能优化算法,滤波估计、多传感器信息融合,机器学
2023-08-18

Linux网络编程如何使用多进程实现服务器并发访问

Linux网络编程如何使用多进程实现服务器并发访问,很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。采用多进程的方式实现服务器的并发访问的经典范例。程序实现功能:1
2023-06-13

计算机网络编程 | 多路I/O转接服务器

欢迎关注博主 Mindtechnist 或加入【Linux C/C++/Python社区】一起学习和分享Linux、C、C++、Python、Matlab,机器人运动控制、多机器人协作,智能优化算法,滤波估计、多传感器信息融合,机器学
2023-08-18

高并发网络编程:使用Go WaitGroup实现并发服务器

以下是使用Go的WaitGroup实现高并发服务器的示例代码:```gopackage mainimport ("fmt""net""sync")func handleRequest(conn net.Conn) {defer conn.C
2023-10-08

如何进行C#网络编程服务器端程序的实现源码浅析

本篇文章为大家展示了如何进行C#网络编程服务器端程序的实现源码浅析,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。C#网络编程服务器端程序实现源码是怎么样的呢?让我们来看看其中重要的一部分:由于在此次
2023-06-17

多台主机使用DNS服务器实现网络负载均衡详细教程

解决方法有很多,如使用Windows 2000或Windows Server 2003提供网络负载均衡服务,但该服务的设置非常复杂。而通过DNS服务器实现网络负载均衡则是一种比较简单的方法。  笔者以企业网中的Web服务器为例来介绍一下如何
2023-05-25

编程热搜

目录