Created
August 29, 2012 17:23
-
-
Save msiedlarek/3515841 to your computer and use it in GitHub Desktop.
Timing TCP sending of padded and unpadded messages
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <arpa/inet.h> | |
#include <sys/types.h> | |
#include <sys/socket.h> | |
#include <sys/time.h> | |
#include <netdb.h> | |
#include <unistd.h> | |
#include <errno.h> | |
#include <string.h> | |
#include <stdlib.h> | |
#include <stdio.h> | |
#ifndef HOSTNAME | |
#error "You need to define HOSTNAME macro using compiler flag." | |
#endif /* HOSTNAME */ | |
#ifndef PORT | |
#error "You need to define PORT macro using compiler flag." | |
#endif /* PORT */ | |
#ifndef DATA_SIZE | |
#error "You need to define DATA_SIZE macro using compiler flag." | |
#endif /* DATA_SIZE */ | |
#ifndef ITERATIONS | |
#error "You need to define ITERATIONS macro using compiler flag." | |
#endif /* ITERATIONS */ | |
int main(void) | |
{ | |
/* Hostname, IP address or NULL to use any. */ | |
const char* hostname = HOSTNAME; | |
/* Port number, service name from /etc/services or NULL to use any. */ | |
const char* service = PORT; | |
int eai_error; | |
struct addrinfo service_address_hints; | |
struct addrinfo *service_addresses; | |
struct addrinfo *service_address; | |
int server_socket = -1; | |
char server_ip_string[INET6_ADDRSTRLEN]; | |
int server_port; | |
void* server_address; | |
unsigned char buffer[DATA_SIZE]; | |
int iteration; | |
struct timeval receiving_start; | |
struct timeval receiving_end; | |
memset(&service_address_hints, 0, sizeof(service_address_hints)); | |
/* Use IPv4 or IPv6. */ | |
service_address_hints.ai_family = AF_UNSPEC; | |
/* Use TCP protocol. */ | |
service_address_hints.ai_socktype = SOCK_STREAM; | |
/* Choose IP automatically. */ | |
service_address_hints.ai_flags = AI_PASSIVE; | |
eai_error = getaddrinfo( | |
hostname, | |
service, | |
&service_address_hints, | |
&service_addresses | |
); | |
if (eai_error) { | |
fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(eai_error)); | |
return EXIT_FAILURE; | |
} | |
for (service_address = service_addresses; service_address != NULL; | |
service_address = service_address->ai_next) { | |
server_socket = socket( | |
service_address->ai_family, | |
service_address->ai_socktype, | |
service_address->ai_protocol | |
); | |
if (server_socket == -1) { | |
fprintf(stderr, "socket: %s\n", strerror(errno)); | |
continue; | |
} | |
if (connect( | |
server_socket, | |
service_address->ai_addr, | |
service_address->ai_addrlen | |
) == -1) { | |
close(server_socket); | |
server_socket = -1; | |
fprintf(stderr, "connect: %s\n", strerror(errno)); | |
continue; | |
} | |
break; | |
} | |
if (service_address == NULL) { | |
goto clean_and_exit; | |
} | |
if (service_address->ai_family == AF_INET) { | |
/* Get address information for IPv4. */ | |
server_address = (void*)(&( | |
((struct sockaddr_in*)service_address->ai_addr)->sin_addr | |
)); | |
server_port = ntohs( | |
((struct sockaddr_in*)service_address->ai_addr)->sin_port | |
); | |
} else if (service_address->ai_family == AF_INET6) { | |
/* Get address information for IPv6. */ | |
server_address = (void*)(&( | |
((struct sockaddr_in6*)service_address->ai_addr)->sin6_addr | |
)); | |
server_port = ntohs( | |
((struct sockaddr_in6*)service_address->ai_addr)->sin6_port | |
); | |
} else { | |
fputs("Unsupported internet address family!", stderr); | |
goto clean_and_exit; | |
} | |
/* Convert IP address to it's printable representation. */ | |
inet_ntop( | |
service_address->ai_family, | |
server_address, | |
server_ip_string, | |
sizeof(server_ip_string) | |
); | |
printf("Connected to %s on port %d\n", server_ip_string, server_port); | |
gettimeofday(&receiving_start, NULL); | |
for (iteration = 0; iteration < ITERATIONS; iteration++) { | |
if (send(server_socket, &buffer, DATA_SIZE, 0) != DATA_SIZE) { | |
fprintf(stderr, "send: %s\n", strerror(errno)); | |
} | |
} | |
gettimeofday(&receiving_end, NULL); | |
printf("%u\n", receiving_end.tv_usec - receiving_start.tv_usec); | |
clean_and_exit: | |
if (server_socket != -1) { | |
close(server_socket); | |
} | |
freeaddrinfo(service_addresses); | |
return EXIT_SUCCESS; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
DATA_SIZE_WITHOUT_PADDING = 7 | |
DATA_SIZE_WITH_PADDING = 8 | |
ITERATIONS = 1000000 | |
HOSTNAME = localhost | |
PORT = 8000 | |
################################################################################ | |
CC = gcc | |
CFLAGS = -Wall -Wextra -ansi -pedantic -O2 \ | |
-DHOSTNAME="(const char *)\"$(HOSTNAME)\"" \ | |
-DPORT="(const char *)\"$(PORT)\"" \ | |
-DITERATIONS="(int)$(ITERATIONS)" | |
all: padded_server nonpadded_server padded_client nonpadded_client | |
padded_server: server.c | |
$(CC) $(CFLAGS) -DDATA_SIZE="(size_t)$(DATA_SIZE_WITH_PADDING)" -o $@ $< | |
nonpadded_server: server.c | |
$(CC) $(CFLAGS) -DDATA_SIZE="(size_t)$(DATA_SIZE_WITHOUT_PADDING)" -o $@ $< | |
padded_client: client.c | |
$(CC) $(CFLAGS) -DDATA_SIZE="(size_t)$(DATA_SIZE_WITH_PADDING)" -o $@ $< | |
nonpadded_client: client.c | |
$(CC) $(CFLAGS) -DDATA_SIZE="(size_t)$(DATA_SIZE_WITHOUT_PADDING)" -o $@ $< | |
clean: | |
rm -f padded_server nonpadded_server padded_client nonpadded_client |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <arpa/inet.h> | |
#include <sys/types.h> | |
#include <sys/socket.h> | |
#include <sys/time.h> | |
#include <netdb.h> | |
#include <unistd.h> | |
#include <errno.h> | |
#include <time.h> | |
#include <string.h> | |
#include <stdlib.h> | |
#include <stdio.h> | |
#ifndef HOSTNAME | |
#error "You need to define HOSTNAME macro using compiler flag." | |
#endif /* HOSTNAME */ | |
#ifndef PORT | |
#error "You need to define PORT macro using compiler flag." | |
#endif /* PORT */ | |
#ifndef DATA_SIZE | |
#error "You need to define DATA_SIZE macro using compiler flag." | |
#endif /* DATA_SIZE */ | |
#ifndef ITERATIONS | |
#error "You need to define ITERATIONS macro using compiler flag." | |
#endif /* ITERATIONS */ | |
static const int LISTENER_QUEUE_LIMIT = 4; | |
int main(void) | |
{ | |
/* Hostname, IP address or NULL to use any. */ | |
const char* hostname = HOSTNAME; | |
/* Port number, service name from /etc/services or NULL to use any. */ | |
const char* service = PORT; | |
int eai_error; | |
struct addrinfo service_address_hints; | |
struct addrinfo *service_addresses; | |
struct addrinfo *service_address; | |
int listener_socket = -1; | |
char listener_ip_string[INET6_ADDRSTRLEN]; | |
int listener_port; | |
void* listener_address; | |
int client_socket; | |
struct sockaddr_storage client_address; | |
socklen_t client_address_size = sizeof(client_address); | |
unsigned char buffer[DATA_SIZE]; | |
int iteration; | |
struct timeval receiving_start; | |
struct timeval receiving_end; | |
memset(&service_address_hints, 0, sizeof(service_address_hints)); | |
/* Use IPv4 or IPv6. */ | |
service_address_hints.ai_family = AF_UNSPEC; | |
/* Use TCP protocol. */ | |
service_address_hints.ai_socktype = SOCK_STREAM; | |
/* Choose IP automatically. */ | |
service_address_hints.ai_flags = AI_PASSIVE; | |
eai_error = getaddrinfo( | |
hostname, | |
service, | |
&service_address_hints, | |
&service_addresses | |
); | |
if (eai_error) { | |
fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(eai_error)); | |
return EXIT_FAILURE; | |
} | |
for (service_address = service_addresses; service_address != NULL; | |
service_address = service_address->ai_next) { | |
listener_socket = socket( | |
service_address->ai_family, | |
service_address->ai_socktype, | |
service_address->ai_protocol | |
); | |
if (listener_socket == -1) { | |
fprintf(stderr, "socket: %s\n", strerror(errno)); | |
continue; | |
} | |
if (bind( | |
listener_socket, | |
service_address->ai_addr, | |
service_address->ai_addrlen | |
) == -1) { | |
close (listener_socket); | |
listener_socket = -1; | |
fprintf(stderr, "bind: %s\n", strerror(errno)); | |
continue; | |
} | |
break; | |
} | |
if (service_address == NULL) { | |
goto clean_and_exit; | |
} | |
if (service_address->ai_family == AF_INET) { | |
/* Get address information for IPv4. */ | |
listener_address = (void*)(&( | |
((struct sockaddr_in*)service_address->ai_addr)->sin_addr | |
)); | |
listener_port = ntohs( | |
((struct sockaddr_in*)service_address->ai_addr)->sin_port | |
); | |
} else if (service_address->ai_family == AF_INET6) { | |
/* Get address information for IPv6. */ | |
listener_address = (void*)(&( | |
((struct sockaddr_in6*)service_address->ai_addr)->sin6_addr | |
)); | |
listener_port = ntohs( | |
((struct sockaddr_in6*)service_address->ai_addr)->sin6_port | |
); | |
} else { | |
fputs("Unsupported internet address family!", stderr); | |
goto clean_and_exit; | |
} | |
/* Convert IP address to it's printable representation. */ | |
inet_ntop( | |
service_address->ai_family, | |
listener_address, | |
listener_ip_string, | |
sizeof(listener_ip_string) | |
); | |
if (listen(listener_socket, LISTENER_QUEUE_LIMIT) == -1) { | |
fprintf(stderr, "listen: %s\n", strerror(errno)); | |
goto clean_and_exit; | |
} | |
printf("Listening on %s port %d\n", listener_ip_string, listener_port); | |
client_socket = accept( | |
listener_socket, | |
(struct sockaddr *)&client_address, | |
&client_address_size | |
); | |
if (client_socket == -1) { | |
fprintf(stderr, "accept: %s\n", strerror(errno)); | |
goto clean_and_exit; | |
} | |
gettimeofday(&receiving_start, NULL); | |
for (iteration = 0; iteration < ITERATIONS; iteration++) { | |
if (recv(client_socket, &buffer, DATA_SIZE, 0) != DATA_SIZE) { | |
fprintf(stderr, "recv: %s\n", strerror(errno)); | |
} | |
} | |
gettimeofday(&receiving_end, NULL); | |
printf("%u\n", receiving_end.tv_usec - receiving_start.tv_usec); | |
close(client_socket); | |
clean_and_exit: | |
if (listener_socket != -1) { | |
close(listener_socket); | |
} | |
freeaddrinfo(service_addresses); | |
return EXIT_SUCCESS; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment