Skip to content

Instantly share code, notes, and snippets.

@akcoder
Created December 4, 2019 19:20
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 akcoder/8c04adecfed9f0b73ebda8c874f12da9 to your computer and use it in GitHub Desktop.
Save akcoder/8c04adecfed9f0b73ebda8c874f12da9 to your computer and use it in GitHub Desktop.
A modified version of the UDP echo server from CMU. Modified to echo back the number of bytes sent, not just the strlen of the data sent. Fixes issue with the SmartRG CPES where they send 24 NULL bytes.
/*
* https://www.cs.cmu.edu/afs/cs/academic/class/15213-f99/www/class26/udpserver.c
* udpserver.c - A simple UDP echo server
* usage: udpserver <port>
*/
#include <stdio.h>
#include <stdbool.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <netdb.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#define BUFSIZE 1024
/*
* error - wrapper for perror
*/
void error(char *msg) {
perror(msg);
exit(1);
}
int main(int argc, char **argv) {
int sockfd; /* socket */
int portno; /* port to listen on */
socklen_t clientlen; /* byte size of client's address */
struct sockaddr_in serveraddr; /* server's addr */
struct sockaddr_in clientaddr; /* client addr */
char buf[BUFSIZE]; /* message buf */
char *hostaddrp; /* dotted decimal host addr string */
int optval; /* flag value for setsockopt */
int n; /* message byte size */
/*
* check command line arguments
*/
if (argc != 2) {
fprintf(stderr, "usage: %s <port>\n", argv[0]);
exit(1);
}
portno = atoi(argv[1]);
// socket: create the parent socket
sockfd = socket(AF_INET, SOCK_DGRAM, 0);
if (sockfd < 0) {
error("ERROR opening socket");
}
/* setsockopt: Handy debugging trick that lets
* us rerun the server immediately after we kill it;
* otherwise we have to wait about 20 secs.
* Eliminates "ERROR on binding: Address already in use" error.
*/
optval = 1;
setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (const void *)&optval, sizeof(int));
//Init the buffer to null
memset(buf, 0, BUFSIZE);
// build the server's Internet address
bzero((char *)&serveraddr, sizeof(serveraddr));
serveraddr.sin_family = AF_INET;
serveraddr.sin_addr.s_addr = htonl(INADDR_ANY);
serveraddr.sin_port = htons((unsigned short)portno);
// bind: associate the parent socket with a port
if (bind(sockfd, (struct sockaddr *)&serveraddr, sizeof(serveraddr)) < 0) {
error("ERROR on binding");
}
// main loop: wait for a datagram, then echo it
clientlen = sizeof(clientaddr);
while (true) {
// recvfrom: receive a UDP datagram from a client
bzero(buf, BUFSIZE);
n = recvfrom(sockfd, buf, BUFSIZE, 0, (struct sockaddr *)&clientaddr, &clientlen);
hostaddrp = inet_ntoa(clientaddr.sin_addr);
if (n < 0) {
error("ERROR in recvfrom");
} else if (n > BUFSIZE) {
snprintf(buf, BUFSIZE, "ERROR amount of data received from %s is greater than buffer size of %d", hostaddrp, BUFSIZE);
error(buf);
}
printf("Received %d/%d bytes from %s\n", (int)strlen(buf), n, hostaddrp);
// sendto: echo the input back to the client
n = sendto(sockfd, buf, n, 0, (struct sockaddr *)&clientaddr, clientlen);
if (n < 0) {
error("ERROR in sendto");
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment