socket网络编程避免僵尸进程

来源:互联网 发布:成都淘宝美工培训班 编辑:程序博客网 时间:2024/06/05 17:25
//服务器程序//(1)当fork字进程时,必须捕获SIGCHLD信号//(2)当捕获信号时,必须处理被中断的系统调用(accept)//(3)SIGCHLD的信号处理函数必须被正确的书写,应使用waitpid函数,以免留下僵尸进程#include<stdio.h>#include<stdlib.h>#include<strings.h>#include<string.h>#include<netinet/in.h>#include<sys/socket.h>#include<signal.h>#include<unistd.h>#include<sys/types.h>#include<sys/stat.h>#include<errno.h>void sig_chld(int signo)//信号处理函数必须要有一个int 型的参数,并且返回值为void{    pid_t pid;    int stat;    while((pid = waitpid(-1, &stat, WNOHANG)) > 0)    {        printf("child %d terminated\n", pid);    }    return;}void str_echo(int sockfd){    char buffer[100];    int n;    memset(buffer, 0, 100);    while((n = read(sockfd, buffer, 100)) > 0)    {        buffer[n+1]='\0';        printf("%s\n", buffer);        write(sockfd, buffer, strlen(buffer));        memset(buffer, 0, 100);    }}int main(){    int listenfd, connfd;//监听套接字、已连接的套接字    struct sockaddr_in server_sockaddr, client_sockaddr;//IPv4套接字地址结构    socklen_t clilen;    pid_t pid;    if((listenfd = socket(AF_INET, SOCK_STREAM, 0)) == -1)    {        fprintf(stderr, "Socket failed\n");        exit(EXIT_FAILURE);    }    bzero(&server_sockaddr, sizeof(server_sockaddr));//清零    server_sockaddr.sin_family = AF_INET;    server_sockaddr.sin_port = htons(9877);//以网络字节序存储本地端口号    server_sockaddr.sin_addr.s_addr = htonl(INADDR_ANY);//通配地址      if(bind(listenfd, (struct sockaddr*)&server_sockaddr, sizeof(server_sockaddr)) == -1)//绑定本地地址和端口号    {        fprintf(stderr, "Bind failed\n");        exit(EXIT_FAILURE);    }    if(listen(listenfd, 5) == -1)    {        fprintf(stderr, "Listen failed\n");        exit(EXIT_FAILURE);    }    signal(SIGCHLD, sig_chld);//信号接收函数    while(1)    {        clilen = sizeof(client_sockaddr);        if((connfd = accept(listenfd, (struct sockaddr*)&client_sockaddr, &clilen)) < 0)        {            if(errno == EINTR)                continue;            else            {                fprintf(stderr, "Accept failed\n");                exit(EXIT_FAILURE);            }        }        //创建子进程处理客户端的请求        if((pid = fork()) == 0)//子进程中去处理客户端的服务        {            close(listenfd);            str_echo(connfd);            close(connfd);            exit(0);        }        close(connfd);    }}
//一个客户端连接多个服务器#include<stdio.h>#include<stdlib.h>#include<strings.h>#include<string.h>#include<netinet/in.h>#include<sys/socket.h>#include<arpa/inet.h>void str_cli(int sockfd){    char send_buffer[100], receive_buffer[100];    int n;    memset(send_buffer, 0, 100);    memset(receive_buffer, 0, 100);    while(fgets(send_buffer, 100, stdin) != NULL)    {        write(sockfd, send_buffer, strlen(send_buffer));//向网络中发数据        read(sockfd, receive_buffer, 100);        printf("%s\n", receive_buffer);        memset(send_buffer, 0, 100);        memset(receive_buffer, 0, 100);    }}int main(int argc, char **argv){    int sockfd[5], i;//套接字描述符    struct sockaddr_in server_sockaddr;//需要连接服务器的地址    if(argc != 2)    {        fprintf(stderr, "Input error\n");        exit(EXIT_FAILURE);    }    for(i=0; i<5; i++)    {        if((sockfd[i] = socket(AF_INET, SOCK_STREAM, 0)) == -1)        {            fprintf(stderr, "Socket failed\n");            exit(EXIT_FAILURE);        }        bzero(&server_sockaddr, sizeof(server_sockaddr));//清零        server_sockaddr.sin_family = AF_INET;        server_sockaddr.sin_port = htons(9877);//以网络字节序存储端口号        inet_pton(AF_INET, argv[1], &server_sockaddr.sin_addr);//将字符串转化为以网路字节序存储的地址        if(connect(sockfd[i], (struct sockaddr*)&server_sockaddr, sizeof(server_sockaddr)) == -1)//连接        {            fprintf(stderr, "Connec failed\n");        }    }    str_cli(sockfd[0]);//从套接字中读写数据    exit(0);}
原创粉丝点击