+ // malloc, since there might not be enough room on the stack
+ events = (struct epoll_event *)malloc(sizeof(struct epoll_event) * num_sockets_per_sender);
+ if (events == NULL) {
+ perror("malloc");
+ exit(1);
+ }
+
+ // fill the buffer with random junk
+ for (i = 0; i < 65536; ++i)
+ buf[i] = rand() & 0xff;
+
+ // allocate all the senders
+ for (i = 0; i < num_sockets_per_sender; ++i)
+ generate_new_sender(ep_fd);
+
+ for ( ;; ) {
+ int ret = epoll_wait(ep_fd, events, num_sockets_per_sender, -1);
+ for (i = 0; i < ret; ++i) {
+ unsigned bytes_to_send = events[i].data.u64;
+ unsigned ret;
+
+ if (bytes_to_send > 65536) {
+ bytes_to_send = 65536;
+ }
+
+ ret = send(events[i].data.fd, buf, bytes_to_send, MSG_NOSIGNAL);
+ if (ret == -1) {
+ perror("send()");
+ exit(1);
+ }
+
+ events[i].data.u64 -= ret;
+ bytes_sent += ret;
+
+ // update the central counter after every 1MB (8ms
+ // at gigabit speeds, should be enough) of sent data
+ if (bytes_sent > 1048576) {
+ pthread_mutex_lock(&send_mutex);
+ total_bytes_sent += bytes_sent;
+ pthread_mutex_unlock(&send_mutex);
+
+ bytes_sent = 0;
+ }
+
+ if (events[i].data.u64 == 0) {
+ close(events[i].data.fd);
+ if (epoll_ctl(ep_fd, EPOLL_CTL_DEL, events[i].data.fd, NULL) == -1) {
+ perror("EPOLL_CTL_ADD");
+ exit(1);
+ }
+
+ generate_new_sender(ep_fd);
+ }
+ }