Last active
July 27, 2017 11:52
-
-
Save huzhifeng/cd9b9bf36e52433d6e48c366f12bf23a to your computer and use it in GitHub Desktop.
UDP latency test (Based on https://www.abc.se/~m6695/udp.html)
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
#ifndef _COMMON_H | |
#define MAX_IP_LEN 16 | |
#define MAX_TIME_LEN 32 | |
#define MAX_DATA_LEN 64 | |
/* 6ms */ | |
#define MAX_LATENCY (60 * 1000) | |
typedef struct _packet { | |
unsigned long long sid; | |
unsigned long long ts; | |
char msg[MAX_DATA_LEN]; | |
} packet; | |
char *microsecond2time(char *buf, unsigned long long ts) | |
{ | |
unsigned long long sec = ts / 1000 / 1000; | |
unsigned long long msec = (ts - sec * 1000 * 1000) / 1000; | |
unsigned long long usec = (ts - sec * 1000 * 1000) % 1000; | |
char time[MAX_TIME_LEN] = { 0x0 }; | |
struct tm *ptm = NULL; | |
if (NULL == buf) { | |
return NULL; | |
} | |
ptm = localtime((time_t *)&sec); | |
strftime(time, MAX_TIME_LEN, "%Y-%m-%d %H:%M:%S", ptm); | |
sprintf(buf, "[%s:%03d:%03d]", time, msec, usec); | |
return buf; | |
} | |
#endif |
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
CC = gcc | |
CFLAGS = -O2 -g -Wall | |
INSTALL_DIR = /usr/bin | |
.PHONY: clean install uninstall | |
all: server client | |
server: udp-server.c | |
$(CC) udp-server.c -o udp-server | |
client: udp-client.c | |
$(CC) udp-client.c -o udp-client | |
clean: | |
rm -f *.o udp-server udp-client | |
install: server client | |
cp -f udp-server udp-client $(INSTALL_DIR)/ | |
uninstall: | |
rm -f $(INSTALL_DIR)/udp-server $(INSTALL_DIR)/udp-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 <stdio.h> | |
#include <stdlib.h> | |
#include <string.h> | |
#include <time.h> | |
#include <unistd.h> | |
#include <sys/time.h> | |
#include <arpa/inet.h> | |
#include "common.h" | |
static void print_help(const char *program) | |
{ | |
printf("Version: %s %s\n", __DATE__, __TIME__); | |
printf("Usage: %s <ip> [port]\n", program); | |
printf(" ip server IP for connecting\n"); | |
printf(" port UDP port for communicating (default is 2017)\n"); | |
printf(" -h, --help display this help and exit\n"); | |
printf("\nExample:\n"); | |
printf(" %s 192.168.1.1\n", program); | |
printf(" %s 192.168.1.1 2017\n", program); | |
} | |
int main(int argc, char *argv[]) | |
{ | |
int s = 0; /* UDP socket descriptor */ | |
int port = 2017; /* UDP port (default) */ | |
unsigned long long sid = 0; /* UDP packet sequence id */ | |
char ip[MAX_IP_LEN] = ""; /* Server IP */ | |
packet pkt; | |
struct sockaddr_in si; | |
struct timeval tv; | |
struct timezone tz; | |
if (argc == 2) { | |
if ((strcmp(argv[1], "-h") == 0) || (strcmp(argv[1], "--help") == 0)) { | |
print_help(argv[0]); | |
exit(0); | |
} else { | |
strncpy(ip, argv[1], MAX_IP_LEN); /* FIXME: verify ip address */ | |
} | |
} else if (argc == 3) { | |
strncpy(ip, argv[1], MAX_IP_LEN); /* FIXME: verify ip address */ | |
port = atoi(argv[2]); /* FIXME: verify port number */ | |
} else { | |
print_help(argv[0]); | |
exit(0); | |
} | |
if ((s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1) { | |
fprintf(stderr, "Failed to create socket\n"); | |
exit(1); | |
} | |
memset(&si, 0x0, sizeof(si)); | |
si.sin_family = AF_INET; | |
si.sin_port = htons(port); | |
if (inet_aton(ip, &si.sin_addr) == 0) { | |
fprintf(stderr, "Failed to inet_aton with %s:%d\n", ip, port); | |
exit(1); | |
} | |
while (1) { | |
sid++; | |
gettimeofday(&tv, &tz); | |
memset(&pkt, 0x0, sizeof(pkt)); | |
pkt.sid = sid; | |
pkt.ts = tv.tv_sec * 1000 * 1000 + tv.tv_usec; | |
microsecond2time(pkt.msg, pkt.ts); | |
sprintf(pkt.msg, "%s-[%08llu]", pkt.msg, sid); | |
printf("%s\n", pkt.msg); | |
if (sendto(s, &pkt, sizeof(pkt), 0, (struct sockaddr *)&si,\ | |
sizeof(struct sockaddr_in)) == -1) { | |
fprintf(stderr, "Failed to send [%s] to %s:%d\n", pkt.msg, ip, port); | |
close(s); | |
exit(1); | |
} | |
} | |
close(s); | |
return 0; | |
} |
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 <stdio.h> | |
#include <stdlib.h> | |
#include <string.h> | |
#include <time.h> | |
#include <unistd.h> | |
#include <sys/time.h> | |
#include <arpa/inet.h> | |
#include "common.h" | |
static void print_help(const char *program) | |
{ | |
printf("Version: %s %s\n", __DATE__, __TIME__); | |
printf("Usage: %s [port]\n", program); | |
printf(" port UDP port for binding and listening (default is 2017)\n"); | |
printf(" -h, --help display this help and exit\n"); | |
printf("\nExample:\n"); | |
printf(" %s\n", program); | |
printf(" %s 2017\n", program); | |
} | |
int main(int argc, char *argv[]) | |
{ | |
int s = 0; /* UDP socket descriptor */ | |
int port = 2017; /* UDP port */ | |
unsigned long long last_sid = 0; | |
unsigned long long ts = 0; | |
char time[MAX_TIME_LEN] = { 0x0 }; | |
socklen_t addrlen; | |
struct sockaddr_in si_server, si_client; | |
packet pkt; | |
struct timeval tv; | |
struct timezone tz; | |
if (argc == 2) { | |
if ((strcmp(argv[1], "-h") == 0) || (strcmp(argv[1], "--help") == 0)) { | |
print_help(argv[0]); | |
exit(0); | |
} else { | |
port = atoi(argv[2]); /* FIXME: verify port number */ | |
} | |
} else if (argc != 1) { | |
print_help(argv[0]); | |
exit(0); | |
} | |
printf("Starting...\n"); | |
if ((s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1) { | |
fprintf(stderr, "Failed to create socket\n"); | |
exit(1); | |
} | |
memset(&si_server, 0x0, sizeof(si_server)); | |
si_server.sin_family = AF_INET; | |
si_server.sin_port = htons(port); | |
si_server.sin_addr.s_addr = htonl(INADDR_ANY); | |
if (bind(s, (struct sockaddr *)&si_server, sizeof(struct sockaddr)) == -1) { | |
fprintf(stderr, "Failed to bind with port %d\n", port); | |
exit(1); | |
} | |
while (1) { | |
memset(&pkt, 0x0, sizeof(pkt)); | |
if (recvfrom(s, &pkt, sizeof(pkt), 0, \ | |
(struct sockaddr *)&si_client, &addrlen) == -1) { | |
fprintf(stderr, "Failed to recvfrom\n"); | |
close(s); | |
exit(1); | |
} | |
gettimeofday(&tv, &tz); | |
memset(time, 0x0, sizeof(time)); | |
ts = tv.tv_sec * 1000 * 1000 + tv.tv_usec; | |
microsecond2time(time, ts); | |
printf("Received from [%s:%d]: %s\n", inet_ntoa(si_client.sin_addr), \ | |
ntohs(si_client.sin_port), pkt.msg); | |
printf("Local time: %s\n", time); | |
if (pkt.sid != (last_sid + 1)) { | |
printf("Warning: missing sid, expected %llu but actually %llu\n", \ | |
last_sid + 1, pkt.sid); | |
} | |
if (ts - pkt.ts > MAX_LATENCY) { | |
printf("Warning: the latency %llu exceeds the threshold %llu(us)\n", \ | |
ts - pkt.ts, MAX_LATENCY); | |
} | |
last_sid = pkt.sid; | |
} | |
close(s); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment