/* Canhão UDP Servidor Alunos: Luis Eduardo Mochenski Floriano GRR 20190354 Thiago Ruiz Aniceto GRR 20190355 Atualizado em: 21/02/2023 */ #include #include #include #include #include #include // Sistema DNS-revis #include #include #include #include #define TAMFILA 5 #define MAXHOSTNAME 30 #define TAM_MENSAGEM_LOG 9000 #define TIMEOUT 1000000 // 3000000 == UM SEGUNDO int ultima_posicao_recebida = 0; void log_mensagem(char *mensagem) { // Registra o tempo usando a lib "time.h" struct timespec spec; clock_gettime(CLOCK_REALTIME, &spec); // Adiciona o tempo atual com o formato "Y-M-D H:M:S:ms" char datetime_str[24]; // Salva sem MS strftime(datetime_str, sizeof(datetime_str), "%H:%M:%S", localtime(&spec.tv_sec)); // Adiciona MS ao final da string sprintf(datetime_str + strlen(datetime_str), ".%03ld", spec.tv_nsec / 1000000); // Registra o log printf("[%s]: %s\n", datetime_str, mensagem); } void registra_dados_recebidos(char *buf, int *recebidos, int *tam_recebidos) { char *ptr; int count = *tam_recebidos; recebidos[*tam_recebidos] = atoi(buf); ++(*tam_recebidos); ultima_posicao_recebida = *tam_recebidos == 1 ? 1 : *tam_recebidos - 2; } int verifica_fora_de_ordem_e_loga(int *recebidos, int tam_recebidos) { int count = 0; char mensagem_de_log[TAM_MENSAGEM_LOG]; for (int i = ultima_posicao_recebida; i < tam_recebidos - 1; i++) { if (recebidos[i] > recebidos[i + 1]) { count++; snprintf(mensagem_de_log, TAM_MENSAGEM_LOG, "O item %d está fora de ordem!", recebidos[i]); log_mensagem(mensagem_de_log); } } return count; } int verifica_dados_faltantes_e_loga(int *recebidos, int tam_recebidos) { int count = 0; char mensagem_de_log[TAM_MENSAGEM_LOG]; for (int i = ultima_posicao_recebida; i < tam_recebidos - 1; i++) { if (recebidos[i] != recebidos[i + 1] - 1) { count += abs(recebidos[i] - recebidos[i + 1]) - 1; snprintf(mensagem_de_log, TAM_MENSAGEM_LOG, "Há %d item(ns) faltantes entre %d e %d", abs(recebidos[i] - recebidos[i + 1]) - 1, recebidos[i], recebidos[i + 1]); log_mensagem(mensagem_de_log); } } return count; } int main(int argc, char *argv[]) { int sock_escuta, sock_atende; int i; char buf[BUFSIZ + 1]; struct sockaddr_in sa, isa; struct hostent *hp; char localhost[MAXHOSTNAME]; if (argc != 2) { puts("Uso correto: servidor "); exit(1); } gethostname(localhost, MAXHOSTNAME); if ((hp = gethostbyname(localhost)) == NULL) { puts("Não foi possível resolver o próprio endereço IP."); 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; if ((sock_escuta = socket(hp->h_addrtype, SOCK_DGRAM, 0)) < 0) { puts("Não conseguiu abrir o socket."); exit(1); } if (bind(sock_escuta, (struct sockaddr *)&sa, sizeof(sa)) < 0) { puts("Não conseguiu abrir o bind."); exit(1); } log_mensagem("Inicia recebimento de dados canhão UDP"); int total = 0; char mensagem_de_log[TAM_MENSAGEM_LOG]; int *recebidos = NULL; int tam_recebidos = 0; int quantidade_fora_de_ordem = 0; int quantidade_faltantes = 0; while (1) { i = sizeof(sa); while (1) { // read(sock_atende, buf, BUFSIZ); recvfrom(sock_escuta, buf, BUFSIZ, 0, (struct sockaddr *)&isa, &i); if (strlen(buf) > 0) { snprintf(mensagem_de_log, TAM_MENSAGEM_LOG, "Recebendo[tam: %ld]: %s", strlen(buf), buf); log_mensagem(mensagem_de_log); // Caso não tenhamos um total definido, verifica se a mensagem possui o padrão "total=n" if (total == 0) { char bufcpy[BUFSIZ + 1]; memcpy(bufcpy, buf, BUFSIZ); char *ptr = strstr(bufcpy, "total="); if (ptr != NULL) { total = atoi(ptr + strlen("total=")); snprintf(mensagem_de_log, TAM_MENSAGEM_LOG, "Registra quantos dados o Servidor deve esperar receber total = %d", total); log_mensagem(mensagem_de_log); recebidos = (int *)malloc(total * sizeof(int)); } else { puts("Não foi possível definir tamanho do Canhão UDP. A mensagem inicial deve conter o formato \"total=n\"!"); exit(1); } } else { if (strcmp(buf, "fim") == 0) { snprintf(mensagem_de_log, TAM_MENSAGEM_LOG, "Recebeu %s", buf); log_mensagem(mensagem_de_log); break; } registra_dados_recebidos(buf, recebidos, &tam_recebidos); quantidade_fora_de_ordem += verifica_fora_de_ordem_e_loga(recebidos, tam_recebidos); quantidade_faltantes += verifica_dados_faltantes_e_loga(recebidos, tam_recebidos); } } memset(buf, 0, strlen(buf)); } break; } snprintf(mensagem_de_log, TAM_MENSAGEM_LOG, "Fim canhão UDP, %d pacotes recebidos", tam_recebidos); log_mensagem(mensagem_de_log); // Loga métricas do array de dados recebidos log_mensagem("Métricas do resultado final canhão UDP"); snprintf(mensagem_de_log, TAM_MENSAGEM_LOG, "Total de dados recebidos %d / esperava-se %d Taxa: %f%% ", tam_recebidos, total, 100 * ((float)tam_recebidos / (float)total)); log_mensagem(mensagem_de_log); snprintf(mensagem_de_log, TAM_MENSAGEM_LOG, "Total de dados fora de ordem %d", quantidade_fora_de_ordem); log_mensagem(mensagem_de_log); snprintf(mensagem_de_log, TAM_MENSAGEM_LOG, "Total de dados faltantes %d", total - tam_recebidos); log_mensagem(mensagem_de_log); exit(0); }