/* perf_client_udp.c - STRICT C89/C90 UDP performance tester for the metric protocol */ #include #include #include #include #include #include #include #include #include #include #define PORT 9999 #define BUF_SIZE 1024 #define TEST_DURATION 30 /* seconds */ #define MSG_PING 0x01 #define MSG_PONG 0x02 #define MSG_METRIC_REQ 0x03 #define MSG_METRIC_RESP 0x04 #define MSG_SUBSCRIBE 0x05 #define MSG_PUSH 0x06 #define MSG_UNSUB 0x07 #define MSG_ERROR 0xFF #define HEADER_SIZE 3 static void send_to(int sock, struct sockaddr_in *to, unsigned char type, const void *payload, unsigned short len) { unsigned char header[HEADER_SIZE]; header[0] = type; header[1] = (len >> 8) & 0xFF; header[2] = len & 0xFF; sendto(sock, header, HEADER_SIZE, 0, (struct sockaddr *)to, sizeof(*to)); if (len > 0) sendto(sock, payload, len, 0, (struct sockaddr *)to, sizeof(*to)); } static int recv_from_exact(int sock, void *buf, int n) { int total = 0; while (total < n) { int r = recv(sock, (char *)buf + total, n - total, 0); if (r <= 0) return -1; total += r; } return total; } int main(int argc, char *argv[]) { int sock, maxfd, flood_mode = 0, duration = TEST_DURATION; struct sockaddr_in server_addr; unsigned char header[HEADER_SIZE]; unsigned char payload[BUF_SIZE]; double val; unsigned char type; unsigned short len; fd_set readfds; time_t start, now; unsigned long count = 0; const char *metric = "cpu"; unsigned int interval_ms = 10; /* 10 ms pushes in subscribe mode */ if (argc > 1 && strcmp(argv[1], "--flood") == 0) flood_mode = 1; sock = socket(AF_INET, SOCK_DGRAM, 0); if (sock < 0) { perror("socket"); exit(1); } server_addr.sin_family = AF_INET; server_addr.sin_port = htons(PORT); inet_pton(AF_INET, "127.0.0.1", &server_addr.sin_addr); printf("=== UDP Metric Performance Test (C89) ===\n"); printf("Server: 127.0.0.1:%d\n", PORT); if (flood_mode) { printf("Mode: FLOOD (rapid get %s)\n", metric); } else { printf("Mode: SUBSCRIBE '%s' every %u ms\n", metric, interval_ms); } printf("Test duration: %d seconds\n\n", duration); /* Subscribe or start flooding */ if (flood_mode) { /* nothing extra needed */ } else { unsigned char p[BUF_SIZE]; unsigned char name_len = strlen(metric); p[0] = name_len; memcpy(p + 1, metric, name_len); p[1 + name_len] = (interval_ms >> 24) & 0xFF; p[1 + name_len + 1] = (interval_ms >> 16) & 0xFF; p[1 + name_len + 2] = (interval_ms >> 8) & 0xFF; p[1 + name_len + 3] = interval_ms & 0xFF; send_to(sock, &server_addr, MSG_SUBSCRIBE, p, 1 + name_len + 4); printf("Subscribed... counting PUSHes\n"); } start = time(NULL); maxfd = sock + 1; while (1) { FD_ZERO(&readfds); FD_SET(sock, &readfds); if (select(maxfd, &readfds, NULL, NULL, NULL) < 0) { if (errno == EINTR) continue; perror("select"); break; } if (FD_ISSET(sock, &readfds)) { if (recv_from_exact(sock, header, HEADER_SIZE) != HEADER_SIZE) break; type = header[0]; len = (header[1] << 8) | header[2]; if (len > 0) { if (recv_from_exact(sock, payload, len) != len) break; } if (type == MSG_PUSH) { unsigned char name_len = payload[0]; payload[1 + name_len] = '\0'; memcpy(&val, payload + 1 + name_len, sizeof(double)); count++; } else if (type == MSG_METRIC_RESP && flood_mode) { count++; } else if (type == MSG_ERROR) { printf(" [ERROR] %.*s\n", len, payload); } } now = time(NULL); if (now - start >= duration) break; } if (!flood_mode) { send_to(sock, &server_addr, MSG_UNSUB, NULL, 0); } printf("\n=== Results ===\n"); printf("Duration: %lu seconds\n", (unsigned long)(now - start)); printf("Messages received: %lu\n", count); printf("Throughput: %.1f messages/second\n", (double)count / (now - start)); if (flood_mode) { printf("(This is the rate of successful round-trips)\n"); } else { printf("(UDP PUSH rate — best-effort)\n"); } close(sock); return 0; }