Skip to content

Instantly share code, notes, and snippets.

@miekg
Created May 10, 2017 10:33
Show Gist options
  • Star 13 You must be signed in to star a gist
  • Fork 7 You must be signed in to fork a gist
  • Save miekg/a61d55a8ec6560ad6c4a2747b21e6128 to your computer and use it in GitHub Desktop.
Save miekg/a61d55a8ec6560ad6c4a2747b21e6128 to your computer and use it in GitHub Desktop.
udp server in C
/*
* udpserver.c - A simple UDP echo server
* usage: udpserver <port>
*/
#include <stdio.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 */
int clientlen; /* byte size of client's address */
struct sockaddr_in serveraddr; /* server's addr */
struct sockaddr_in clientaddr; /* client addr */
struct hostent *hostp; /* client host info */
char *buf; /* 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));
/*
* 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 (1) {
/*
* recvfrom: receive a UDP datagram from a client
*/
buf = malloc(BUFSIZE);
n = recvfrom(sockfd, buf, BUFSIZE, 0,
(struct sockaddr *)&clientaddr, &clientlen);
if (n < 0)
error("ERROR in recvfrom");
/*
* gethostbyaddr: determine who sent the datagram
*/
hostp = gethostbyaddr((const char *)&clientaddr.sin_addr.s_addr,
sizeof(clientaddr.sin_addr.s_addr),
AF_INET);
if (hostp == NULL)
error("ERROR on gethostbyaddr");
hostaddrp = inet_ntoa(clientaddr.sin_addr);
if (hostaddrp == NULL)
error("ERROR on inet_ntoa\n");
/*printf("server received %d bytes\n", n); */
/*
* 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");
}
}
@ussserrr
Copy link

Do we really need to malloc() the buffer at every loop cycle?

@lafdez
Copy link

lafdez commented Dec 9, 2018

Probably it is a mistake. I am pretty sure you can malloc() before entering the loop. And then, inside the loop, you should do a memset() to reset the buffer every cycle.

Copy link

ghost commented May 10, 2019

sure it is a mistake, and a serious one as memory allocated is never freed (and could not be as previous buf pointer value is lost/overwritten each time).
also there is no need to memset() as data length is supplied on input.

@Arkango
Copy link

Arkango commented Nov 28, 2019

I'm having trouble with recvfrom, error 15, which is non blocking errror

@bill-the-programmer
Copy link

bill-the-programmer commented Jan 29, 2020

More over... There is no need to declare int to be casted later into uint.... And call atoul() to get unsigned value instead of atoi()...
...
int portno;
...
portno = atoi(argv[1]);
...
serveraddr.sin_port = htons((unsigned short)portno);
...

@ShooreshS
Copy link

Thanks a lot for sharing. HOWEVER, it does not show 802.1q tags similar to another program that I got from here.
I can capture the complete ethernet frame including the VLAN tags using tcpdump. For some reason, these programs drop/exclude 802.1q tags.
Does anybody know the reason?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment