2 * inet (BSD) socket receiver application
3 * starts a listener socket that receives data from requesting
6 * 2010, Razvan Deaconescu
13 #include <sys/types.h>
14 #include <sys/socket.h>
18 #include "sock_util.h"
22 #define DEFAULT_LISTEN_PORT 54321
23 #define DEFAULT_SERVER_BACKLOG 5
24 #define DEFAULT_BUFFER_SIZE 1024
26 #define PACKET_INDEX_SIZE sizeof(unsigned long long)
27 #define PACKET_TIMESPEC_SIZE sizeof(time_t)
28 #define PACKET_PAYLOAD_SIZE (PACKET_SIZE - PACKET_INDEX_SIZE - PACKET_TIMESPEC_SIZE)
29 #define PACKET_SIZE (cmd_args.buffer_size)
32 * TODO: fix nomenclature (TIMER_BASE_PERIOD, cmd_args.frequency)
33 * run the timer once each TIMER_BASE_PERIOD
34 * this is divided by cmd_args.frequency for a shorter period
38 unsigned short int listen_port;
41 .listen_port = DEFAULT_LISTEN_PORT,
42 .buffer_size = DEFAULT_BUFFER_SIZE,
48 /* connection socket */
51 static void init_buffer_random(char *buf, size_t len)
57 for (i = 0; i < len-2; i++)
58 buf[i] = (char) (rand() % 26) + 'a';
62 static void init_buffers(void)
64 init_buffer_random(rcv_buf, PACKET_SIZE);
65 init_buffer_random(snd_buf, PACKET_SIZE);
68 static void init(void)
70 rcv_buf = malloc(PACKET_SIZE * sizeof(char));
71 snd_buf = malloc(PACKET_SIZE * sizeof(char));
72 DIE(snd_buf == NULL, "malloc");
77 static void cleanup(void)
83 static void fill_send_buffer(void)
85 static unsigned long long index = 0;
87 time_t curr_time_secs;
89 curr_time_secs = time(NULL);
91 ptr = snd_buf + PACKET_PAYLOAD_SIZE;
92 * (unsigned long long *) ptr = index;
93 ptr += PACKET_INDEX_SIZE;
94 * (time_t *) ptr = curr_time_secs;
96 printf("[send] index: %llu curr_time_secs: %lu\n", index, curr_time_secs);
100 static ssize_t send_buffer(int sockfd)
102 return send(sockfd, snd_buf, PACKET_SIZE, 0);
105 static ssize_t receive_buffer(int sockfd)
110 while (nbytes < (ssize_t) PACKET_SIZE) {
111 n = recv(sockfd, rcv_buf, PACKET_SIZE - nbytes, 0);
122 static void print_buffer_meta(const char *buf, size_t len)
124 unsigned long long index;
125 time_t curr_time_secs;
126 time_t sender_time_secs;
129 curr_time_secs = time(NULL);
131 ptr = buf + len - PACKET_INDEX_SIZE - PACKET_TIMESPEC_SIZE;
132 index = * (unsigned long long *) ptr;
133 ptr += PACKET_INDEX_SIZE;
134 sender_time_secs = * (time_t *) ptr;
136 printf("[recv] index %llu, ", index);
137 if (sender_time_secs > curr_time_secs)
138 printf("negative latency (weird)\n");
140 printf("latency %lu seconds (curr_time = %lu, sender_time = %lu)\n",
141 curr_time_secs - sender_time_secs,
146 static void usage(const char *argv0)
148 fprintf(stderr, "Usage: %s [-h | --help] [-p | --port <listen-port>] [-b | --buffer-size <buffer-size>]\n", argv0);
151 static void print_args(void)
153 printf("listen_port: %hu\n", cmd_args.listen_port);
154 printf("buffer_size: %lu\n", cmd_args.buffer_size);
157 static void parse_args(int argc, char **argv)
162 int option_index = 0;
163 static struct option long_options[] = {
164 {"port", 1, NULL, 'p'},
165 {"buffer-size", 1, NULL, 'b'},
166 {"help", 0, NULL, 'h'},
170 c = getopt_long(argc, argv, "hp:b:",
171 long_options, &option_index);
177 printf("option %s", long_options[option_index].name);
179 printf(" with arg %s", optarg);
184 /* TODO: use strtoul */
185 cmd_args.listen_port = atoi(optarg);
189 /* TODO: use strtoul */
190 cmd_args.buffer_size = atoi(optarg);
202 printf("?? getopt returned character code 0%o ??\n", c);
206 if (optind != argc) {
214 int main(int argc, char **argv)
218 struct sockaddr_in addr;
219 socklen_t addrlen = 0;
221 parse_args(argc, argv);
225 listenfd = tcp_listen_connections(cmd_args.listen_port,
226 DEFAULT_SERVER_BACKLOG);
227 DIE(listenfd < 0, "tcp_listen_connections");
230 sockfd = accept(listenfd, (SSA *) &addr, &addrlen);
231 DIE(sockfd < 0, "accept");
236 nbytes = receive_buffer(sockfd);
237 DIE(nbytes < 0, "receive_buffer");
239 printf("Connection closed.\n");
243 print_buffer_meta(rcv_buf, PACKET_SIZE);