Skip to content

Instantly share code, notes, and snippets.

@herry13
Created June 7, 2017 14:54
Show Gist options
  • Select an option

  • Save herry13/194774db850dcc3e6ffbe37e9cd108f8 to your computer and use it in GitHub Desktop.

Select an option

Save herry13/194774db850dcc3e6ffbe37e9cd108f8 to your computer and use it in GitHub Desktop.
//
// To compile:
// gcc -Wall -pedantic -O3 -fomit-frame-pointer -o agent udp.c
//
#include <unistd.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define SERVICE_PORT 9999
#define BUFSIZE 2048
extern int errno;
/**
* Create and return a socket handler for given port number.
*
* Param:
* port - the port which the socket will be opened. If it equals
* to 0, then a random port will be assigned to the socket.
*
* Return: a socket handler, or -1 if socket creation fails
*/
int create_udp_socket(const int & port) {
int sock;
struct sockaddr_in addr;
// create an udp socket
if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
perror("cannot create socket\n");
return -1;
}
// set up our address
memset(&addr, 0, sizeof(addr));
addr.sin_len = sizeof(addr);
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
addr.sin_addr.s_addr = INADDR_ANY; // bind it to all local addresses
// bind the server to the address
if (bind(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
perror("socket binding failed\n");
return -1;
}
return sock;
}
/**
* Listen any message on given port and then print it to standard output.
*
* Param:
* port - the port which the server will listen to
*/
void serve(const int& port) {
int sock;
struct sockaddr_in client_addr;
socklen_t addrlen = sizeof(client_addr);
int recvlen;
unsigned char buf[BUFSIZE];
char hostname[128];
// get server's hostname
gethostname(hostname, 128);
// create an udp socket
sock = create_udp_socket(port);
if (sock == -1) return;
printf("server started on %s, listening on port %d\n", hostname, port);
// loop forever, waiting for connection requests and process the message
while (true) {
recvlen = recvfrom(sock, buf, BUFSIZE, 0, (struct sockaddr *)&client_addr,
&addrlen);
if (recvlen > 0) {
buf[recvlen] = 0;
printf("received message: %s\nfrom:%s port:%d\n",
buf,
inet_ntoa(client_addr.sin_addr),
ntohs(client_addr.sin_port));
}
}
}
/**
* Send a message to given address and port.
*
* Param:
* message - a message to be sent
* address - destination IP address
* port - destination port number
*
* Return: 0 if it is successful, otherwise non-zero integer
*/
int send(const char *message, const char *address, const int port) {
int sock;
int i;
struct sockaddr_in server_addr;
socklen_t addrlen = sizeof(server_addr);
char buf[BUFSIZE];
// create an udp socket
sock = create_udp_socket(0);
if (sock == -1) return -1;
// Set up server's address to whom we want to send messages.
// The address is expressed as a numeric IPv4 address that we will
// convert to a binary format using inet_aton
memset(&server_addr, 0, sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(port);
if (inet_aton(address, &server_addr.sin_addr) == 0) {
perror("inet_atom() failed\n");
return 1;
}
// now, send the message 5 times
for (i = 0; i < 5; i++) {
sprintf(buf, "{\"id\":%d,\"message\":\"%s\"}", i, message);
printf("sending packet %d to %s port %d\nmessage: %s\n",
i, address, port, buf);
if (sendto(sock, buf, strlen(buf), 0, (struct sockaddr *)&server_addr,
addrlen) < 0) {
perror("sendto() failed\n");
}
}
close(sock);
return 0;
}
int main(int argc, char **argv) {
extern char *optarg;
extern int optind;
int c, err = 0;
int port = SERVICE_PORT;
char * message = NULL;
char buf[BUFSIZE];
char address[20];
sprintf(address, "127.0.0.1");
while ((c = getopt(argc, argv, "c:a:p:h")) != -1) {
switch (c) {
case 'c':
message = optarg;
if (strlen(message) <= 0) {
perror("empty message\n");
err = 1;
}
break;
case 'a':
sprintf(address, "%s", optarg);
if (strlen(address) <= 0) {
perror("empty address\n");
err = 2;
}
break;
case 'p':
port = atoi(optarg);
if (port < 1024 || port > 65535) {
sprintf(buf, "invalid port number: %d\n", port);
perror(buf);
err = 3;
}
break;
case 'h':
case '?':
err = 4;
break;
}
}
if (err != 0 || (optind < argc)) {
printf("usage: %s [-c message] [-a address] [-p port]\n", argv[0]);
return 1;
}
if (message == NULL)
serve(port);
else
send(message, address, port);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment