/* UDS client */ #include #include #include #include #include #include #include #include #include #include #include #include // use abstract address #define SOCKET "\0udsbench.socket" static int die(const char *msg) { if (errno) fprintf(stderr, "%s: error %d %m\n", msg, errno); else fprintf(stderr, "%s\n", msg); if (errno != EPIPE) exit(EXIT_FAILURE); return 0; } int main(int argc, char *argv[]) { struct sockaddr_un addr = { .sun_family = AF_UNIX, .sun_path = SOCKET, }; int sock, rc, client = 1, i; char *buf; struct timespec start, end; double duration; bool async = false; struct pollfd pfd; typeof(&read) f1, f2; long msglen, loops; if (argc != 4) die("usage: client {sync|async} msglen loops"); if (!strcmp(argv[1], "async")) async = true; msglen = strtoul(argv[2], NULL, 0); loops = strtoul(argv[3], NULL, 0); printf("running in %s mode, msg size %lu, %lu loops\n", async ? "async" : "sync", msglen, loops); buf = alloca(msglen); sock = socket(AF_UNIX, SOCK_SEQPACKET, 0); if (sock < 0) die("can't create socket"); if (connect(sock, (struct sockaddr *) &addr, sizeof(addr)) < 0) die("can't connect"); printf("waiting for other client\n"); rc = read(sock, buf, 1); if (rc != 1) { die("read"); exit(EXIT_FAILURE); } if (buf[0] != '\0') client = 2; printf("this is client %d\n", client); clock_gettime(CLOCK_MONOTONIC, &start); if (client == 1) f1 = (typeof(&read))write, f2 = read; else f1 = read, f2 = (typeof(&read))write; if (async && client == 1) { pfd.fd = sock; pfd.events = POLLIN | POLLOUT; for (i = 0; i < loops; ) { rc = poll(&pfd, 1, -1); if (rc == -1) die("poll"); if (pfd.revents & POLLOUT) { rc = write(sock, buf, msglen); if (rc != msglen) { die("write"); break; } } if (pfd.revents & POLLIN) { rc = read(sock, buf, msglen); if (rc != msglen) { die("read"); break; } i++; } } } else { for (i = 0; i < loops; i++) { rc = f1(sock, buf, msglen); if (rc != msglen) { die(f1 == read ? "read" : "write"); break; } rc = f2(sock, buf, msglen); if (rc != msglen) { die(f2 == read ? "read" : "write"); break; } } } clock_gettime(CLOCK_MONOTONIC, &end); duration = end.tv_sec - start.tv_sec + (end.tv_nsec - start.tv_nsec) * 1e-9; printf("%f s, %.0f msg/s, %.1f us/msg, %.3f MB/s\n", duration, loops / duration, duration * 1e6 / loops, (loops * msglen >> 20) / duration); return EXIT_SUCCESS; }