我必须在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())中发生了什么,我没有得到任何输出。