7.5 La aplicación receive

La aplicación receive captura todos los paquetes enviados al puerto de escucha, extrae el audio que contienen y lo escribe sobre su salida estándar.

7.5.1 receive.c

/******************************************************************************  
 * receive.c -- Receptor de datos a través de UDP.  
 *  
 * Recibe un flujo de datos a través de un puerto y lo copia a la  
 * salida estándard.  
 *  
 * gse. 2005.  
 *****************************************************************************/  
 
/******************************************************************************  
 *  
 * Ficheros cabecera.  
 *  
 *****************************************************************************/  
 
/* Entrada y salida de streams buffereados. */  
#include <stdio.h>  
 
/* Biblioteca de funciones estándar (exit(), EXIT_SUCCESS,  
   EXIT_FAILURE, ...) */  
#include <stdlib.h>  
 
/* Manipulación de cadenas y movimiento de memoria (memset(), ...). */  
#include <string.h>  
 
/* Biblioteca estándar de funciones relacionadas con el sistema  
   operativo Unix (read(), write(), getopt(), ...). */  
#include <unistd.h>  
 
#include <fcntl.h>  
 
/* Sockets. */  
/* Más info en:  
 *  
 * http://www.csce.uark.edu/~aapon/courses/os/examples/concurrentserver.c  
 * http://www.fortunecity.com/skyscraper/arpanet/6/cc.htm  
 * http://beej.us/guide/bgnet/  
 */  
 
/* Tipos de datos primitivos del sistema. */  
#include <sys/types.h>  
 
/* Sockets (socket(), listen(), ...). */  
#include <sys/socket.h>  
 
/* Direcciones IP, opciones y definiciones. */  
#include <netinet/in.h>  
 
/* Servicio de resolución de nombres. */  
#include <netdb.h>  
 
/* Signals (interrupciones) (signal(), SIGINT). */  
#include <signal.h>  /* signal() */  
 
 
/******************************************************************************  
 *  
 * Definiciones.  
 *  
 *****************************************************************************/  
 
/* Número de bytes del buffer de audio. */  
#define BUFFER_SIZE 512  
 
/* Puerto destino de los datagramas. */  
#define LISTENING_PORT 6666  
 
/******************************************************************************  
 *  
 * Variable globales.  
 *  
 *****************************************************************************/  
 
int sd; /* Socket descriptor */  
 
 
/******************************************************************************  
 *  
 * Funciones.  
 *  
 *****************************************************************************/  
 
/* Cuerpo principal del programa. */  
int main(int argc, char *argv[]) {  
  work(argc, argv);  
  return EXIT_SUCCESS;  
}  
 
work(int argc, char *argv[]) {  
 
  /* Si pulsamos CRTL+C, el programa acaba ejecutando la función  
     end(). */  
  void end() {  
    fprintf(stderr,"receive: CTRL+C detected. Exiting ... ");  
    close(sd);  
    fprintf(stderr,"done\n");  
    exit(EXIT_SUCCESS);  
  }  
  signal(SIGINT, end);  //activando la senal SIGINT  
 
  /* Tamaño del buffer. */  
  int buffer_size = BUFFER_SIZE;  
 
  /* Dirección origen por defecto de los datagramas. */  
  char *source_hostname = "localhost";  
 
  /* Puerto destino por defecto de los datagramas. */  
  int listening_port = LISTENING_PORT;  
 
  int c;  
  while ((c = getopt (argc, argv, "b:h:p:")) != -1) {  
    switch (c) {  
    case ’b’:  
      buffer_size = atoi(optarg);  
      break;  
    case ’h’:  
      source_hostname = optarg;  
      break;  
    case ’p’:  
      listening_port = atoi(optarg);  
      break;  
    case ’?’:  
      if (isprint (optopt))  
        fprintf (stderr, "Unknown option ‘-%c’.\n", optopt);  
      else  
        fprintf (stderr,  
                 "Unknown option character ‘\\x%x’.\n",  
                 optopt);  
      return 1;  
    default:  
      abort ();  
    }  
  }  
 
  fprintf(stderr,"%s: buffer size = \"%d\"\n",  
          argv[0],buffer_size);  
  fprintf(stderr,"%s: source hostname = \"%s\"\n",  
          argv[0],source_hostname);  
  fprintf(stderr,"%s: listening port = \"%d\"\n",  
          argv[0],listening_port);  
 
  /* Creamos el socket UDP bloqueante */  
  if((sd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {  
    perror("socket");  
    exit(EXIT_FAILURE);  
  }  
 
  /* Dir IP destino y puerto de escucha. */  
  struct sockaddr_in socket_addr; {  
    /* Usaremos Internet */  
    socket_addr.sin_family = AF_INET;  
    /* IP destino de los datagramas: cualquiera de mis interfaces. */  
    socket_addr.sin_addr.s_addr = htons(INADDR_ANY);  
    /* Puerto de escucha. */  
    socket_addr.sin_port = htons(listening_port);  
    memset(&(socket_addr.sin_zero), ’\0’, 8);  
  }  
 
  /* Cuando hagamos el bind(), si el puerto todavía no ha sido  
     liberado por el SO, no tendremos que esperar a reutilizarlo. */  
  int yes=1;  
  if(setsockopt(sd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int))<0) {  
    perror("setsockopt");  
    exit(EXIT_FAILURE);  
  }  
 
  /* Mapeamos el socket a un puerto de salida y a un interface de red */  
  if(bind(sd, (struct sockaddr *)&socket_addr, sizeof(struct sockaddr)) < 0) {  
    perror("bind");  
    exit(EXIT_FAILURE);  
  }  
 
  char *buffer = (char *)malloc(buffer_size*sizeof(char));  
  for(;;) {  
    /* Buffer con el audio */  
    //char buffer[BUFFER_SIZE];  
    /* Recibimos el datagrama */  
    struct sockaddr_in source_addr;  
    socklen_t addr_len = sizeof(struct sockaddr_in);  
    int bytes_read = recvfrom(sd, (void *)buffer, buffer_size, 0, (struct sockaddr *)&source_addr, &addr_len);  
    /* Escribimos el datagrama a stdout */  
    write(1, (void *)buffer, bytes_read);  
  }  
 
}