多进程C linux服务器挂在输出到套接字上

时间:2019-02-05 15:46:12

标签: c linux server

我必须在c中编写一个多进程服务器和一个客户端,但是(我认为)问题是服务器挂起并且套接字上未输出任何数据,我也不明白为什么。

我已经运行wireshark来查看两者(客户端和服务器)彼此说了什么,而且我确实知道服务器正确地(通过使用printf()从客户端接收到了正确的数据。 / p>

服务器:

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

#define READ 0
#define WRITE 1
#define FILENAMESIZE 30

void sig_chld_handler(int signum){int status;
while(waitpid(-1,&status,WNOHANG)>0);
}

int main(int argc,char **argv){int pid,pid1,pid2,err,sd,on=-1;
struct sigaction sig_chld;
sig_chld.sa_handler=sig_chld_handler;
sig_chld.sa_flags=SA_RESTART;
sigemptyset(&sig_chld.sa_mask);

struct addrinfo hints,*res;
memset(&hints,0,sizeof(hints));
hints.ai_family=AF_UNSPEC;
hints.ai_socktype=SOCK_STREAM;
hints.ai_flags=AI_PASSIVE;

if(sigaction(SIGCHLD,&sig_chld,NULL)<0){
    perror("SIGACTION");
    exit(EXIT_FAILURE);
}
if((err=getaddrinfo(NULL,argv[1],&hints,&res))!=0){
    fprintf(stderr,"getaddrinfo: %s",gai_strerror(err));
    exit(EXIT_FAILURE);
}
if((sd=socket(res->ai_family,res->ai_socktype,res->ai_protocol))<0){
    perror("socket");
    exit(EXIT_FAILURE);
}
on=1;
if(setsockopt(sd,SOL_SOCKET,SO_REUSEADDR,&on,sizeof(on))<0){
    perror("setsockopt");
    exit(EXIT_FAILURE);
}
if(bind(sd,res->ai_addr,res->ai_addrlen)<0){
    perror("bind");
    exit(EXIT_FAILURE);
}
freeaddrinfo(res);
if(listen(sd,SOMAXCONN)<0){
    perror("listen");
    exit(EXIT_FAILURE);
}
while(1){int ns;
    if((ns=accept(sd,NULL,NULL))<0){
        if(errno==EINTR){
            continue;
        }
        perror("accept");
        exit(EXIT_FAILURE);
    }
    if((pid=fork())<0){
        perror("fork1");
        exit(EXIT_FAILURE);
    }
    if(pid==0){/*Main son*/
        const char *ack="ack\n";
        char topic[30],date[10],number[5],filename[FILENAMESIZE];
        int piped[2],piped2[2];
        close(sd);

        memset(topic,0,sizeof(topic));
        memset(date,0,sizeof(date));
        memset(date,0,sizeof(date));
    /*Client dialog*/
        if(read(ns,topic,sizeof(topic))<0){
            perror("read 1");
            exit(EXIT_FAILURE);
        }
        if(write(ns,ack,strlen(ack)+1)<0){
            perror("write 1");
            exit(EXIT_FAILURE);
        }
        if(read(ns,number,sizeof(number))<0){
            perror("read 1");
            exit(EXIT_FAILURE);
        }
        if(write(ns,ack,strlen(ack)+1)<0){
            perror("write 2");
            exit(EXIT_FAILURE);
        }
        if(read(ns,date,sizeof(date))<0){
            perror("read 1");
            exit(EXIT_FAILURE);
        }
        if(write(ns,ack,strlen(ack)+1)<0){
            perror("write 3");
            exit(EXIT_FAILURE);
        }
        if(pipe(piped)<0){
            perror("piped");
            exit(EXIT_FAILURE);
        }
        if((pid1=fork())<0){
            perror("fork 1");
            exit(EXIT_FAILURE);
        }
        else if(pid1==0){/*Nephew: grep*/
            char *dir="/home/user";
            sprintf(filename,"%s/%s.txt",dir,date);

            /*closing unuseful description*/
            close(ns);
            close(piped[READ]);
            /*stdout redirect*/
            close(1);
            dup(piped[WRITE]);
            close(piped[WRITE]);

            execlp("grep","grep",topic,filename,NULL);

            perror("grep");
            exit(EXIT_FAILURE);
        }
        if(pipe(piped2)<0){
            perror("piped2");
            exit(EXIT_FAILURE);
        }
        if((pid2=fork())<0){
            perror("fork 2");
            exit(EXIT_FAILURE);
        }
        else if(pid2==0){
            /*Closing unuseful descriptors*/
            close(ns);
            close(piped[WRITE]);
            close(piped2[READ]);

                            /*stdin redirect*/
            close(0);
            dup(piped[READ]);
            close(piped[READ]);

            /*stdout redirect*/
            close(1);
            dup(piped2[WRITE]);
            close(piped2[WRITE]);

            execlp("sort","sort","-r","-n",NULL);

            perror("sort");
            exit(EXIT_FAILURE);
        }
        /*Closing unused descriptors*/
        close(piped[WRITE]);
        close(piped[READ]);
        close(piped2[WRITE]);

        /*Redirect stdin*/
        close(0);
        dup(piped2[READ]);
        close(piped2[READ]);

        /*Redirect stdout to socket*/
        close(1);
        dup(ns);
        close(ns);

        execlp("head","head","-n",number,NULL);

        perror("head");
        exit(EXIT_FAILURE);
    }
    close(ns);
}



return 0;
 }

客户:

   #include <stdio.h>
   #include <sys/wait.h>
   #include <sys/types.h>
   #include <sys/socket.h>
   #include <netdb.h>
   #include <netinet/in.h>
   #include <stdlib.h>
   #include <string.h>
   #include <fcntl.h>
   #include <unistd.h>

   #define buf_size 2048


int main(int argc, char *argv[]){int sd,err,red;char buffer[buf_size],date[9],topic[21],number[5];
struct addrinfo hints,*res,*ptr;
memset(&hints,0,sizeof(hints));
hints.ai_family=AF_UNSPEC;
hints.ai_socktype=SOCK_STREAM;

if(argc<3){
    fprintf(stderr,"Wrong usage.");
    exit(EXIT_FAILURE);
}

if((err=getaddrinfo(argv[1],argv[2],&hints,&res))!=0){
    fprintf(stderr,"Error getaddrinfo: %s",gai_strerror(err));
    exit(EXIT_FAILURE);
}

while(1){char *ack="ack\n";
    for(ptr=res;ptr!=NULL;ptr=ptr->ai_next){
        if((sd=socket(ptr->ai_family,ptr->ai_socktype,ptr->ai_protocol))<0){
            fprintf(stderr,"Socket fail.\n");
            continue;
        }
        if(connect(sd,ptr->ai_addr,ptr->ai_addrlen)!=-1){
            printf("Connected.");
            break; /*Connected*/
        }
        close(sd);
    }
    if(ptr==NULL){
        fprintf(stderr,"No address found");
        exit(EXIT_FAILURE);
    }
    //freeaddrinfo(ptr);
    printf("\nInserirt topic:");
    scanf("%s",topic);
    if(strcmp("fine",topic)==0){
        printf("Terminazione...");
        break;
    }   
    printf("\nInsert date:");
    scanf("%s",date);
    if(strcmp("fine",date)==0){
        printf("Terminazione...");
        break;      
    }

    printf("\nInsert results number:");
    scanf("%s",number);
    if(strcmp("fine",number)==0){
        printf("Terminazione...");
        break;      
    }
    if(write(sd,topic,strlen(topic)+1)<0){
        perror("Write (1).");
        exit(EXIT_FAILURE);
    }
    if(read(sd,buffer,sizeof(buffer))<0){
        perror("Message (1) not received.");
        exit(EXIT_FAILURE);
    }
    if(strcmp(buffer,ack)!=0){
        fprintf(stderr,"Issue with ack.(1)");
        exit(EXIT_FAILURE);
    }
    if(write(sd,number,strlen(number)+1)<0){
        perror("Write (2)");
        exit(EXIT_FAILURE);
    }
    if(read(sd,buffer,sizeof(buffer))<0){
        perror("Message (2) not received.");
        exit(EXIT_FAILURE);
    }
    if(strcmp(buffer,ack)!=0){
        fprintf(stderr,"Issue with ack.(2)");
        exit(EXIT_FAILURE);
    }
    if(write(sd,date,strlen(date)+1)<0){
        perror("Write (3)");
        exit(EXIT_FAILURE);
    }
    if(read(sd,buffer,sizeof(buffer))<0){
        perror("Message (3) not received.");
        exit(EXIT_FAILURE);
    }
    if(strcmp(buffer,ack)!=0){
        fprintf(stderr,"Issue with ack.(3)");
        exit(EXIT_FAILURE);
    }

    fflush(stdout);
    while((red=read(sd,buffer,sizeof(buffer)))>0){
        printf("%d",red);
        if(write(1,buffer,red)<0){
            perror("write error stdout.");
            exit(EXIT_FAILURE);
        }
    }
    if(red<0){
        perror("Result read Error:");
        exit(EXIT_FAILURE);
    }
    close(sd);
}
freeaddrinfo(res);
freeaddrinfo(ptr);

return 0;
}

此服务器应打开一个文件(每天一个文件,位于dir-诸如YYYYMMDD.txt-之类的目录中)(使用客户端接收到的数据“ date”构建的绝对路径),grep按“ topic”,按第一个字段排序然后写出套接字“数字”行。 但是,服务器没有输出任何数据到客户端(wireshark),因此客户端无法创建套接字。我确实尝试过使用信号灯,但没有成功。老实说,我不知道现在该怎么办。

Edit1:添加printf()来查看在父进程,子进程和侄子进程(每个进程都有一个printf())中发生了什么,我没有得到任何输出。

0 个答案:

没有答案