Index: benchmark/io/sendfile/consumer.c
===================================================================
--- benchmark/io/sendfile/consumer.c	(revision 8761d40a52a968eac13a3bc2545622386e7a958a)
+++ benchmark/io/sendfile/consumer.c	(revision 8761d40a52a968eac13a3bc2545622386e7a958a)
@@ -0,0 +1,128 @@
+// Simple sink program that opens a tcp socket on a random port
+// and then reads everything the socket has to write and then ends.
+
+#define _GNU_SOURCE
+
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <errno.h>
+#include <time.h>
+#include <unistd.h>
+
+#include <sys/socket.h>
+#include <netinet/in.h>
+
+enum {
+	USAGE_ERROR = 1,
+	SOCKET_ERROR,
+	BIND_INUSE,
+	BIND_ERROR,
+	GETNAME_ERROR,
+	LISTEN_ERROR,
+	ACCEPT_ERROR,
+	READ_ERROR
+};
+
+enum { buffer_len = 10240 };
+char buffer[buffer_len];
+
+enum { TIMEGRAN = 1000000000LL };
+
+int main(int argc, char * argv[]) {
+	int port = 0;
+	switch(argc) {
+	case 1: break;
+	case 2:
+	default:
+		fprintf( stderr, "USAGE: %s [port]", argv[0] );
+		exit( USAGE_ERROR );
+	}
+
+	printf( "%d: Listening on port %d\n", getpid(), port );
+	int listenfd = socket(AF_INET, SOCK_STREAM, 0);
+	if(listenfd < 0) {
+		fprintf( stderr, "socket error: (%d) %s\n", (int)errno, strerror(errno) );
+		exit( SOCKET_ERROR );
+	}
+
+	int ret = 0;
+	struct sockaddr_in address;
+	socklen_t addrlen = sizeof(address);
+	memset( (char *)&address, '\0', addrlen );
+	address.sin_family = AF_INET;
+	address.sin_addr.s_addr = htonl( INADDR_ANY );
+	address.sin_port = htons( port );
+
+	ret = bind( listenfd, (struct sockaddr *) &address, addrlen );
+	if(ret < 0) {
+		if(errno == EADDRINUSE) {
+			fprintf( stderr, "Port already in use in non-interactive mode. Aborting\n" );
+			exit( BIND_INUSE );
+		}
+		fprintf( stderr, "bind error: (%d) %s\n", (int)errno, strerror(errno) );
+		exit( BIND_ERROR );
+	}
+
+	ret = getsockname( listenfd, (struct sockaddr *) &address, &addrlen );
+	if(ret < 0) {
+		fprintf( stderr, "getname error: (%d) %s\n", (int)errno, strerror(errno) );
+		exit(GETNAME_ERROR);
+	}
+
+	printf( "actial port: %d\n", ntohs(address.sin_port) );
+
+	ret = listen( listenfd, 0 );
+	if(ret < 0) {
+		fprintf( stderr, "listen error: (%d) %s\n", (int)errno, strerror(errno) );
+		exit( 5 );
+	}
+
+	struct sockaddr_in cli_addr;
+     	__socklen_t clilen = sizeof(cli_addr);
+	int fd = accept( listenfd, (struct sockaddr *) &cli_addr, &clilen );
+	if(fd < 0) {
+		fprintf( stderr, "accept error: (%d) %s\n", (int)errno, strerror(errno) );
+		exit( ACCEPT_ERROR );
+	}
+
+	int error = 0;
+	size_t calls = 0;
+	size_t bytes = 0;
+
+	struct timespec after, before;
+
+	clock_gettime(CLOCK_MONOTONIC, &before);
+
+	for(;;) {
+		ret = recv(fd, buffer, buffer_len, 0);
+		if(ret == 0 ) goto EXIT;
+		if(ret < 0 ) {
+			if( errno == EAGAIN || errno == EWOULDBLOCK) continue;
+			if( errno == ECONNRESET ) { printf("Connection reset\n"); goto EXIT; }
+			if( errno == EPIPE ) { printf("Pipe closed\n"); goto EXIT; }
+			fprintf( stderr, "accept error: (%d) %s\n", (int)errno, strerror(errno) );
+			error = READ_ERROR;
+			goto EXIT;
+		}
+		calls++;
+		bytes += ret;
+	}
+	EXIT:;
+
+	clock_gettime(CLOCK_MONOTONIC, &after);
+
+	uint64_t tb = ((int64_t)before.tv_sec * TIMEGRAN) + before.tv_nsec;
+	uint64_t ta = ((int64_t)after.tv_sec * TIMEGRAN) + after.tv_nsec;
+	double secs = ((double)ta - tb) / TIMEGRAN;
+
+	printf("Received %'zu bytes in %'zu reads, %f seconds\n", bytes, calls, secs);
+	printf(" - %'3.3f bytes per second\n", (((double)bytes) / secs));
+	printf(" - %'3.3f bytes per calls\n", (((double)bytes) / calls));
+
+	close(listenfd);
+	close(fd);
+	return error;
+}
