TCP/IP网络编程学习(10):利用信号处理技术消灭僵尸进程和基于多任务的并发处理器

本文主要是介绍TCP/IP网络编程学习(10):利用信号处理技术消灭僵尸进程和基于多任务的并发处理器,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

利用信号处理技术消灭僵尸进程

子进程终止时产生SIGCHLD信号。就可以捕捉信号终止子进程。

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <sys/wait.h>void read_childproc(int sig){//子进程终止调用该函数int status;pid_t id=waitpid(-1, &status, WNOHANG);//将子进程正常终止if(WIFEXITED(status)){printf("Removed proc id: %d \n", id);printf("Child send: %d \n", WEXITSTATUS(status));}
}int main(int argc, char *argv[])
{pid_t pid;struct sigaction act;act.sa_handler=read_childproc;sigemptyset(&act.sa_mask);act.sa_flags=0;sigaction(SIGCHLD, &act, 0);pid=fork();if(pid==0){puts("Hi! I'm child process");sleep(10);//等待10s终止return 12;}else{   printf("Child proc id: %d \n", pid);pid=fork();if(pid==0){puts("Hi! I'm child process");sleep(10);exit(24);}else{int i;printf("Child proc id: %d \n", pid);for(i=0; i<5; i++){puts("wait...");sleep(5);}}}return 0;
}

基于多任务的并发服务器

在这里插入图片描述
每当有客户端请求服务时,服务器都创建子进程以提供服务。

  1. 服务器端(父进程)通过调用 accept画数受理连接请求 。
  2. 此时获取的套接字文件描述符创建并传递给子进程 。(因为子进程会复制父进程拥有的所有资源 。实际上根本不用另外经过传递文件描述符的过程 。)
  3. 子进程利用传递来 的文件描述符提供服务 。
while(1){adr_sz=sizeof(clnt_adr);clnt_sock=accept(serv_sock, (struct sockaddr*)&clnt_adr, &adr_sz);if(clnt_sock==-1)continue;elseputs("new client connected...");pid=fork();if(pid==-1){close(clnt_sock);continue;}if(pid==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 disconnected...");return 0;}elseclose(clnt_sock);}

通过fork函数复制文件描述符

套接字属于操作系统,fork子进程只是将父进程的文件描述符拿了过去。进程拥有代表相应套接字的文件描述符。父进程将2个套接字(一个是服务器端套接字,另一个是与客户端连接的套接字)文件描述符复制给子进程 。
在这里插入图片描述

1个套接字中存在2个文件描述符时,只有2个文件描述符都终止 (销毁)后,才能销毁套接字 。如果维持阁中的连接状态,即使子进程销毁了与客户端连接的套接字文件描述符,也无法完全销毁套接字(服务器端套接字同样如此)。 因此,调用fork函数后,要将无关的套接字文件描述符关掉,

在这里插入图片描述

一次accept就会创建一个套接字。

分割TCP的I/O程序

传输数据后需要等待服务器端返回的数据,因为程序代码中重复调用了 read和write函数 。 只能能这么写的原因之一是,程序在 1 个进程中运行 。 但现在可以创建多个进程,因此可以分割数据收发过程 。 客户端的父进程负责接收数据,额外创建的子进程负责发送数据 。 分割后,不同进程分别负责输入和输出,这样无论客户端是否从服务器端接收完数据都可以进行传输 。
在这里插入图片描述
之前的回声客户端要接收到服务器的数据才发数据,现在可以连发数据。
在这里插入图片描述
分割I/O后的客户端发送数据时不必考虑接收数据的情况,因此可以连续发送数据,由此提高同一时间内传输的数据量 。 这种差异在网速较慢时尤为明显 。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>#define BUF_SIZE 30
void error_handling(char *message);
void read_routine(int sock, char *buf);
void write_routine(int sock, char *buf);int main(int argc, char *argv[])
{int sock;pid_t pid;char buf[BUF_SIZE];struct sockaddr_in serv_adr;if(argc!=3) {printf("Usage : %s <IP> <port>\n", argv[0]);exit(1);}sock=socket(PF_INET, SOCK_STREAM, 0);  memset(&serv_adr, 0, sizeof(serv_adr));serv_adr.sin_family=AF_INET;serv_adr.sin_addr.s_addr=inet_addr(argv[1]);serv_adr.sin_port=htons(atoi(argv[2]));if(connect(sock, (struct sockaddr*)&serv_adr, sizeof(serv_adr))==-1)error_handling("connect() error!");pid=fork();if(pid==0)write_routine(sock, buf);//子进程程用来写else read_routine(sock, buf);//父进程用来读close(sock);return 0;
}void read_routine(int sock, char *buf)
{while(1){int str_len=read(sock, buf, BUF_SIZE);if(str_len==0)return;buf[str_len]=0;printf("Message from server: %s", buf);}
}
void write_routine(int sock, char *buf)
{while(1){fgets(buf, BUF_SIZE, stdin);if(!strcmp(buf,"q\n") || !strcmp(buf,"Q\n")){	shutdown(sock, SHUT_WR);return;}write(sock, buf, strlen(buf));}
}
void error_handling(char *message)
{fputs(message, stderr);fputc('\n', stderr);exit(1);
}

这篇关于TCP/IP网络编程学习(10):利用信号处理技术消灭僵尸进程和基于多任务的并发处理器的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/318773

相关文章

Android使用java实现网络连通性检查详解

《Android使用java实现网络连通性检查详解》这篇文章主要为大家详细介绍了Android使用java实现网络连通性检查的相关知识,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录NetCheck.Java(可直接拷贝)使用示例(Activity/Fragment 内)权限要求

Python多任务爬虫实现爬取图片和GDP数据

《Python多任务爬虫实现爬取图片和GDP数据》本文主要介绍了基于FastAPI开发Web站点的方法,包括搭建Web服务器、处理图片资源、实现多任务爬虫和数据可视化,同时,还简要介绍了Python爬... 目录一. 基于FastAPI之Web站点开发1. 基于FastAPI搭建Web服务器2. Web服务

Apache服务器IP自动跳转域名的问题及解决方案

《Apache服务器IP自动跳转域名的问题及解决方案》本教程将详细介绍如何通过Apache虚拟主机配置实现这一功能,并解决常见问题,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,... 目录​​问题背景​​解决方案​​方法 1:修改 httpd-vhosts.conf(推荐)​​步骤

python协程实现高并发的技术详解

《python协程实现高并发的技术详解》协程是实现高并发的一种非常高效的方式,特别适合处理大量I/O操作的场景,本文我们将简单介绍python协程实现高并发的相关方法,需要的小伙伴可以了解下... 目录核心概念与简单示例高并发实践:网络请求协程如何实现高并发:核心技术协作式多任务与事件循环非阻塞I/O与连接

Linux(centos7)虚拟机没有IP问题及解决方案

《Linux(centos7)虚拟机没有IP问题及解决方案》文章介绍了在CentOS7中配置虚拟机网络并使用Xshell连接虚拟机的步骤,首先,检查并配置网卡ens33的ONBOOT属性为yes,然后... 目录输入查看ZFhrxIP命令:ip addr查看,没有虚拟机IP修改ens33配置文件重启网络Xh

Linux kill正在执行的后台任务 kill进程组使用详解

《Linuxkill正在执行的后台任务kill进程组使用详解》文章介绍了两个脚本的功能和区别,以及执行这些脚本时遇到的进程管理问题,通过查看进程树、使用`kill`命令和`lsof`命令,分析了子... 目录零. 用到的命令一. 待执行的脚本二. 执行含子进程的脚本,并kill2.1 进程查看2.2 遇到的

Java AOP面向切面编程的概念和实现方式

《JavaAOP面向切面编程的概念和实现方式》AOP是面向切面编程,通过动态代理将横切关注点(如日志、事务)与核心业务逻辑分离,提升代码复用性和可维护性,本文给大家介绍JavaAOP面向切面编程的概... 目录一、AOP 是什么?二、AOP 的核心概念与实现方式核心概念实现方式三、Spring AOP 的关

Java JUC并发集合详解之线程安全容器完全攻略

《JavaJUC并发集合详解之线程安全容器完全攻略》Java通过java.util.concurrent(JUC)包提供了一整套线程安全的并发容器,它们不仅是简单的同步包装,更是基于精妙并发算法构建... 目录一、为什么需要JUC并发集合?二、核心并发集合分类与详解三、选型指南:如何选择合适的并发容器?在多

Java 结构化并发Structured Concurrency实践举例

《Java结构化并发StructuredConcurrency实践举例》Java21结构化并发通过作用域和任务句柄统一管理并发生命周期,解决线程泄漏与任务追踪问题,提升代码安全性和可观测性,其核心... 目录一、结构化并发的核心概念与设计目标二、结构化并发的核心组件(一)作用域(Scopes)(二)任务句柄

Java中的Schema校验技术与实践示例详解

《Java中的Schema校验技术与实践示例详解》本主题详细介绍了在Java环境下进行XMLSchema和JSONSchema校验的方法,包括使用JAXP、JAXB以及专门的JSON校验库等技术,本文... 目录1. XML和jsON的Schema校验概念1.1 XML和JSON校验的必要性1.2 Sche