source: benchmark/io/sendfile/consumer.c @ 8761d40a

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

Added sink program to test splice

  • Property mode set to 100644
File size: 3.2 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        default:
40                fprintf( stderr, "USAGE: %s [port]", argv[0] );
41                exit( USAGE_ERROR );
42        }
43
44        printf( "%d: Listening on port %d\n", getpid(), port );
45        int listenfd = socket(AF_INET, SOCK_STREAM, 0);
46        if(listenfd < 0) {
47                fprintf( stderr, "socket error: (%d) %s\n", (int)errno, strerror(errno) );
48                exit( SOCKET_ERROR );
49        }
50
51        int ret = 0;
52        struct sockaddr_in address;
53        socklen_t addrlen = sizeof(address);
54        memset( (char *)&address, '\0', addrlen );
55        address.sin_family = AF_INET;
56        address.sin_addr.s_addr = htonl( INADDR_ANY );
57        address.sin_port = htons( port );
58
59        ret = bind( listenfd, (struct sockaddr *) &address, addrlen );
60        if(ret < 0) {
61                if(errno == EADDRINUSE) {
62                        fprintf( stderr, "Port already in use in non-interactive mode. Aborting\n" );
63                        exit( BIND_INUSE );
64                }
65                fprintf( stderr, "bind error: (%d) %s\n", (int)errno, strerror(errno) );
66                exit( BIND_ERROR );
67        }
68
69        ret = getsockname( listenfd, (struct sockaddr *) &address, &addrlen );
70        if(ret < 0) {
71                fprintf( stderr, "getname error: (%d) %s\n", (int)errno, strerror(errno) );
72                exit(GETNAME_ERROR);
73        }
74
75        printf( "actial port: %d\n", ntohs(address.sin_port) );
76
77        ret = listen( listenfd, 0 );
78        if(ret < 0) {
79                fprintf( stderr, "listen error: (%d) %s\n", (int)errno, strerror(errno) );
80                exit( 5 );
81        }
82
83        struct sockaddr_in cli_addr;
84        __socklen_t clilen = sizeof(cli_addr);
85        int fd = accept( listenfd, (struct sockaddr *) &cli_addr, &clilen );
86        if(fd < 0) {
87                fprintf( stderr, "accept error: (%d) %s\n", (int)errno, strerror(errno) );
88                exit( ACCEPT_ERROR );
89        }
90
91        int error = 0;
92        size_t calls = 0;
93        size_t bytes = 0;
94
95        struct timespec after, before;
96
97        clock_gettime(CLOCK_MONOTONIC, &before);
98
99        for(;;) {
100                ret = recv(fd, buffer, buffer_len, 0);
101                if(ret == 0 ) goto EXIT;
102                if(ret < 0 ) {
103                        if( errno == EAGAIN || errno == EWOULDBLOCK) continue;
104                        if( errno == ECONNRESET ) { printf("Connection reset\n"); goto EXIT; }
105                        if( errno == EPIPE ) { printf("Pipe closed\n"); goto EXIT; }
106                        fprintf( stderr, "accept error: (%d) %s\n", (int)errno, strerror(errno) );
107                        error = READ_ERROR;
108                        goto EXIT;
109                }
110                calls++;
111                bytes += ret;
112        }
113        EXIT:;
114
115        clock_gettime(CLOCK_MONOTONIC, &after);
116
117        uint64_t tb = ((int64_t)before.tv_sec * TIMEGRAN) + before.tv_nsec;
118        uint64_t ta = ((int64_t)after.tv_sec * TIMEGRAN) + after.tv_nsec;
119        double secs = ((double)ta - tb) / TIMEGRAN;
120
121        printf("Received %'zu bytes in %'zu reads, %f seconds\n", bytes, calls, secs);
122        printf(" - %'3.3f bytes per second\n", (((double)bytes) / secs));
123        printf(" - %'3.3f bytes per calls\n", (((double)bytes) / calls));
124
125        close(listenfd);
126        close(fd);
127        return error;
128}
Note: See TracBrowser for help on using the repository browser.