#include #include #include #include #include #include #include #include #include #include #include #include "readLine.h" #ifndef BOOL #define BOOL int #define TRUE 0 #define FALSE 1 #endif #define PORT 7777 #define BACKLOG 10 int done[2]; int comunicacao(int socket){ char tmp[1]; char *buff = NULL; unsigned int size = 0; unsigned int i = 0; while(recv(socket,&tmp,1,(int)NULL) != 0){ size++; if((buff=(char*)realloc(buff,sizeof(char)*size))==NULL){ perror("realloc"); close(socket); write(done[1],"0",1); /* Major failure, stop the server */ exit(EXIT_FAILURE); } buff[size]='\0'; buff[i++]=tmp[0]; if(tmp[0]=='\n') break; } if(send(socket,buff,size,(int)NULL) < 0){ perror("send"); close(socket); free(buff); exit(EXIT_FAILURE); /* Apesar de ser um erro e inutilizar o servidor na maioria das vezes...eh apenas na maioria das vezes */ } if(strncmp(buff,"STOP SERVER\n",strlen("STOP SERVER\n"))==0){ if(send(socket,"STOPING\n",strlen("STOPING\n"),MSG_DONTWAIT) < 0){ perror("send"); } write(done[1],"0",1); } free(buff); close(socket); return 0; } void sigchld_handler(int s){ int childStatus; while(waitpid(-1,&childStatus,WNOHANG) > 0); if(WIFEXITED(childStatus)){ if(WEXITSTATUS(childStatus)!=0) perror("child"); } } int main(int argc, char *argv[]){ struct sockaddr_in server, client; int serverSock, clientSock; socklen_t clientSize = 0; pid_t clientPid; struct sigaction sa; BOOL stop = FALSE; char tmp; tmp='1'; memset(&server,'\0',sizeof(struct sockaddr_in)); memset(&client,'\0',sizeof(struct sockaddr_in)); if(pipe(done) < 0){ perror("pipe"); exit(EXIT_FAILURE); } if(fcntl(done[0],F_SETFL,O_NONBLOCK) < 0) perror("fcntl"); if(fcntl(done[1],F_SETFL,O_NONBLOCK) < 0) perror("fcntl"); if((serverSock = socket(AF_INET,SOCK_STREAM,0))==0){ perror("socket"); exit(EXIT_FAILURE); } if(fcntl(serverSock,F_SETFL,O_NONBLOCK) < 0) perror("fcntl"); server.sin_family = AF_INET; server.sin_port = htons(PORT); server.sin_addr.s_addr = INADDR_ANY; if(bind(serverSock,(struct sockaddr *)&server,sizeof(struct sockaddr)) < 0){ perror("bind"); exit(EXIT_FAILURE); } if(listen(serverSock,BACKLOG) < 0){ perror("bind"); exit(EXIT_FAILURE); } clientSize = sizeof(client); sa.sa_handler = sigchld_handler; sigemptyset(&sa.sa_mask); sa.sa_flags = SA_RESTART; if(sigaction(SIGCHLD,&sa,NULL) < 0){ perror("sigaction"); exit(EXIT_FAILURE); } while(stop==FALSE){ read(done[0],&tmp,1); if(tmp=='0') stop=TRUE; tmp='1'; if((clientSock = accept(serverSock,(struct sockaddr*)&client,&clientSize)) < 0){ if(errno!=EAGAIN || errno!=EWOULDBLOCK) perror("accept"); } if(clientSock > 0){ clientPid = fork(); if((int)clientPid < 0 ){ perror("fork"); } if((int)clientPid == 0){ /* Se este for o cliente */ close(serverSock); comunicacao(clientSock); exit(0); /* Saimos do cliente */ }else{ close(clientSock); /* O servidor nao precisa disso */ read(done[0],&tmp,1); if(tmp=='0') stop=TRUE; tmp='1'; } } } close(serverSock); exit(EXIT_SUCCESS); }