简单回射程序之处理僵死进程版服务器程序

一、server.c

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <unistd.h>
#include <signal.h>
#include <sys/socket.h>

#define SERV_PORT 9999
#define MAXLINE 4096
#define LISTENQ 1024
#define SA struct sockaddr

typedef void Sigfunc(int);

void str_echo(int);
void sig_chld(int);
ssize_t writen(int, const void*, size_t);
Sigfunc *signal(int, Sigfunc*);

int main(int argc, char *argv[]) {
    int listenfd, connfd;
    pid_t childpid;
    socklen_t clilen;
    struct sockaddr_in cliaddr, servaddr;

    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, (SA *)&servaddr, sizeof(servaddr));

    listen(listenfd, LISTENQ); 

    signal(SIGCHLD, sig_chld); /* Install signal processing function */

    for ( ; ; ) {
        clilen = sizeof(cliaddr);
        connfd = accept(listenfd, (SA *)&cliaddr, &clilen);

        if ( (childpid = fork()) == 0) { /* Generate child processes to handle foreign connections */
            close(listenfd);
            str_echo(connfd);
            exit(0);
        }
        close(connfd);
    }
    close(listenfd);
    exit(0);
}

void str_echo(int sockfd) {
    ssize_t n;
    char buf[MAXLINE];

    again:
    while ( (n = read(sockfd, buf, MAXLINE)) > 0) {
        writen(sockfd, buf, n);
        bzero(buf, sizeof(buf));
    }
    if (n < 0 && errno == EINTR) {
        goto again;
    } else if (n < 0) {
        perror("read");
    }
}

二、writen.c

#include <unistd.h>
#include <errno.h>

ssize_t writen(int fd, const void *vptr, size_t n) {
    size_t nleft;
    ssize_t nwriten;
    const char *ptr;

    ptr = vptr;
    nleft = n;
    while (nleft > 0) {
        if ( (nwriten = write(fd, ptr, nleft)) <= 0) {
            if (nwriten < 0 && errno) {
                nwriten = 0; /* call write() again */
            } else {
                return (-1); /* error */
            }
        } 
        nleft -= nwriten;
        ptr += nwriten;
    }
    return (n - nwriten);
}

三、signal.c

#include <signal.h>

typedef void Sigfunc(int);

Sigfunc *signal(int signo, Sigfunc *func) {
    struct sigaction act, oact;

    act.sa_handler = func;
    sigemptyset(&act.sa_mask);
    act.sa_flags = 0;
    if (signo == SIGALRM) {
#ifdef SA_INTERRUPT
        act.sa_flags |= SA_INTERRUPT; /* SunOS 4.x */
#endif
    } else {
#ifdef SA_RESTART
    act.sa_flags |= SA_RESTART;   /* SVR4, 4.4BSD */
#endif
    }
    if (sigaction(signo, &act, &oact) < 0) {
    return SIG_ERR;
    }
    return (oact.sa_handler);
}

四、sig_chld.c

#include <stdio.h>
#include <sys/wait.h>

void sig_chld(int signo) {
    pid_t pid;
    int stat;
    
    pid = wait(&stat);
    printf("child %d terminated\n", pid);
    return;
}

五、Makefile

target=server
cc=gcc
$(target):writen.o server.o signal.o sig_chld.o
        $(cc)  writen.o server.o signal.o sig_chld.o -o $(target)
writen.o:writen.c
        $(cc) -c writen.c -o writen.o
server.o:server.c
        $(cc) -c server.c -o server.o
signal.o:
        $(cc) -c signal.c -o signal.o
sig_chld.o:
        $(cc) -c sig_chld.c -o sig_chld.o
clean:
        rm -rf *.o $(target)                            

 

转载于:https://www.cnblogs.com/soldierback/p/10695252.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
下面是一个Python语言的多进程TCP服务器程序示例,它能够实现每当有一个客户端连接时,向客户端程序回复这是第几个连接服务器的客户端的功能。 ```python import socket import os import signal def handle_request(conn, addr, client_count): print("New client connected:", addr) conn.send(f"Hello, you are the {client_count}th client connected to the server.".encode()) conn.close() def handle_sigchld(signum, frame): while True: try: pid, status = os.waitpid(-1, os.WNOHANG) except OSError: return if pid == 0: return def main(): server_addr = ('', 8888) backlog = 5 client_count = 0 # 创建套接字 server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # 绑定服务器地址 server_socket.bind(server_addr) # 监听客户端连接 server_socket.listen(backlog) print("Listening on", server_addr) # 处理进程退出信号 signal.signal(signal.SIGCHLD, handle_sigchld) while True: # 接受客户端连接请求 conn, addr = server_socket.accept() client_count += 1 # 创建子进程 pid = os.fork() if pid == 0: # 子进程 server_socket.close() # 子进程不需要监听,关闭监听套接字 handle_request(conn, addr, client_count) os._exit(0) else: conn.close() # 父进程不需要与客户端通信,关闭连接套接字 if __name__ == '__main__': main() ``` 程序中使用了fork()函数创建子进程处理客户端连接,父进程负责监听客户端连接请求,并在接收到连接请求时创建子进程。每个子进程都可以独立地与客户端通信,处理完请求后退出。同时,使用了signal模块处理进程退出信号,防止子进程变成僵尸进程

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值