/* * Program: Simple chat client multiplexing IO * * Author: Pedro Velho * * Date: 15/08/2005 * * This simple server makes a loop where it may * receive connections, each time a connection is * made a message is delivered to the other pocess * that are connected. * */ #include //printf #include #include //string cpp class #include #include #include #include #include #include //struct sockaddr_in, AFINET, SOCK_STREAM #include //socket, bind, accept #include //struct time_val #include // hton #include #include #include using namespace std; #define BUFFER_MAX_SIZE 1200 //semaforo para a regia critica da lista de sockets sem_t socket_list_sem; //lista de sockets conectados vector socket_list; //prototipos das funcoes void sendtoall(string message); void *handle_client(void * p); int main (int argc, char **argv){ //guarda o descritor do socket servidor int sockfd; //endereco no qual o servidor ficara amarrado recebendo conexoes struct sockaddr_in my_addr; //endereco do cliente, necessario para mostrar o endereco de quem se conectou struct sockaddr_in his_addr; int sock_size; //descritor do novo socket criado quando uma nova coneccao eh recebida int new_socket; //variavel para guardar a identificacao da thread criada pthread_t p; //inicializa o semaforo com valor 1, indicando regia critica sem_init(&socket_list_sem, 0 , 1); //cria o descritor do socket servidor e o coloca na variavel sockfd sockfd = socket(PF_INET, SOCK_STREAM, 0); //variavel que guarda o valor para ajustar a opcao abaixo int yes=1; //ajusta a opcao de resuar endereco para nao ficar pindurado caso ocorra //uma finalizacao anormal do processo, sem fechar o socket ao qual o //endereco estava amarrado if ( (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof (int))) < 0){ perror("setsockopt"); } //famila do endereco internet my_addr.sin_family = AF_INET; // host byte order //porta do endereco no qual estaremos recebendo conexoes my_addr.sin_port = htons(7888); // short, network byte order //qualquer endereco de rede no qual estivermos esperando my_addr.sin_addr.s_addr = INADDR_ANY; //zera a parte nao utilizada da struct sockaddr_in memset(&(my_addr.sin_zero), '\0', 8); // zero the rest of the struct printf("Servidor escutando na porta %d\n", 7888); //amarra o descritor sockfd ao endereco setado acima if(bind( sockfd, (struct sockaddr *) &my_addr, sizeof(struct sockaddr))){ perror("Bind"); exit(1); } //estabelece o numero maximo de conexoes simultaneas que podem ser tratadas //por esse servidor if(listen(sockfd, 2)){ perror("Listen"); exit(1); } //buffer para recebimento temporario de mensagens dos clientes char msg[BUFFER_MAX_SIZE]; //agora fica em um ciclo infinito recebendo conexoes while(true){ sock_size = sizeof(struct sockaddr_in); printf("Aguardando conexao...\n"); //bloqueia ate receber uma tentativa de conexao new_socket = accept(sockfd, (struct sockaddr *)&his_addr, (socklen_t*)&sock_size); //efetua tratamento de erro da chamada accept if(new_socket == -1){ perror("Erro ao receber o accept\n"); break; } printf("server recebeu a conexao do cliente: %s na socket %d\n", inet_ntoa(his_addr.sin_addr), new_socket); //ao receber uma conexao sem erro acrescenta o descritor da socket que trata essa conexao //na lista de sockets conectadas, repare que eh uma regia critica sem_wait(&socket_list_sem); socket_list.push_back(new_socket); sem_post(&socket_list_sem); //cria uma thread para receber mensagens do cliente que acabou de conectar pthread_create(&p, NULL, handle_client, (void *)&new_socket); } } /* * Funcao que trata uma conexao com um cliente. */ void *handle_client(void * p) { int new_socket; char buf[BUFFER_MAX_SIZE]; int size=0; string message; new_socket = *((int *) p); //fica em um ciclo recebendo mensagens e repassando-as aos outros clientes while(true){ //limpa o buffer temporario de recebimento memset(buf, 0, BUFFER_MAX_SIZE); printf("Eperando mensagem!\n"); //bloqueia esperando mensagem dessa socket if( (size = recv(new_socket, buf, BUFFER_MAX_SIZE, 0)) <= 0){ printf("Cliente %d desconectou!\n", new_socket); close(new_socket); fflush(NULL); break; } buf[size-1]=0; //manda para todos a mensagem recebida sendtoall(string(buf)); } } void sendtoall(const string message){ sem_wait(&socket_list_sem); printf("Enviando mensagem =\"%s\"\n", message.c_str()); for(int i=0; i