source: benchmark/io/sendfile/consumer.c @ da81b849

ADTast-experimentalenumpthread-emulationqualifiedEnum
Last change on this file since da81b849 was da81b849, checked in by Thierry Delisle <tdelisle@…>, 2 years ago

Fix argument handling for sink.

  • Property mode set to 100644
File size: 3.5 KB
Line 
1// Simple sink program that opens a tcp socket on a random port
2// and then reads everything the socket has to write and then ends.
3
4#define _GNU_SOURCE
5
6#include <stdint.h>
7#include <stdio.h>
8#include <stdlib.h>
9#include <string.h>
10
11#include <errno.h>
12#include <time.h>
13#include <unistd.h>
14
15#include <sys/socket.h>
16#include <netinet/in.h>
17
18enum {
19        USAGE_ERROR = 1,
20        SOCKET_ERROR,
21        BIND_INUSE,
22        BIND_ERROR,
23        GETNAME_ERROR,
24        LISTEN_ERROR,
25        ACCEPT_ERROR,
26        READ_ERROR
27};
28
29enum { buffer_len = 10240 };
30char buffer[buffer_len];
31
32enum { TIMEGRAN = 1000000000LL };
33
34int main(int argc, char * argv[]) {
35        int port = 0;
36        switch(argc) {
37        case 1: break;
38        case 2:
39                {
40                        const char * const str = argv[1];
41                        char* endptr;
42                        unsigned long long ret = strtoul(str, &endptr, 10);
43                        if('\0' != *endptr) { fprintf( stderr, "Invalid argument \"%s\" (not a number)\n", str ); goto USAGE;}
44                        if(errno == ERANGE || ret > 65535)  { fprintf( stderr, "Invalid argument \"%s\" (value too large)\n", str ); goto USAGE;}
45
46                        port = ret;
47                        break;
48                }
49        USAGE:
50        default:
51                fprintf( stderr, "USAGE: %s [port]\n", argv[0] );
52                exit( USAGE_ERROR );
53        }
54
55        printf( "%d: Listening on port %d\n", getpid(), port );
56        int listenfd = socket(AF_INET, SOCK_STREAM, 0);
57        if(listenfd < 0) {
58                fprintf( stderr, "socket error: (%d) %s\n", (int)errno, strerror(errno) );
59                exit( SOCKET_ERROR );
60        }
61
62        int ret = 0;
63        struct sockaddr_in address;
64        socklen_t addrlen = sizeof(address);
65        memset( (char *)&address, '\0', addrlen );
66        address.sin_family = AF_INET;
67        address.sin_addr.s_addr = htonl( INADDR_ANY );
68        address.sin_port = htons( port );
69
70        ret = bind( listenfd, (struct sockaddr *) &address, addrlen );
71        if(ret < 0) {
72                if(errno == EADDRINUSE) {
73                        fprintf( stderr, "Port already in use in non-interactive mode. Aborting\n" );
74                        exit( BIND_INUSE );
75                }
76                fprintf( stderr, "bind error: (%d) %s\n", (int)errno, strerror(errno) );
77                exit( BIND_ERROR );
78        }
79
80        ret = getsockname( listenfd, (struct sockaddr *) &address, &addrlen );
81        if(ret < 0) {
82                fprintf( stderr, "getname error: (%d) %s\n", (int)errno, strerror(errno) );
83                exit(GETNAME_ERROR);
84        }
85
86        printf( "actial port: %d\n", ntohs(address.sin_port) );
87
88        ret = listen( listenfd, 0 );
89        if(ret < 0) {
90                fprintf( stderr, "listen error: (%d) %s\n", (int)errno, strerror(errno) );
91                exit( 5 );
92        }
93
94        struct sockaddr_in cli_addr;
95        __socklen_t clilen = sizeof(cli_addr);
96        int fd = accept( listenfd, (struct sockaddr *) &cli_addr, &clilen );
97        if(fd < 0) {
98                fprintf( stderr, "accept error: (%d) %s\n", (int)errno, strerror(errno) );
99                exit( ACCEPT_ERROR );
100        }
101
102        int error = 0;
103        size_t calls = 0;
104        size_t bytes = 0;
105
106        struct timespec after, before;
107
108        clock_gettime(CLOCK_MONOTONIC, &before);
109
110        for(;;) {
111                ret = recv(fd, buffer, buffer_len, 0);
112                if(ret == 0 ) goto EXIT;
113                if(ret < 0 ) {
114                        if( errno == EAGAIN || errno == EWOULDBLOCK) continue;
115                        if( errno == ECONNRESET ) { printf("Connection reset\n"); goto EXIT; }
116                        if( errno == EPIPE ) { printf("Pipe closed\n"); goto EXIT; }
117                        fprintf( stderr, "accept error: (%d) %s\n", (int)errno, strerror(errno) );
118                        error = READ_ERROR;
119                        goto EXIT;
120                }
121                calls++;
122                bytes += ret;
123        }
124        EXIT:;
125
126        clock_gettime(CLOCK_MONOTONIC, &after);
127
128        uint64_t tb = ((int64_t)before.tv_sec * TIMEGRAN) + before.tv_nsec;
129        uint64_t ta = ((int64_t)after.tv_sec * TIMEGRAN) + after.tv_nsec;
130        double secs = ((double)ta - tb) / TIMEGRAN;
131
132        printf("Received %'zu bytes in %'zu reads, %f seconds\n", bytes, calls, secs);
133        printf(" - %'3.3f bytes per second\n", (((double)bytes) / secs));
134        printf(" - %'3.3f bytes per calls\n", (((double)bytes) / calls));
135
136        close(listenfd);
137        close(fd);
138        return error;
139}
Note: See TracBrowser for help on using the repository browser.