每天一小步——自写服务器与信号处理僵尸子进程
来源:互联网 发布:艾薇儿已经去世 知乎 编辑:程序博客网 时间:2024/05/17 01:07
学习中写了一个简单的小服务器程序,可以用来上传备份文件。tcp/ip协议的三次握手是不变的,我们所要做的就是在这个框架上搭建自己想要的功能实现扩展,并优化程序!
虽然是一个小服务器程序,但是也是会遇到不少问题,但最后还是努力解决了!如文件名与文件内容出现交错,最后用传完文件名后,采用一个确认,然后再传送文件内容来解决了内容!
为了实现服务多用户的功能,采用了fork函数。但是采用fork后必然会出现僵尸子进程,处理好僵尸进程也为难了我一会!刚开始采用了wait和waitpid函数!
wait函数会阻塞住进程,影响了服务多用户的功能。子进程在终止时会给父进程发SIGCHLD信号,该信号的默认处理动作是忽略,父进程可以自定义SIGCHLD信号的处理函数,这样父进程只需专心处理自己的工作,不必关心子进程了,子进程终止时会通知父进程,父进程在信号处理函数中调用wait清理子进程即可!但是我的程序在采用这个方法时遇到了一个至今没法解决的问题,老是无限循环一个错误!有兴趣的同学可以帮我实现!
waitpid函数虽然是封装了wait函数,但是比wait灵活许多,但是我用了 waitpid(0,&status,WNOHANG|WUNTRACED);时总是会残留一个僵尸进程,无法全部处理完全,有兴趣的高手,可以帮一下小弟!
由于UNIX的历史原因,要想不产生僵尸进程还有另外一种办法:父进程调用sigaction将SIGCHLD的处理动作置为SIG_IGN,这样fork出来的子进程在终止时会自动清理
掉,不会产生僵尸进程,也不会通知父进程。系统默认的忽略动作和用户用sigaction函数自定义的忽略通常是没有区别的,但这是一个特例。这个方法是方法我没出现错误,但此方法对于Linux可用,但不保证在其它UNIX系统上都可用。
#include <stdio.h>#include <stdlib.h>#include <string.h>#include <unistd.h>#include <sys/socket.h>#include <netinet/in.h>#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>#include <signal.h>#include <sys/wait.h>#define MAXLINE 128#define SERV_PORT 8000void pid_action(int pid,int listenfd,int connfd,struct sockaddr_in *cliaddr){ int i,n,ret=0; int dest; char buf[MAXLINE],ibuf[MAXLINE]; char str[INET_ADDRSTRLEN]; char *copy=NULL; close(listenfd); bzero(buf,MAXLINE); n=read(connfd,buf,MAXLINE); dest=open(buf,O_RDWR|O_CREAT|O_TRUNC,0666); if(dest<0){ perror("open"); exit(1); } write(connfd,"1",1);/*transmission on demand*/ bzero(buf,MAXLINE); /*receive the file content*/ while((n=read(connfd,buf,MAXLINE))>0){ copy=buf; while(n>0){ ret=write(dest,copy,n); n=n-ret; copy=copy+ret; } write(dest,buf,n); bzero(buf,MAXLINE); } printf("received from %s at PORT %d\n",inet_ntop(AF_INET,&cliaddr->sin_addr,str,sizeof(str)),ntohs(cliaddr->sin_port)); close(dest); close(connfd);}int main(void){ struct sockaddr_in servaddr,cliaddr; struct sigaction newact,oldact; socklen_t cliaddr_len; int listenfd,connfd,status; pid_t pid; /*sigaction configuration*/ newact.sa_handler=SIG_IGN; sigemptyset(&newact.sa_mask); newact.sa_flags=0; sigaction(SIGCHLD,&newact,&oldact); listenfd=socket(AF_INET,SOCK_STREAM,0); /*net configuration*/ 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); if((pid=fork())<0){ perror("fork"); exit(1); } if(pid==0){ pid_action(pid,listenfd,connfd,&cliaddr); exit(1); } if(pid>0){ close(connfd); } }}
- 每天一小步——自写服务器与信号处理僵尸子进程
- 36-多进程并发服务器(僵尸进程与信号处理)
- Head First HTML5 Programming—每天一小步-(一)
- Head First HTML5 Programming—每天一小步-(二)
- 网络编程(13)—— 利用信号处理函数signal和sigaction销毁僵尸进程
- 利用信号处理技术消灭僵尸进程
- 进程—僵尸进程与孤儿进程
- 进程—僵尸进程与孤儿进程
- 测试的每天一小步
- 每天一小步,人生一大步——8086/8088基本指令
- 每天一小步——C语言中嵌入正则表达式
- 每天一小步——设备模型之kobject,kset及其关系
- UNIX网络编程——使用waitpid处理僵尸进程(TCP客户/服务器优化1)
- 孤儿进程与僵尸进程【一】
- 说说Linux中的信号处理和僵尸进程的避免
- 说说Linux中的信号处理和僵尸进程的避免
- linux下的僵尸进程处理SIGCHLD信号
- linux下的僵尸进程处理SIGCHLD信号
- 多线程下的懒汉式和饿汉式
- 网站用户忠诚度
- [Anonymous] 给一个数组a[2n] ,将前后两段数组元素交叉排列, a1..anb1...bn 变成 a1b1...anbn
- jQuery Ajax事件-ajaxStart(callback)
- 老码农:如何写出让自己满意的代码
- 每天一小步——自写服务器与信号处理僵尸子进程
- 自己动手写ndk-gdb
- 中文Access 2003案例经典(奋斗的小鸟)_PDF 电子书
- Toad for Oracle 12 下载地址及注册码 及如何连接64位oracle 11g
- 菜鸟学习:有些同学VMware linux在NAT下连不上网……
- 串口通讯编程一日通2(Overlapped IO模型)
- 冒泡排序法和选择排序法
- sublime 自动缩进 问题的解决方案
- [阿里] C++ 实现一个 不能继承的类