|
// Server side implementation of UDP client-server model |
|
#include <stdio.h> |
|
#include <stdlib.h> |
|
#include <unistd.h> |
|
#include <string.h> |
|
#include <sys/types.h> |
|
#include <sys/socket.h> |
|
#include <arpa/inet.h> |
|
#include <netinet/in.h> |
|
#include <time.h> |
|
#include <pthread.h> |
|
|
|
#define SERVER_PORT 5132 |
|
#define CLIENT_PORT 5133 |
|
|
|
double curr_timestamp() { |
|
struct timespec monotime; |
|
clock_gettime(CLOCK_MONOTONIC, &monotime); |
|
return monotime.tv_sec + monotime.tv_nsec/1000000000.0; |
|
} |
|
|
|
// Driver code |
|
void * server(void * dummy) { |
|
struct sockaddr_in servaddr = {0}, cliaddr = {0}; |
|
|
|
// Creating socket file descriptor |
|
int sockfd = socket(AF_INET, SOCK_DGRAM, 0); |
|
if (sockfd < 0) { |
|
perror("socket creation failed"); |
|
exit(EXIT_FAILURE); |
|
} |
|
|
|
// Filling server information |
|
servaddr.sin_family = AF_INET; |
|
servaddr.sin_addr.s_addr = INADDR_ANY; |
|
servaddr.sin_port = htons(SERVER_PORT); |
|
|
|
// Bind the socket with the server address |
|
if (bind(sockfd, (const struct sockaddr *)&servaddr, sizeof(servaddr)) < 0) { |
|
perror("bind failed"); |
|
exit(EXIT_FAILURE); |
|
} |
|
|
|
socklen_t len = sizeof(cliaddr); |
|
char buffer[128] = {0}; |
|
|
|
double t_start = curr_timestamp(); |
|
while (1) { |
|
int num_bytes = recvfrom(sockfd, (char *)buffer, sizeof(buffer), 0, (struct sockaddr *) &cliaddr, &len); |
|
sendto(sockfd, (const char *)NULL, 0, 0, (const struct sockaddr *) &cliaddr, len); |
|
} |
|
return NULL; |
|
} |
|
|
|
void client() { |
|
struct sockaddr_in servaddr = {0}, cliaddr = {0}; |
|
int sockfd = socket(AF_INET, SOCK_DGRAM, 0); |
|
if (sockfd < 0) { |
|
perror("socket creation failed"); |
|
exit(EXIT_FAILURE); |
|
} |
|
|
|
servaddr.sin_family = AF_INET; |
|
servaddr.sin_addr.s_addr = inet_addr("127.0.0.1"); |
|
servaddr.sin_port = htons(SERVER_PORT); |
|
|
|
// Connect to speed up transmission |
|
if (connect(sockfd, (const struct sockaddr *) &servaddr, sizeof(servaddr)) < 0) { |
|
perror("socket connect failed"); |
|
exit(EXIT_FAILURE); |
|
} |
|
|
|
// Keep track of some temporal characteristics |
|
double t_start = curr_timestamp(); |
|
double last_print = t_start; |
|
double avg_send_elapsed = 0.0, avg_recv_elapsed = 0.0; |
|
|
|
// This buffer is useless, we never send or receive anything. |
|
char buffer[128]; |
|
|
|
while (1) { |
|
// This sleep causes a large increase in latency |
|
//usleep(10000); |
|
|
|
double t_pre_send = curr_timestamp(); |
|
if (send(sockfd, NULL, 0, 0) == -1) { |
|
perror("send failed"); |
|
} |
|
avg_send_elapsed = 0.9*avg_send_elapsed + 0.1*(curr_timestamp() - t_pre_send); |
|
|
|
double t_pre_recv = curr_timestamp(); |
|
socklen_t len = 0; |
|
int num_bytes = recvfrom(sockfd, (char *)buffer, sizeof(buffer), 0, (struct sockaddr *) &cliaddr, &len); |
|
avg_recv_elapsed = 0.9*avg_recv_elapsed + 0.1*(curr_timestamp() - t_pre_recv); |
|
|
|
double curr_time = curr_timestamp(); |
|
if (curr_time - last_print > 1.0) { |
|
last_print = curr_time; |
|
printf("[%.1f] send: %.2fus\trecv: %.2fus\n", curr_time - t_start, avg_send_elapsed*1000000, avg_recv_elapsed*1000000); |
|
} |
|
} |
|
} |
|
|
|
int main() { |
|
pthread_t server_thread; |
|
if (pthread_create(&server_thread, NULL, server, NULL) != 0) { |
|
perror("Unable to create server thread!\n"); |
|
exit(EXIT_FAILURE); |
|
} |
|
client(); |
|
return 0; |
|
} |