git.iko.soy/distributed-process
on c7f72ce help sign in
150 lines 3.5 kB history raw
1#include <stdio.h>
2#include <stdlib.h>
3#include <sys/types.h>
4#include <sys/socket.h>
5#include <netdb.h>
6#include <string.h>
7#include <unistd.h>
8#include <signal.h>
9#include <errno.h>
10#include <time.h>
11#include <sys/time.h>
12#include <math.h>
14// Note: this is not consistent across CPUs (and hence across threads on multicore machines)
15double timestamp() {
16 struct timeval tp;
17 gettimeofday(&tp, NULL);
18 return ((double) tp.tv_sec) * 1e6 + (double) tp.tv_usec;
21int server() {
22 printf("starting server\n");
24 struct addrinfo hints, *res;
25 int error, server_socket;
27 memset(&hints, 0, sizeof(hints));
28 hints.ai_family = PF_INET;
29 hints.ai_socktype = SOCK_STREAM;
30 hints.ai_flags = AI_PASSIVE;
32 error = getaddrinfo(NULL, "8080", &hints, &res);
33 if(error) {
34 printf("server error: %s\n", gai_strerror(error));
35 return -1;
36 }
38 server_socket = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
39 if(server_socket < 0) {
40 printf("server error: could not create socket\n");
41 return -1;
42 }
44 int yes = 1;
45 if(setsockopt(server_socket, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) < 0) {
46 printf("server error: could not set socket options\n");
47 return -1;
48 }
50 if(bind(server_socket, res->ai_addr, res->ai_addrlen) < 0) {
51 printf("server error: could not bind to socket\n");
52 return -1;
53 }
55 listen(server_socket, 5);
57 int client_socket;
58 struct sockaddr_storage client_addr;
59 socklen_t addr_size;
60 client_socket = accept(server_socket, (struct sockaddr *)&client_addr, &addr_size);
62 for(;;) {
63 char* buf = malloc(8);
64 ssize_t read = recv(client_socket, buf, 8, 0);
65 if(read == 0) {
66 free(buf);
67 break;
68 }
69 // printf("server received '%s'\n", buf);
70 send(client_socket, buf, 8, 0);
71 free(buf);
72 }
74 freeaddrinfo(res);
75 return 0;
78int client(int pings) {
79 printf("starting client\n");
81 struct addrinfo hints, *res;
82 int error, client_socket;
84 memset(&hints, 0, sizeof(hints));
85 hints.ai_family = PF_INET;
86 hints.ai_socktype = SOCK_STREAM;
88 error = getaddrinfo("127.0.0.1", "8080", &hints, &res);
89 if(error) {
90 printf("client error: %s\n", gai_strerror(error));
91 return -1;
92 }
94 client_socket = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
95 if(client_socket < 0) {
96 printf("client error: could not create socket\n");
97 return -1;
98 }
100 if(connect(client_socket, res->ai_addr, res->ai_addrlen) < 0) {
101 printf("client error: could not connect: %s\n", strerror(errno));
102 return -1;
103 }
105 for(int i = 0; i < pings; i++) {
106 double timestamp_before = timestamp();
108 send(client_socket, "ping123", 8, 0);
110 char *buf = malloc(8);
111 ssize_t read = recv(client_socket, buf, 8, 0);
113 if(read == 0) {
114 printf("server exited prematurely\n");
115 free(buf);
116 break;
117 }
119 // printf("client received '%s'\n", buf);
120 free(buf);
122 double timestamp_after = timestamp();
123 fprintf(stderr, "%i %lf\n", i, timestamp_after - timestamp_before);
124 }
126 printf("client did %d pings\n", pings);
128 freeaddrinfo(res);
129 return 0;
132int usage(int argc, char** argv) {
133 printf("usage: %s <number of pings>\n", argv[0]);
134 return -1;
137int main(int argc, char** argv) {
138 if(argc != 2) {
139 return usage(argc, argv);
140 }
142 if(fork() == 0) {
143 // TODO: we should wait until we know the server is ready
144 int pings = 0;
145 sscanf(argv[1], "%d", &pings);
146 return client(pings);
147 } else {
148 return server();
149 }