/* Código do servidor do trabalho de Redes 2 "Artilharia UDP" Implementado por Leandro Rodrigues e Matheus Rotondano */ #include #include #include #include #include #include #include #include #include #define TAMFILA 5 #define CONST16 16 #define CONST32 32 #define CONST64 64 #define CONST128 128 /* Struct para utilizar o time.h */ typedef struct tm tm; /* - Tipo client guarda os dados das transmissões por cliente. - Isso inclui a mensagem que chegou por último e a atualmente recebida, para fins de comparação se foi perdido algo ou invertido. */ typedef struct c { char id[CONST32]; //Identificação do cliente ao ser alocado (nome do cliente que é passado) int msgsRecebidas; //Mensagens recebidas desse cliente int msgsPerdidas; //Mensagens perdidas desse cliente int msgsInvertidas; //Mensagens que chegaram invertidas desse cliente int msgsDuplicadas; //Mensagens que chegaram duplicadas para esse cliente int msgAnt; //Mensagem que chegou anteriormente int msgAtual; //Mensagem que acabou de ser recebida } client; /* Variaveis globais que servem para, respectivamente: - Controlar o loop que deixa o servidor ativo - Contar o total de mensagens recebidas - Contar o total de mensagens pertidas - Contar o total de mensagens invertidas - Contar o total de mensagens duplicadas */ static int executa = 1; static int totalRecebidas = 0; static int totalPerdidas = 0; static int totalInvertidas = 0; static int totalDuplicadas = 0; /* Arquivo do log do servidor */ FILE *logFile; /* Headers das funções criadas */ void intHandler(int dummy); void finalizarServidor (FILE *logFile); void inicializaVector (client clientVector[]); int clientePertenceVector(char clientName[], client clientVector[]); void insereCliente(char clientName[], client clientVector[]); int posicaoCliente(char clientName[], client clientVector[]); main ( int argc, char *argv[] ) { int s, t; unsigned int i, j, k; client clientVector[CONST128]; char buf [BUFSIZ + 1]; struct sockaddr_in sa, isa; /* sa: servidor, isa: cliente */ struct hostent *hp; char localhost [CONST32]; char clientName[CONST32]; char mensagemChar[CONST16]; int mensagemInt; int posCliente; /* Mensagem de erro caso o usuario esteja executando o programa de modo errado */ if (argc != 2) { puts("Uso correto: servidor "); exit(1); } /* Pega o nome do servidor e guarda em localhost */ gethostname (localhost, CONST32); /* Inicializa o vetor de clientes, setando cada componente de cada estrutura em 0 */ inicializaVector(clientVector); /* Variaveis para pegar o horario do computador para colocar no log */ time_t tempo_atual; tm *tempo; time(&tempo_atual); tempo = localtime(&tempo_atual); /* É criado um diretório chamado logServer onde todos os logs de execução do servidor são salvos. Sempre que o servidor é iniciado, um arquivo chamado "logServer .txt" é criado dentro desse diretório. */ char logPath[CONST64]; mkdir("logServer", 0777); sprintf(logPath, "logServer/logServer %2.2d-%2.2d-%2.2d %2.2d:%2.2d:%2.2d.txt", tempo->tm_mday, tempo->tm_mon, tempo->tm_year+1900, tempo->tm_hour, tempo->tm_min, tempo->tm_sec); logFile = fopen(logPath, "wr+"); fprintf(logFile, "Log criado em %2.2d/%2.2d/%2.2d %2.2dh:%2.2dm:%2.2ds\n", tempo->tm_mday, tempo->tm_mon, tempo->tm_year+1900, tempo->tm_hour, tempo->tm_min, tempo->tm_sec); fprintf(logFile, "Comecei a executar o servidor %s\n\n", localhost); /* O programa é abortado caso o servidor não consiga seu proprio IP */ if ((hp = gethostbyname(localhost)) == NULL) { fprintf(logFile, "Nao consegui meu proprio IP\nEncerrando servidor...\n"); fprintf(logFile, "\n\nLog finalizado em %2.2d/%2.2d/%2.2d %2.2dh:%2.2dm:%2.2ds\n", tempo->tm_mday, tempo->tm_mon, tempo->tm_year+1900, tempo->tm_hour, tempo->tm_min, tempo->tm_sec); fclose(logFile); exit(1); } sa.sin_port = htons(atoi(argv[1])); bcopy ((char *) hp->h_addr, (char *) &sa.sin_addr, hp->h_length); sa.sin_family = hp->h_addrtype; /* O programa é abortado caso o servidor não consiga abrir o socket */ if ((s = socket(hp->h_addrtype,SOCK_DGRAM,0)) < 0) { fprintf(logFile, "Nao consegui abrir o socket\nEncerrando servidor...\n"); fprintf(logFile, "\n\nLog finalizado em %2.2d/%2.2d/%2.2d %2.2dh:%2.2dm:%2.2ds\n", tempo->tm_mday, tempo->tm_mon, tempo->tm_year+1900, tempo->tm_hour, tempo->tm_min, tempo->tm_sec); fclose(logFile); exit(1); } /* O programa é abortado caso o servidor não consiga fazer o bind */ if (bind(s, (struct sockaddr *) &sa,sizeof(sa)) < 0) { fprintf(logFile, "Nao consegui fazer o bind\nEncerrando servidor...\n"); fprintf(logFile, "\n\nLog finalizado em %2.2d/%2.2d/%2.2d %2.2dh:%2.2dm:%2.2ds\n", tempo->tm_mday, tempo->tm_mon, tempo->tm_year+1900, tempo->tm_hour, tempo->tm_min, tempo->tm_sec); fclose(logFile); exit(1); } /* signal() serve para poder parar o servidor com o comando ctrl+C Quando ctrl+C é encontrado, executa (que inicialmente vale 1) passa a valer 0 e o programa sai do loop. */ signal(SIGINT, intHandler); while (executa) { i = sizeof(isa); recvfrom(s, buf, BUFSIZ, 0, (struct sockaddr *) &isa, &i); /* As mensagens são da forma " " Essa parte separa o nome do cliente do resto da mensagem. */ for (j = 0; buf[j] != ' '; ++j) clientName[j] = buf[j]; for (k = 0, j = j + 1; buf[j] != '\0'; ++k, ++j) mensagemChar[k] = buf[j]; mensagemInt = atoi(mensagemChar); /* Checa se o cliente que acabou de entrar no servidor está no vetor de clientes do servidor. Caso ele não esteja, ele é adicionado ao vetor */ if (!clientePertenceVector(clientName, clientVector)) { insereCliente(clientName, clientVector); fprintf(logFile, "O cliente %s acabou de entrar no servidor.\n", clientName); } /* Posição do cliente que acabou de entrar no servidor na lista de clientes do servidor. */ posCliente = posicaoCliente(clientName, clientVector); /* Atualiza os campos da estrutura do cliente. */ clientVector[posCliente].msgAnt = clientVector[posCliente].msgAtual; clientVector[posCliente].msgAtual = mensagemInt; clientVector[posCliente].msgsRecebidas = clientVector[posCliente].msgsRecebidas + 1; ++totalRecebidas; /* Todas as condições abaixo são feitas se baseando no fato de que as mensagens enviadas são números ordenados. */ /* Se a diferença da mensagem atual da mensagem anterior for 0, significa que a mensagem foi duplicada. */ if ((clientVector[posCliente].msgAtual - clientVector[posCliente].msgAnt) == 0) { clientVector[posCliente].msgsDuplicadas = clientVector[posCliente].msgsDuplicadas + 1; ++totalDuplicadas; /* Se a diferença da mensagem atual da mensagem anterior for menor que 0, significa que uma mensagem foi invertida. */ } else if ((clientVector[posCliente].msgAtual - clientVector[posCliente].msgAnt) < 0) { if (clientVector[posCliente].msgsPerdidas > 0) clientVector[posCliente].msgsPerdidas = clientVector[posCliente].msgsPerdidas - 1; if (totalPerdidas > 0) --totalPerdidas; clientVector[posCliente].msgsInvertidas = clientVector[posCliente].msgsInvertidas + 1; ++totalInvertidas; /* Se a diferença da mensagem atual da mensagem anterior for maior que 1, o valor dessa diferença é o número de mensagens que foram perdidas. */ } else if ((clientVector[posCliente].msgAtual - clientVector[posCliente].msgAnt) > 1) { clientVector[posCliente].msgsPerdidas = clientVector[posCliente].msgAtual - clientVector[posCliente].msgAnt - 1; totalPerdidas = totalPerdidas + (clientVector[posCliente].msgAtual - clientVector[posCliente].msgAnt - 1); } /* Se a diferença da mensagem atual da mensagem anterior for 1, significa que está tudo certo. */ /* Limpa os buffers */ memset(clientName, 0, 32); memset(mensagemChar, 0, 16); } } /* Inicializa o vetor de clientes, setando cada componente de cada estrutura em 0 */ void inicializaVector (client clientVector[]) { int i; for (i = 0; i < 128; ++i) { clientVector[i].id[0] = '\0'; clientVector[i].msgsRecebidas = 0; clientVector[i].msgsPerdidas = 0; clientVector[i].msgsInvertidas = 0; clientVector[i].msgsDuplicadas = 0; clientVector[i].msgAnt = 0; clientVector[i].msgAtual = 0; } } /* Retorna 1 se um cliente já pertence ao vetor de clientes e 0 no caso contrario. */ int clientePertenceVector (char clientName[], client clientVector[]) { int i; for (i = 0; clientVector[i].id; ++i) { if (clientVector[i].id[0] == '\0') return 0; if (strcmp(clientName, clientVector[i].id) == 0) { return 1; } } return 0; } /* Insere um cliente no vetor de clientes. */ void insereCliente (char clientName[], client clientVector[]) { int i; for (i = 0; clientVector[i].id[0] != '\0'; ++i); strcpy(clientVector[i].id, clientName); clientVector[i].msgsPerdidas = 0; clientVector[i].msgsInvertidas = 0; clientVector[i].msgsDuplicadas = 0; } /* Retorna a posição de um cliente no vetor de clientes. */ int posicaoCliente (char clientName[], client clientVector[]) { int i; for (i = 0; (strcmp(clientName, clientVector[i].id) != 0); ++i); return i; } /* Função que encerra o programa quando ctrl+C é encontrado. */ void intHandler(int dummy) { executa = 0; printf("\nCtrl + C, encerrando execucao do servidor.\n"); fprintf(logFile, "\nCtrl + C, encerrando execucao do servidor.\n"); finalizarServidor(logFile); exit(1); } /* Função que finaliza o servidor. */ void finalizarServidor (FILE *logFile) { time_t tempo_atual; tm *tempo; time(&tempo_atual); tempo = localtime(&tempo_atual); fprintf(logFile, "\nNumero de mensagens recebidas: %d", totalRecebidas); fprintf(logFile, "\nNumero de mensagens perdidas: %d", totalPerdidas); fprintf(logFile, "\nNumero de mensagens invertidas: %d", totalInvertidas); fprintf(logFile, "\nNumero de mensagens duplicadas: %d", totalDuplicadas); fprintf(logFile, "\n\nLog finalizado em %2.2d/%2.2d/%2.2d %2.2dh:%2.2dm:%2.2ds\n", tempo->tm_mday, tempo->tm_mon, tempo->tm_year+1900, tempo->tm_hour, tempo->tm_min, tempo->tm_sec); fclose(logFile); exit(1); }