【TCP/IP】多进程服务器的实现(进阶) - 多进程服务器模型及代码实现

        经过前面的铺垫,我们已经具备实现并发服务器的基础了,接下来让我们尝试将之前的单任务回声服务器改装成多任务并发模式吧!

多任务回声服务器模型

        在编写代码前,先让我们大致将多任务(回声)服务器的模型抽象一下,如下图所示:

        当客户端请求服务(连接请求)时,回声服务器端便会创建子进程以提供服务。为了完成这些任务,需要经过以下过程:

  • 第一阶段 : 回声服务器端(父进程)调用accept函数受理客户端发来的连接请求。
  • 第二阶段 : 父进程套接字的文件描述符被拷贝传递给子进程 。
  • 第三阶段 : 子进程利用传递来的文件描述符提供服务。

        OK,让我们开始试着用代码去实现

multi_echoserver.cpp

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <signal.h>
#include <sys/wait.h>
#include <arpa/inet.h>
#include <sys/socket.h>#define BUF_SIZE 1024void Handler_childproc(int sig)
{int status;pid_t pid = waitpid(-1, &status, WNOHANG);printf("Removed process id: %d \n", pid);
}void Sender_message(char *message)
{puts(message);exit(1);
}int main(int argc, char *argv[])
{int serv_sock, clnt_sock;int str_len, state, port;struct sockaddr_in serv_adr, clnt_adr;struct sigaction act;pid_t pid;socklen_t adr_sz;char buf[BUF_SIZE];//防止僵尸进程act.sa_handler = Handler_childproc;sigemptyset(&act.sa_mask);act.sa_flags = 0;state = sigaction(SIGCHLD, &act, 0);serv_sock = socket(PF_INET, SOCK_STREAM, 0);if (serv_sock == -1){Sender_message((char *)"Socket creation error");}printf("Please input the port of socket that you want to create:\n");scanf("%d", &port);memset(&serv_adr, 0, sizeof(serv_adr));serv_adr.sin_family = AF_INET;serv_adr.sin_addr.s_addr = htonl(INADDR_ANY);serv_adr.sin_port = htons(port);if (bind(serv_sock, (struct sockaddr *)&serv_adr, sizeof(serv_adr)) == -1){Sender_message((char *)"bind error");}if (listen(serv_sock, 5) == -1){Sender_message((char *)"listen error");}while (1){adr_sz = sizeof(clnt_adr);//accept后(受理客户端发来的请求)创建子进程clnt_sock = accept(serv_sock, (struct sockaddr *)&clnt_adr, &adr_sz);if (clnt_sock == -1){continue;}else{puts("New client was connected...");}pid = fork();switch (pid){case -1:{close(clnt_sock);continue;}case 0: //子进程{//关闭服务器端套接字的文件描述符(很重要,若不处理会使服务器端套接字最终无法正常关闭)close(serv_sock);while ((str_len = read(clnt_sock, buf, BUF_SIZE)) != 0){write(clnt_sock, buf, str_len);}close(clnt_sock);puts("Client was disconnected...");return 0;}default: //父进程{//关闭客户端连接close(clnt_sock);break;}}}close(serv_sock);return 0;
}

        * 可以直接用之前编译的回声客户端代码,参见: 回声客户端缺陷的解决 这一篇文章

        运行结果:

        启动多个回声客户端后,没啥问题,功能正常~

补充:

        在上述代码中(multi_echoserver),调用fork函数后,父进程会复制2个套接字的文件描述符给子进程(一个是服务器,一个是客户端),过程如下图所示:

        当1个套接字中衍生出了2个文件描述符时,只有这2个描述符都被销毁后,套接字才能被完全销毁。(无论是在客户端还是服务器端,依此类推)因此,在调用fork函数后,一定要将无关的套接字的文件描述符处理好,否则将导致套接字无法正常关闭。 

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

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

相关文章

Jenkins自动化构建

自动化构建 Jenkins 是一款开源 CI&CD 软件&#xff0c;用于自动化各种任务&#xff0c;包括构建、测试和部署软件 Jenkins 支持各种运行方式&#xff0c;可通过系统包、Docker 或者通过一个独立的 Java 程序 安装依赖 安装参考&#xff1a;Windows环境下安装Jenkins **…

MySQL数据库——高级查询语句

MySQL数据库——高级查询语句 一、数据库查询二、高效查询方式1.指定指字段进行查询——SELECT2.对字段进行去重查询——DISTINCT3.条件查询——where3.逻辑关系的增加查询——and 和 or4.已知值的数据记录查询——IN5.范围内数据记录查询——BETWEEN6.通配符查询7.关键字排序查…

ng-zorro select Multiple selection 一行展示

问题&#xff1a; ng-zorro 的多项选择组件&#xff0c;选完选项之后不要换行展示&#xff0c;不换行&#xff0c;超出隐藏或者可滚动。这个问题的关键点在于&#xff1a; 各个选项数据字符串长度不确定&#xff0c;不能够准确知道当前容器最大能够渲染多少个选项&#xff0c;…

微服务如何治理

微服务远程调用可能有如下问题&#xff1a; 注册中心宕机&#xff1b; 服务提供者B有节点宕机&#xff1b; 服务消费者A和注册中心之间的网络不通&#xff1b; 服务提供者B和注册中心之间的网络不通&#xff1b; 服务消费者A和服务提供者B之间的网络不通&#xff1b; 服务提供者…

【人工智能】人工智能和双曲几何

一、说明 作为人工智能技术的理论支撑,几何学是必不可少的;目前直接的几何技术有:计算几何--对集合体如点云处理有用;射影几何--对3d重构有用;双曲几何--在自然语言的词嵌入做基础数学模型,另外深度学习国外有双曲网络在应用。本文针对双曲几何进行探讨。 二、各种几何的…

Oracle-抢购活动出现交易耗时飙高案例

问题背景: 接用户保障&#xff0c;他们的核心交易库在理财抢购活动期间出现交易耗时飙高的问题&#xff0c;交易耗时从原来的130毫秒飙高到1秒以上&#xff0c;请求分析交易耗时飙高原因。 问题分析&#xff1a; 通过应用的后台日志记录&#xff0c;发现交易耗时飙高的主要在于…

Unity | HDRP高清渲染管线学习笔记:Lightmapping(光照烘焙)与Lightmap(光照贴图)

目录 相关概念 1.渐进式光照贴图烘焙 1.1 渐进式光照贴图烘焙对模型的要求 1.2 渐进式光照贴图烘焙对硬件的要求 1.3 渐进式光照贴图烘焙支持的Unity渲染管线 1.4 进行渐进式光照贴图烘焙结果 1.5 渐进式光照贴图烘焙的CPU版本和GPU版本 1.6 Lighting窗口Lightmapping …

Elasticsearch介绍与应用

Elasticsearch介绍与应用 Elasticsearch的官方文档。 Elasticsearch官网参考文档&#xff1a;https://www.elastic.co/guide/index.html Elasticsearch官方下载地址&#xff1a;https://www.elastic.co/cn/downloads/elasticsearch mvnrepository依赖库地址&#xff1a;http…

数据结构--顺序栈的实现

数据结构–顺序栈的实现 顺序栈的定义 顺序栈的定义代码实现 #define MaxSize 10 typedef struct {ElemType data[MaxSize]; //静态数组存放栈中元素int top; //栈顶指针 } SqStack;int main() {SqStack S; //声明一个顺序栈(分配空间)//... ...return 0; }一些常见操作 初始…

机器视觉初步8:特征提取专题

文章目录 1.角点检测2.纹理特征提取3.特征描述符匹配3.1 Harris角点描述符3.2 SIFT&#xff08;尺度不变特征变换&#xff09;描述符3.3 SURF&#xff08;加速稳健特征&#xff09;描述符 4.基于深度学习的特征提取 在机器视觉中&#xff0c;特征提取是从目标图像中提取有用的视…

linux - spin lock实现分析

linux - spin lock实现分析 spinlock1 spinlock的数据结构2 spinlock的接口2.1 spin_lock_init2.2 spin_lock2.3 spin_unlock2.4 spin_lock_irq2.5 spin_unlock_irq2.6 spin_lock_irqsave2.7 spin_unlock_irqrestore2.8 spin_lock_bh2.9 spin_unlock_bh spinlock 1 spinlock的数…

我心中的TOP1编程语言—JavaScript

作为一名研发工程师&#xff08;程序员&#xff09;&#xff0c;平时工作中肯定会接触或了解很多编程语言。每个人都会有自己工作中常用的语言&#xff0c;也会有偏爱的一些编程语言。而我心中的最爱&#xff0c;毫无疑问&#xff0c;就是 JavaScript。 JavaScript 是一门编程…