// Written by retoor@molodetz.nl // This source code performs a load test by simulating multiple IRC clients that connect to an IRC server, join a channel, and send a series of messages. It measures the total messages sent, bytes sent, and received. // Uses the following non-standard C libraries: pthread, sys/socket, netinet/in.h, arpa/inet.h // MIT License #include #include #include #include #include #include #include #include #include #define SERVER "127.0.0.1" #define PORT 6667 #define CHANNEL "#loadtest" #define NUM_CLIENTS 300 #define MESSAGES_PER_CLIENT 100 #define MESSAGE_INTERVAL 100000 int total_messages = MESSAGES_PER_CLIENT * NUM_CLIENTS; long long total_bytes_sent = 0; long long total_bytes_received = 0; pthread_mutex_t bytes_mutex = PTHREAD_MUTEX_INITIALIZER; void random_nick(char *nick, size_t len) { const char charset[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; strcpy(nick, "LT"); for (size_t i = 2; i < len - 1; ++i) { int key = rand() % (int)(sizeof(charset) - 1); nick[i] = charset[key]; } nick[len-1] = '\0'; } void *irc_client(void *arg) { int client_id = *(int *)arg; char nick[11]; random_nick(nick, sizeof(nick)); char user[64]; snprintf(user, sizeof(user), "%s 0 * :Load Tester", nick); int sockfd = socket(AF_INET, SOCK_STREAM, 0); if (sockfd < 0) { perror("socket"); pthread_exit(NULL); } struct sockaddr_in serv_addr; memset(&serv_addr, 0, sizeof(serv_addr)); serv_addr.sin_family = AF_INET; serv_addr.sin_port = htons(PORT); inet_pton(AF_INET, SERVER, &serv_addr.sin_addr); if (connect(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) { printf("[%s] Error: connect failed\n", nick); close(sockfd); pthread_exit(NULL); } char buf[512]; int sent; snprintf(buf, sizeof(buf), "NICK %s\r\n", nick); sent = send(sockfd, buf, strlen(buf), 0); pthread_mutex_lock(&bytes_mutex); if (sent > 0) total_bytes_sent += sent; pthread_mutex_unlock(&bytes_mutex); snprintf(buf, sizeof(buf), "USER %s\r\n", user); sent = send(sockfd, buf, strlen(buf), 0); pthread_mutex_lock(&bytes_mutex); if (sent > 0) total_bytes_sent += sent; pthread_mutex_unlock(&bytes_mutex); usleep(1000000); snprintf(buf, sizeof(buf), "JOIN %s\r\n", CHANNEL); sent = send(sockfd, buf, strlen(buf), 0); pthread_mutex_lock(&bytes_mutex); if (sent > 0) total_bytes_sent += sent; pthread_mutex_unlock(&bytes_mutex); usleep(1000000); for (int i = 0; i < MESSAGES_PER_CLIENT; ++i) { char buf[1024]; char msg[250]; memset(msg, 'a', sizeof(msg)); msg[sizeof(msg)-1] = '\0'; snprintf(buf, sizeof(buf), "PRIVMSG %s :%s from %s #%d\r\n", CHANNEL, msg, nick, i); sent = send(sockfd, buf, strlen(buf), 0); pthread_mutex_lock(&bytes_mutex); if (sent > 0) total_bytes_sent += sent; pthread_mutex_unlock(&bytes_mutex); int n = recv(sockfd, buf, sizeof(buf)-1, MSG_DONTWAIT); pthread_mutex_lock(&bytes_mutex); if (n > 0) total_bytes_received += n; pthread_mutex_unlock(&bytes_mutex); usleep(MESSAGE_INTERVAL); } sent = send(sockfd, "QUIT\r\n", 6, 0); pthread_mutex_lock(&bytes_mutex); if (sent > 0) total_bytes_sent += sent; pthread_mutex_unlock(&bytes_mutex); close(sockfd); pthread_exit(NULL); } int main() { srand(time(NULL)); double start_time = (double)clock() / CLOCKS_PER_SEC; pthread_t threads[NUM_CLIENTS]; int ids[NUM_CLIENTS]; for (int i = 0; i < NUM_CLIENTS; ++i) { ids[i] = i; pthread_create(&threads[i], NULL, irc_client, &ids[i]); usleep(50000); } for (int i = 0; i < NUM_CLIENTS; ++i) { pthread_join(threads[i], NULL); } double end_time = (double)clock() / CLOCKS_PER_SEC; double total_time = end_time - start_time; printf("Total time: %.2f seconds\n", total_time); printf("Total messages: %d\n", total_messages); printf("Messages per second: %.2f\n", total_messages / total_time); printf("Total bytes sent: %lld (%.2f MB)\n", total_bytes_sent, total_bytes_sent / (1024.0 * 1024.0)); printf("Total bytes received: %lld (%.2f MB)\n", total_bytes_received, total_bytes_received / (1024.0 * 1024.0)); printf("Send rate: %.2f MB/s\n", (total_bytes_sent / (1024.0 * 1024.0)) / total_time); printf("Receive rate: %.2f MB/s\n", (total_bytes_received / (1024.0 * 1024.0)) / total_time); printf("Load test complete.\n"); return 0; }