Skip to content

Instantly share code, notes, and snippets.

@qookei
Last active May 22, 2020 22:17
Show Gist options
  • Save qookei/877ff32f75f722a8bbc3651169a5461a to your computer and use it in GitHub Desktop.
Save qookei/877ff32f75f722a8bbc3651169a5461a to your computer and use it in GitHub Desktop.
#include <iostream>
#include <string.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <time.h>
#include <inttypes.h>
#include <unistd.h>
#include <atomic>
#include <sys/wait.h>
void check(int v, const char *reason) {
if (v < 0) {
fprintf(stderr, "%s failed: %s\n", reason, strerror(errno));
abort();
}
}
uint64_t current_time_ns() {
timespec tv;
clock_gettime(CLOCK_MONOTONIC, &tv);
return UINT64_C(1000000000) * tv.tv_sec + tv.tv_nsec;
}
std::atomic_bool do_exit = false;
void do_one_send() {
int socket_fd = socket(AF_UNIX, SOCK_STREAM, 0);
check(socket_fd, "socket");
sockaddr_un server_addr;
server_addr.sun_family = AF_UNIX;
memcpy(server_addr.sun_path, "\0perf-test!\0", 12);
check(connect(
socket_fd,
reinterpret_cast<sockaddr *>(&server_addr),
offsetof(sockaddr_un, sun_path) + 12), "connect");
int recv_size;
while (!do_exit) {
uint64_t current_time = current_time_ns();
uint8_t message[8];
memcpy(message, &current_time, 8);
check(send(socket_fd, message, 8, 0), "send");
check((recv_size = recv(socket_fd, message, 8, 0)), "recv");
uint64_t send_time;
memcpy(&send_time, message, 8);
uint64_t diff = current_time_ns() - send_time;
printf("%" PRIu64 "\n", diff);
timespec n{.tv_sec = 1, .tv_nsec = 0};
nanosleep(&n, nullptr);
}
close(socket_fd);
}
void signal_handler(int) {
do_exit = true;
}
int main() {
signal(SIGTERM, signal_handler);
while(!do_exit) {
timespec n{.tv_sec = 0, .tv_nsec = 1000000};
nanosleep(&n, nullptr);
pid_t p = fork();
check(p, "fork");
if (!p) {
do_one_send();
return 0;
}
}
}
#include <iostream>
#include <string.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <unistd.h>
#include <sys/epoll.h>
#include <sys/fcntl.h>
#include <assert.h>
void check(int v, const char *reason) {
if (v < 0) {
fprintf(stderr, "%s failed: %s\n", reason, strerror(errno));
abort();
}
}
int main() {
int epoll_fd = epoll_create1(0);
check(epoll_fd, "epoll_create1");
int socket_fd = socket(AF_UNIX, SOCK_STREAM | SOCK_NONBLOCK, 0);
check(socket_fd, "socket");
sockaddr_un server_addr;
server_addr.sun_family = AF_UNIX;
memcpy(server_addr.sun_path, "\0perf-test!\0", 12);
check(bind(socket_fd,
reinterpret_cast<sockaddr *>(&server_addr),
offsetof(sockaddr_un, sun_path) + 12),
"bind");
check(listen(socket_fd, 0), "listen");
{
epoll_event ev;
ev.events = EPOLLIN;
ev.data.fd = socket_fd;
check(epoll_ctl(epoll_fd, EPOLL_CTL_ADD, socket_fd, &ev), "epoll_ctl(EPOLL_CTL_ADD)");
}
printf("Entering main epoll loop...\n");
constexpr size_t max_events = 10;
epoll_event events[max_events];
while (true) {
int n_fds = epoll_wait(epoll_fd, events, max_events, -1);
check(n_fds, "epoll_wait");
for (int i = 0; i < n_fds; i++) {
auto fd = events[i].data.fd;
if (fd == socket_fd) {
sockaddr_un addr;
socklen_t len = sizeof(sockaddr_un);
int client_fd = accept(socket_fd,
reinterpret_cast<sockaddr *>(&addr),
&len);
check(client_fd, "accept");
int flags=fcntl(client_fd, F_GETFL);
fcntl(client_fd, F_SETFL, flags | O_NONBLOCK);
epoll_event ev;
ev.events = EPOLLHUP | EPOLLIN | EPOLLET;
ev.data.fd = client_fd;
check(epoll_ctl(epoll_fd, EPOLL_CTL_ADD, client_fd, &ev), "epoll_ctl(EPOLL_CTL_ADD)");
} else {
if (events[i].events & EPOLLHUP) {
close(fd);
continue;
}
char buf[1024];
int size = recv(fd, buf, 1024, 0);
assert(size > 0);
write(fd, buf, size);
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment