Skip to content

Instantly share code, notes, and snippets.

@msiedlarek
Created August 29, 2012 17:23
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save msiedlarek/3515841 to your computer and use it in GitHub Desktop.
Save msiedlarek/3515841 to your computer and use it in GitHub Desktop.
Timing TCP sending of padded and unpadded messages
#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;
}
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
#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