#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <time.h>
#include <string.h>
#include <signal.h>
#include <ctype.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <sys/file.h>
#include <sys/wait.h>
#include <errno.h>
#include <ctype.h>

int socket_connected_to_port(int portnum)
{ struct sockaddr_in connection_info;
  int sock=socket(AF_INET, SOCK_DGRAM, 0);
  if (sock<0) { perror("socket creation"); exit(1); }
  bzero(&connection_info, sizeof(connection_info));
  connection_info.sin_family=AF_INET;
  connection_info.sin_addr.s_addr=htonl(INADDR_ANY);
  connection_info.sin_port=htons(portnum);
  int r=bind(sock, (sockaddr *)&connection_info, sizeof(connection_info));
  if (r<0)
  { perror("bind");
    exit(1); }
  return sock; }

int socket_connected_to_random_port(int & portnum)
{ struct sockaddr_in connection_info;
  int sock=socket(AF_INET, SOCK_DGRAM, 0);
  if (sock<0) { perror("socket creation"); exit(1); }
  while (1)
  { portnum=1024+(random() & 0x1FFF);
    bzero(&connection_info, sizeof(connection_info));
    connection_info.sin_family=AF_INET;
    connection_info.sin_addr.s_addr=htonl(INADDR_ANY);
    connection_info.sin_port=htons(portnum);
    int r=bind(sock, (sockaddr *)&connection_info, sizeof(connection_info));
    if (r>=0) break; }
  return sock; }

void main(int argc, char * argv[])
{ srandomdev();
  int portnum;
  int main_socket;
  if (argc>1)
  { portnum=atol(argv[1]);
    main_socket=socket_connected_to_port(portnum); }
  else
    main_socket=socket_connected_to_random_port(portnum);
  printf("[receiver established on port %d]\n", portnum);

  while (1)
  { unsigned char buff[512];
    struct sockaddr_in sender_info;
    unsigned int si_size=sizeof(sender_info);
    int num=recvfrom(main_socket, buff, sizeof(buff), 0, (struct sockaddr *)&sender_info, &si_size);
    if (num<=0)
    { printf("[num=%d]\n", num);
      sleep(1);
      continue; }
    printf("received (%d): '", num);
    for (int i=0; i<num; i+=1)
    { if (buff[i]>=32 && buff[i]<=126)
        printf("%c", buff[i]);
      else
        printf("\\%03o", buff[i]); }
    printf("'\n"); }

  close(main_socket); }