(unix网络编程)tcp回射程序二:避免僵尸进程
2013-12-16 19:12
169 查看
本例在上一例的基础上增加了singal函数来捕捉子进程退出时候产生的SIGCHLD信号,从而防止子进程变成僵尸进程。
服务器端的代码如下:
客户端代码如下:
服务器端的代码如下:
#include <stdio.h> #include <sys/types.h> #include <sys/socket.h> #include <unistd.h> #include <arpa/inet.h> #include <string.h> #include <errno.h> #include <stdlib.h> #include <signal.h> #include <sys/wait.h> #define MAXLINE 4096 #define SERV_PORT 5000 #define LISTENQ 5 void str_echo(int sockfd) { ssize_t n; char buf[MAXLINE]; const char *quit_code = "QUIT\n"; for(;;) { if ((n = read(sockfd, buf, MAXLINE)) > 0) { if (strcmp(buf, quit_code) == 0) { printf("client quit\n"); break; } if (write(sockfd, buf, n) < 0) { printf("write error:%s\n", strerror(errno)); } memset(buf, 0x00, MAXLINE); } if (n < 0 && errno != EINTR) { printf("str_echo: read error:%s\n", strerror(errno)); } } } void sig_chld(int signo) { pid_t pid; int stat; printf("SIGCHLD handled\n"); while ((pid = waitpid(-1, &stat, WNOHANG)) > 0) { printf("child %d terminated\n", pid); } } int main(int argc, char **argv) { int listenfd, connfd; pid_t childpid; socklen_t clilen; struct sockaddr_in cliaddr, servaddr; if ((listenfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { printf("socket error:%s\n", strerror(errno)); return -1; } memset(&servaddr, 0x00, sizeof(servaddr)); servaddr.sin_family = AF_INET; servaddr.sin_addr.s_addr = htonl(INADDR_ANY); servaddr.sin_port = htons(SERV_PORT); if (bind(listenfd, (struct sockaddr *)&servaddr, sizeof(servaddr)) < 0) { printf("bind error:%s\n", strerror(errno)); return -1; } if (listen(listenfd, LISTENQ) < 0) { printf("listen error:%s\n", strerror(errno)); return -1; } signal(SIGCHLD, sig_chld); for(;;) { clilen = sizeof(cliaddr); if ((connfd = accept(listenfd, (struct sockaddr *)&cliaddr, &clilen)) < 0) { printf("listen error:%s\n", strerror(errno)); return -1; } if ((childpid = fork()) == 0) { if (close(listenfd) < 0) { printf("close listenfd error:%s\n", strerror(errno)); } str_echo(connfd); exit(0); } if (close(connfd) < 0) { printf("close connfd error:%s\n", strerror(errno)); } } }
客户端代码如下:
#include <stdio.h> #include <sys/types.h> #include <sys/socket.h> #include <string.h> #include <errno.h> #include <arpa/inet.h> #include <stdlib.h> #define SERV_PORT 5000 #define MAXLINE 4096 void str_cli(FILE *fp, int sockfd) { const char *quit_code = "QUIT\n"; char sendline[MAXLINE], recvline[MAXLINE]; while (fgets(sendline, MAXLINE, fp) != NULL) { if (strcmp(sendline, quit_code) == 0) { printf("client quit\n"); break; } if (write(sockfd, sendline, strlen(sendline)) < 0) { printf("write error:%s\n", strerror(errno)); } if (read(sockfd, recvline, MAXLINE) == 0) { printf("server terminated:%s\n", strerror(errno)); } if (fputs(recvline, stdout) == EOF) { printf("fputs over\n"); } memset(sendline, 0x00, MAXLINE); memset(recvline, 0x00, MAXLINE); } if ((write(sockfd, quit_code, strlen(quit_code))) < 0) { printf("tell server quit error\n"); } } int main(int argc, char **argv) { int sockfd; struct sockaddr_in servaddr; if (argc != 2) { printf("tcpcli1 <IPaddres>\n"); return -1; } if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { printf("socket error:%s\n", strerror(errno)); return -1; } memset(&servaddr, 0x00, sizeof(servaddr)); servaddr.sin_family = AF_INET; servaddr.sin_port = htons(SERV_PORT); if (inet_pton(AF_INET, argv[1], &servaddr.sin_addr) < 0) { printf("inet_pton error:%s\n", strerror(errno)); return -1; } if (connect(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr)) < 0) { printf("connect error:%s\n", strerror(errno)); return -1; } str_cli(stdin, sockfd); exit(0); }
相关文章推荐
- 这个可以程序主要测试高级并发服务器程序怎样写会避免僵尸进程?
- UNIX网络编程——使用waitpid处理僵尸进程(TCP客户/服务器优化1)
- TCP预先派生子进程服务程序,accept无上锁保护
- 避免多次运行同一个程序进程
- 此程序可以产生僵尸进程
- UNIX网络编程——TCP回射服务器/客户端程序
- fork两次如何避免僵尸进程
- 避免僵尸进程的三种方法
- 僵尸进程的产生、危害及避免方法
- 【进程线程与同步】5.2 避免在同一机器上运行同一程序的多个实例
- 原因以及如何避免产生僵尸进程
- 避免僵尸进程
- fork两次如何避免僵尸进程
- linux僵尸进程产生的原因以及如何避免产生僵尸进程
- 僵尸进程的避免 .
- UNIX网络编程——TCP回射服务器/客户端程序
- 说说Linux中的信号处理和僵尸进程的避免
- (unix网络编程)tcp回射程序一:基本实现
- 进程学习回顾---两次fork避免僵尸进程
- 为何要fork()两次来避免产生僵尸进程?