--- /dev/null
+#
+# Copyright (C) 2006 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=chillisocket
+PKG_RELEASE:=1
+
+include $(INCLUDE_DIR)/package.mk
+include $(INCLUDE_DIR)/kernel.mk
+
+define Package/chillisocket
+ SECTION:=Testing
+ CATEGORY:=Testing
+# DEPENDS:=
+ TITLE:=Socket library server client
+endef
+
+TARGET_CPPFLAGS := \
+ -I$(STAGING_DIR)/usr/include/ \
+ -I$(LINUX_DIR)/include \
+ -I$(PKG_BUILD_DIR) \
+ $(TARGET_CPPFLAGS)
+
+define Build/Prepare
+ mkdir -p $(PKG_BUILD_DIR)
+ $(CP) ./src/* $(PKG_BUILD_DIR)/
+endef
+
+define Build/Compile
+ CFLAGS="$(TARGET_CPPFLAGS) $(TARGET_CFLAGS)" \
+ $(MAKE) -C $(PKG_BUILD_DIR) \
+ $(TARGET_CONFIGURE_OPTS) \
+ LIBS="$(TARGET_LDFLAGS) -lm"
+endef
+
+define Package/chillisocket/install
+ $(INSTALL_DIR) $(1)/bin
+# $(INSTALL_BIN) $(PKG_BUILD_DIR)/libChSocket.a $(1)/bin/libChSocket.a
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/servselect $(1)/bin/servselect
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/clientselect $(1)/bin/clientselect
+endef
+
+$(eval $(call BuildPackage,chillisocket))
--- /dev/null
+ifndef CFLAGS
+CFLAGS = -O2 -g -I ../src
+endif
+VERSION=0.1
+
+LIBS=-lnl
+
+# Ficheros objeto que van dentro de la minilibrería.
+LIBCHSOCK=\
+ Socket_Servidor.o\
+ Socket_Cliente.o\
+ Socket.o
+
+all: servselect clientselect server_socket
+# clientselect libChSocket.a
+
+%.o: %.c
+ $(CC) $(CFLAGS) -c -o $@ $^
+
+#libChSocket.a : libChSocket.a($(LIBCHSOCK))
+
+servselect: servselect.o Socket_Servidor.o Socket.o
+ $(CC) $(LDFLAGS) -o $@ $^ $(LIBS)
+
+clientselect: clientselect.o Socket.o Socket_Cliente.o
+ $(CC) $(LDFLAGS) -o $@ $^ $(LIBS)
+# cc clientselect.c -I$(LIBCHSOCKET) -L$(LIBCHSOCKET) -lChSocket -o clientselect
+
+server_socket: server_socket.o remotectrl.o
+ $(CC) $(LDFLAGS) -o $@ $^ $(LIBS)
--- /dev/null
+prefix=/usr
+DESTDIR=
+
+COPTS=-O2
+WOPTS=-pedantic -Werror -Wall
+FPIC=-fPIC
+CFLAGS=$(COPTS) $(WOPTS) -std=gnu99
+
+AR=ar
+CC=gcc
+RANLIB=ranlib
+INSTALL=install
+MKDIR=mkdir
+
+LINK=$(CC)
+SHLIB_EXT=so
+SHLIB_FLAGS=-shared -Wl,-soname,$(SHLIB_FILE)
--- /dev/null
+/*
+* Javier Abellan, 20 Jun 2000
+*
+* Funciones de lectura y escritura en sockets
+*
+* MODIFICACIONES:
+* 4 Septiembre 2003: Añadidas funciones para sockets UDP.
+*/
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <sys/un.h>
+#include <netdb.h>
+#include <unistd.h>
+#include <errno.h>
+#include <stdio.h>
+
+#include "Socket.h"
+
+#define BUFFER_SIZE 13
+
+int ReadTcpSocket (int fd, char **Datos)
+{
+ int Leido = 0;
+ struct head_t *head;
+ int Aux=0;
+ char buffer[BUFFER_SIZE];
+ char *message;
+ message = malloc(BUFFER_SIZE);
+ while (1){
+ bzero(buffer, BUFFER_SIZE);
+ Aux = read(fd, buffer, BUFFER_SIZE-1);
+ if (Leido==0){
+ message = memcpy(message, buffer, Aux);
+ head = malloc(sizeof(struct head_t));
+ head = memcpy(head,buffer,Aux);
+ } else {
+ message = realloc(message,(strlen(message)+Aux));
+ if (Aux == BUFFER_SIZE-1)
+ message = strcat(message,buffer);
+ else
+ message = strncat(message,buffer,Aux);
+ }
+ Leido += Aux;
+
+printf("msg=%s Leido=%d\n", message, Leido);
+ if (Aux < BUFFER_SIZE-1 || Leido == head->len )
+ break;
+ }
+ *Datos=realloc(*Datos,Leido+1);
+ memcpy(*Datos,head,sizeof(struct head_t));
+ memcpy(*Datos+12, message, Leido);
+ return Leido;
+}
+
+int WriteTcpSocket(int fd, int type, int command, char *data){
+ int Escrito = 0;
+ int Aux = 0;
+
+ int Longitud = (sizeof(int)*3)+strlen((char *)data);
+ struct s_msg *Datos;
+ Datos = malloc(Longitud);
+ Datos->type = type;
+ Datos->command = command;
+ Datos->len = Longitud;
+ strcpy(Datos->data, data);
+ printf("Longitud=%d convertido Type=%d Command=%d Len=%d Data=%s\n",Longitud, Datos->type, Datos->command, Datos->len, Datos->data);
+ printf("Longitud=%d int=%d\n", Longitud,sizeof(int));
+/*
+ if ((fd == -1) || (Datos == NULL) || (Longitud < 1))
+ return -1;
+
+*/
+//printf("Data:%s", *Datos);
+ while (Escrito < Longitud)
+ {
+ Aux = write (fd, Datos + Escrito, Longitud - Escrito);
+ if (Aux > 0)
+ {
+ Escrito = Escrito + Aux;
+ }
+ else
+ {
+ if (Aux == 0)
+ return Escrito;
+ else
+ return -1;
+ }
+ }
+ free(Datos);
+ return Escrito;
+}
+
+/*
+* Lee datos del socket. Supone que se le pasa un buffer con hueco
+* suficiente para los datos. Devuelve el numero de bytes leidos o
+* 0 si se cierra fichero o -1 si hay error.
+*/
+int Lee_Socket1 (int fd, char *Datos, int Longitud)
+{
+ int Leido = 0;
+ int Aux = 0;
+
+
+ /*
+ * Comprobacion de que los parametros de entrada son correctos
+ */
+ if ((fd == -1) || (Datos == NULL) || (Longitud < 1))
+ return -1;
+
+ /*
+ * Mientras no hayamos leido todos los datos solicitados
+ */
+
+ while (Leido < Longitud)
+ {
+ Aux = read (fd, Datos + Leido, Longitud - Leido);
+ if (Aux > 0)
+ {
+ /*
+ * Si hemos conseguido leer datos, incrementamos la variable
+ * que contiene los datos leidos hasta el momento
+ */
+ Leido = Leido + Aux;
+ }
+ else
+ {
+ /*
+ * Si read devuelve 0, es que se ha cerrado el socket. Devolvemos
+ * los caracteres leidos hasta ese momento
+ */
+ if (Aux == 0)
+ return Leido;
+ if (Aux == -1)
+ {
+ /*
+ * En caso de error, la variable errno nos indica el tipo
+ * de error.
+ * El error EINTR se produce si ha habido alguna
+ * interrupcion del sistema antes de leer ningun dato. No
+ * es un error realmente.
+ * El error EGAIN significa que el socket no esta disponible
+ * de momento, que lo intentemos dentro de un rato.
+ * Ambos errores se tratan con una espera de 100 microsegundos
+ * y se vuelve a intentar.
+ * El resto de los posibles errores provocan que salgamos de
+ * la funcion con error.
+ */
+ switch (errno)
+ {
+ case EINTR:
+ case EAGAIN:
+ usleep (100);
+ break;
+ default:
+ return -1;
+ }
+ }
+ }
+ }
+
+ /*
+ * Se devuelve el total de los caracteres leidos
+ */
+ return Leido;
+}
+
+/*
+* Escribe dato en el socket cliente. Devuelve numero de bytes escritos,
+* o -1 si hay error.
+*/
+int Escribe_Socket (int fd, char *Datos, int Longitud)
+{
+ int Escrito = 0;
+ int Aux = 0;
+
+ /*
+ * Comprobacion de los parametros de entrada
+ */
+ if ((fd == -1) || (Datos == NULL) || (Longitud < 1))
+ return -1;
+
+ /*
+ * Bucle hasta que hayamos escrito todos los caracteres que nos han
+ * indicado.
+ */
+ while (Escrito < Longitud)
+ {
+ Aux = write (fd, Datos + Escrito, Longitud - Escrito);
+ if (Aux > 0)
+ {
+ /*
+ * Si hemos conseguido escribir caracteres, se actualiza la
+ * variable Escrito
+ */
+ Escrito = Escrito + Aux;
+ }
+ else
+ {
+ /*
+ * Si se ha cerrado el socket, devolvemos el numero de caracteres
+ * leidos.
+ * Si ha habido error, devolvemos -1
+ */
+ if (Aux == 0)
+ return Escrito;
+ else
+ return -1;
+ }
+ }
+
+ /*
+ * Devolvemos el total de caracteres leidos
+ */
+ return Escrito;
+}
+
+/**
+ * Lee un mensaje de un socket udp. Los parámetros que se pasan son:
+ * - Descriptor fd del socket del que se quiere leer.
+ * - Estructura Remoto, en la que se devolverá los datos del que ha enviado el
+ * mensaje que acabamos de leer.
+ * - Longitud_Remoto de la estructura anterior. Debe pasarse relleno con el tamaño
+ * de Remoto y se devolverá rellena con el tamaño de los datos en Remoto.
+ * - Buffer de Datos donde se quiere que aparezca el mensaje.
+ * - Longitud_Datos del buffer anterior.
+ *
+ * Devuelve el número de bytes leidos o -1 en caso de error.
+ */
+int Lee_Socket_Udp (
+ int fd, struct sockaddr *Remoto, socklen_t *Longitud_Remoto,
+ char *Datos, int Longitud_Datos)
+{
+ int Leido = 0;
+ int Aux = 0;
+
+ /*
+ * Comprobacion de que los parametros de entrada son correctos
+ */
+ if ((fd == -1) || (Datos == NULL) || (Longitud_Datos < 1)
+ || (Remoto == NULL) || (Longitud_Remoto == NULL))
+ {
+ return -1;
+ }
+
+ /*
+ * Mientras no hayamos leido todos los datos solicitados
+ */
+ while (Leido < Longitud_Datos)
+ {
+ Aux = recvfrom (fd, Datos + Leido, Longitud_Datos - Leido, 0,
+ Remoto, Longitud_Remoto);
+
+ if (Aux > 0)
+ {
+ /*
+ * Si hemos conseguido leer datos, incrementamos la variable
+ * que contiene los datos leidos hasta el momento
+ */
+ Leido = Leido + Aux;
+ }
+ else
+ {
+ /*
+ * Si read devuelve 0, es que se ha cerrado el socket. Devolvemos
+ * los caracteres leidos hasta ese momento
+ */
+ if (Aux == 0)
+ return Leido;
+ if (Aux == -1)
+ {
+ /*
+ * En caso de error, la variable errno nos indica el tipo
+ * de error.
+ * El error EINTR se produce si ha habido alguna
+ * interrupcion del sistema antes de leer ningun dato. No
+ * es un error realmente.
+ * El error EGAIN significa que el socket no esta disponible
+ * de momento, que lo intentemos dentro de un rato.
+ * Ambos errores se tratan con una espera de 100 microsegundos
+ * y se vuelve a intentar.
+ * El resto de los posibles errores provocan que salgamos de
+ * la funcion con error.
+ */
+ switch (errno)
+ {
+ case EINTR:
+ case EAGAIN:
+ usleep (100);
+ break;
+ default:
+ return -1;
+ }
+ }
+ }
+ }
+
+ /*
+ * Se devuelve el total de los caracteres leidos
+ */
+ return Leido;
+}
+
+/**
+* Escribe dato en el socket cliente. Devuelve numero de bytes escritos,
+* o -1 si hay error.
+* - fd es el descriptor del socket.
+* - Remoto es el destinatario del mensaje, a quién se lo queremos enviar.
+* - Longitud_Remoto es el tamaño de Remoto en bytes.
+* - Datos es el mensaje que queremos enviar.
+* - Longitud_Datos es el tamaño del mensaje en bytes.
+*/
+int Escribe_Socket_Udp (int fd, struct sockaddr *Remoto,
+ socklen_t Longitud_Remoto, char *Datos, int Longitud_Datos)
+{
+ int Escrito = 0;
+ int Aux = 0;
+
+ /*
+ * Comprobacion de los parametros de entrada
+ */
+ if ((fd == -1) || (Datos == NULL) || (Longitud_Datos < 1)
+ || (Remoto == NULL) )
+ {
+ return -1;
+ }
+
+ /*
+ * Bucle hasta que hayamos escrito todos los caracteres que nos han
+ * indicado.
+ */
+ while (Escrito < Longitud_Datos)
+ {
+ Aux = sendto (fd, Datos + Escrito, Longitud_Datos - Escrito, 0,
+ Remoto, Longitud_Remoto);
+
+ if (Aux > 0)
+ {
+ /*
+ * Si hemos conseguido escribir caracteres, se actualiza la
+ * variable Escrito
+ */
+ Escrito = Escrito + Aux;
+ }
+ else
+ {
+ /*
+ * Si se ha cerrado el socket, devolvemos el numero de caracteres
+ * leidos.
+ * Si ha habido error, devolvemos -1
+ */
+ if (Aux == 0)
+ return Escrito;
+ else
+ {
+ return -1;
+ }
+ }
+ }
+
+ /*
+ * Devolvemos el total de caracteres leidos
+ */
+ return Escrito;
+}
+
+
+/**
+ * Rellena una estructura sockaddr_in con los datos que se le pasan. Esta estrutura es
+ * útil para el envio o recepción de mensajes por sockets Udp o para abrir conexiones.
+ * Se le pasa el host. Puede ser NULL (para abrir socket servidor Udp o para recepción de
+ * mensajes de cualquier host).
+ * Se le pasa el servicio. Puede ser NULL (para abrir socket cliente Udp).
+ * Se le pasa una estructura sockaddr_in que devolverá rellena.
+ * Se le pasa una Longitud. Debe contener el tamaño de la estructura sockaddr_in y
+ * devolverá el tamaño de la estructura una vez rellena.
+ * Devuelve -1 en caso de error.
+ */
+int Dame_Direccion_Udp (char *Host, char *Servicio, struct sockaddr_in *Servidor,
+ int *Longitud_Servidor)
+{
+ struct servent *Puerto;
+ struct hostent *Maquina;
+
+ /* Comprobación de parámetros */
+ if (Servidor == NULL) return -1;
+
+ /* Relleno del primer campo de la estructura */
+ Servidor->sin_family = AF_INET;
+
+ /* Si nos han pasado un host ... */
+ if (Host != NULL)
+ {
+ /* ... obtenemos la dirección del host y la ponemos en la estructura */
+ Maquina = gethostbyname (Host);
+ if (Maquina == NULL)
+ return -1;
+
+ Servidor->sin_addr.s_addr = ((struct in_addr *)(Maquina->h_addr))->s_addr;
+ }
+ else
+ /* Si no nos han pasado un host, ponemos cualquier host. */
+ Servidor->sin_addr.s_addr = INADDR_ANY;
+
+ /* Si servicio en NULL, hacemos que el puerto lo eliga el sistema operativo
+ libremente.*/
+ if (Servicio == NULL)
+ Servidor->sin_port = 0;
+ else
+ {
+ /* Si el servicio no es NULL, lo obtenemos. */
+ Puerto = getservbyname (Servicio, "udp");
+ if (Puerto == NULL)
+ return -1;
+ Servidor->sin_port = Puerto->s_port;
+ }
+}
--- /dev/null
+/**
+ * Javier Abellán, 20 Junio 2000
+ *
+ * Funciones de lectura y escritura de la librería de sockets.
+ *
+ * MODIFICACIONES:
+ * 4 de Septiembre de 2003. Añadidas funciones Lee_Socket_Udp(),
+ * Escribe_Socket_Udp() y Dame_Direccion_Udp()
+ */
+#ifndef _SOCKET_H
+#define _SOCKET_H
+
+#include <sys/socket.h>
+
+/*
+enum
+{
+ MSG_OK = 0,
+ MSG_QRY,
+ MSG_START,
+ MSG_PART,
+ MSG_END,
+};
+int ReadTcpSocket(int fd, char **msg);
+int WriteTcpSocket(int fd, struct *Datos);
+*/
+struct head_t {
+ int type;
+ int command;
+ int len;
+};
+
+struct s_msg {
+ int type;
+ int command;
+ int len;
+ char data[30];
+};
+
+int ReadTcpSocket (int fd, char **Datos);
+int WriteTcpSocket (int fd, int type, int command, char *Datos);
+
+/** Lee Datos de tamaño Longitud de un socket cuyo descriptor es fd.
+ * Devuelve el numero de bytes leidos o -1 si ha habido error */
+int Lee_Socket1 (int fd, char *Datos, int Longitud);
+
+/** Envia Datos de tamaño Longitud por el socket cuyo descriptor es fd.
+ * Devuelve el número de bytes escritos o -1 si ha habido error. */
+int Escribe_Socket (int fd, char *Datos, int Longitud);
+
+/** Lee un mensaje de un socket UDP.
+ * Se le pasa el descriptor fd del socket que atiende los mensajes.
+ * Se le pasa uns estructura sockaddr que nos devolverá rellena con los datos del que nos
+ * ha enviado el mensaje, de forma que podamos responderle.
+ * Se le pasa el tamaño de la estructura Remoto. En la misma variable nos devolverá el
+ * tamaño de los datos devueltos.
+ * Se le pasa un buffer de datos para el mensaje y el tamaño en bytes que deseamos leer.
+ */
+int Lee_Socket_Udp (int fd, struct sockaddr *Remoto, socklen_t *Longitud_Remoto,
+ char *Datos, int Longitud_Datos);
+
+/** Envia un mensaje por un socket UDP
+ * Se le pasa el descriptor de socket por el que debe enviar.
+ * Se le pasa el destinatario del mensaje en una estructura Remoto.
+ * Se le pasa el tamaño de dicha estructura en Longitud_Remoto.
+ * Se le pasa el buffer de datos que debe enviar en Datos.
+ * Se le pasa la longitud del buffer de datos en Longitud.
+ * Devuelve el número de bytes enviados o -1 si ha habido algún error.
+ */
+int Escribe_Socket_Udp (int fd, struct sockaddr *Remoto,
+ socklen_t Longitud_Remoto, char *Datos, int Longitud);
+
+/**
+ * Rellena una estructura sockaddr_in con los datos que se le pasan. Esta estrutura es
+ * útil para el envio o recepción de mensajes por sockets Udp o para abrir conexiones.
+ * Se le pasa el host. Puede ser NULL (para abrir socket servidor Udp o para recepción de
+ * mensajes de cualquier host).
+ * Se le pasa el servicio. Puede ser NULL (para abrir socket cliente Udp).
+ * Se le pasa una estructura sockaddr_in que devolverá rellena.
+ * Se le pasa una Longitud. Debe contener el tamaño de la estructura sockaddr_in y
+ * devolverá el tamaño de la estructura una vez rellena.
+ * Devuelve -1 en caso de error.
+ */
+int Dame_Direccion_Udp (char *Host, char *Servicio, struct sockaddr_in *Servidor,
+ int *Longitud);
+#endif
--- /dev/null
+/* Javier Abellán, 20 Junio 2000
+ *
+ * Funciones para abrir/establecer sockets de un cliente con un servidor.
+ *
+ * MODIFICACIONES:
+ * 4 Septiembre 2003. Añadida función Abre_Conexion_Udp()
+ */
+
+
+/*
+* Includes del sistema
+*/
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <netinet/in.h>
+#include <netdb.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+
+/*
+* Conecta con un servidor Unix, en la misma maquina.
+* Devuelve descriptor de socket si todo es correcto, -1 si hay error.
+*/
+int Abre_Conexion_Unix (char *Servicio)
+{
+ struct sockaddr_un Direccion;
+ int Descriptor;
+
+ strcpy (Direccion.sun_path, Servicio);
+ Direccion.sun_family = AF_UNIX;
+
+ /* Se abre el descriptor del socket */
+ Descriptor = socket (AF_UNIX, SOCK_STREAM, 0);
+ if (Descriptor == -1)
+ return -1;
+
+ /* Se establece la conexion.
+ * Devuelve 0 si todo va bien, -1 en caso de error */
+ if (connect (
+ Descriptor,
+ (struct sockaddr *)&Direccion,
+ strlen (Direccion.sun_path) + sizeof (Direccion.sun_family)) == -1)
+ {
+ return -1;
+ }
+
+ return Descriptor;
+}
+
+/*
+* Conecta con un servidor remoto a traves de socket INET
+*/
+int Abre_Conexion_Inet (
+ char *Host_Servidor,
+ char *Servicio)
+{
+ struct sockaddr_in Direccion;
+ struct servent *Puerto;
+ struct hostent *Host;
+ int Descriptor;
+
+/*
+ Puerto = getservbyname (Servicio, "tcp");
+ Puerto = 15557;
+ if (Puerto == NULL)
+ return -1;
+*/
+
+ Host = gethostbyname (Host_Servidor);
+ if (Host == NULL)
+ return -1;
+
+ Direccion.sin_family = AF_INET;
+ Direccion.sin_addr.s_addr = ((struct in_addr *)(Host->h_addr))->s_addr;
+// Direccion.sin_port = Puerto->s_port;
+ Direccion.sin_port = 15557;
+
+ Descriptor = socket (AF_INET, SOCK_STREAM, 0);
+ if (Descriptor == -1)
+ return -1;
+
+ if (connect (
+ Descriptor,
+ (struct sockaddr *)&Direccion,
+ sizeof (Direccion)) == -1)
+ {
+ return -1;
+ }
+
+ return Descriptor;
+}
+
+
+/*
+ * Prepara un socket para un cliente UDP.
+ * Asocia un socket a un cliente UDP en un servicio cualquiera elegido por el sistema,
+ * de forma que el cliente tenga un sitio por el que enviar y recibir mensajes.
+ * Devuelve el descriptor del socket que debe usar o -1 si ha habido algún error.
+ */
+int Abre_Conexion_Udp ()
+{
+ struct sockaddr_in Direccion;
+ int Descriptor;
+
+ /* Se abre el socket UDP (DataGRAM) */
+ Descriptor = socket (AF_INET, SOCK_DGRAM, 0);
+ if (Descriptor == -1)
+ {
+ return -1;
+ }
+
+ /* Se rellena la estructura de datos necesaria para hacer el bind() */
+ Direccion.sin_family = AF_INET; /* Socket inet */
+ Direccion.sin_addr.s_addr = htonl(INADDR_ANY); /* Cualquier dirección IP */
+ Direccion.sin_port = htons(0); /* Dejamos que linux eliga el servicio */
+
+ /* Se hace el bind() */
+ if (bind (
+ Descriptor,
+ (struct sockaddr *)&Direccion,
+ sizeof (Direccion)) == -1)
+ {
+ close (Descriptor);
+ return -1;
+ }
+
+ /* Se devuelve el Descriptor */
+ return Descriptor;
+}
--- /dev/null
+/*
+ * Javier Abellán. 14 Abril 2003
+ *
+ * Funciones para que un cliente pueda abrir sockets con un servidor.
+ */
+#ifndef _SOCKET_CLIENTE_H
+#define _SOCKET_CLIENTE_H
+
+#include <sys/socket.h>
+
+/**
+ * Abre un socket UNIX con un servidor que esté en la misma máquina y que atienda al
+ * servicio de nombre Servicio.
+ */
+int Abre_Conexion_Unix (char *Servicio);
+
+/**
+ * Abre un socket INET con un servidor que esté corriendo en Host_Servidor y que atienda
+ * al servicio cuyo nombre es Servicio.
+ * Host_Servidor debe estar dado de alta en /etc/hosts.
+ * Servicio debe estar dado de alta en /etc/services como tcp.
+ */
+int Abre_Conexion_Inet (char *Host_Servidor, char *Servicio);
+
+#endif
--- /dev/null
+/*
+* Javier Abellan, 20 Jun 2000
+*
+* Funciones para la apertura de un socket servidor y la conexion con sus
+* clientes
+*
+* MODIFICACIONES:
+* 4 Septiembre 2003: Añadida función Abre_Socket_Udp()
+*/
+
+/* Includes del sistema */
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <netinet/in.h>
+#include <netdb.h>
+#include <unistd.h>
+#include <errno.h>
+
+/*
+* Abre socket servidor UNIX. Se le pasa el servicio que se desea atender.
+* Deja el socket preparado
+* para aceptar conexiones de clientes.
+* Devuelve el descritor del socket servidor, que se debera pasar
+* a la funcion Acepta_Conexion_Cliente(). Devuelve -1 en caso de error
+*/
+int Abre_Socket_Unix (char *Servicio)
+{
+ struct sockaddr_un Direccion;
+ int Descriptor;
+
+ /*
+ * Se abre el socket
+ */
+ Descriptor = socket (AF_UNIX, SOCK_STREAM, 0);
+ if (Descriptor == -1)
+ return -1;
+
+ /*
+ * Se rellenan en la estructura Direccion los datos necesarios para
+ * poder llamar a la funcion bind()
+ */
+ strcpy (Direccion.sun_path, Servicio);
+ Direccion.sun_family = AF_UNIX;
+
+ if (bind (
+ Descriptor,
+ (struct sockaddr *)&Direccion,
+ strlen (Direccion.sun_path) + sizeof (Direccion.sun_family)) == -1)
+ {
+ /*
+ * En caso de error cerramos el socket y devolvemos error
+ */
+ close (Descriptor);
+ return -1;
+ }
+
+ /*
+ * Avisamos al sistema que comience a atender peticiones de clientes.
+ */
+ if (listen (Descriptor, 1) == -1)
+ {
+ close (Descriptor);
+ return -1;
+ }
+
+ /*
+ * Se devuelve el descriptor del socket servidor
+ */
+ return Descriptor;
+}
+
+/*
+* Se le pasa un socket de servidor y acepta en el una conexion de cliente.
+* devuelve el descriptor del socket del cliente o -1 si hay problemas.
+* Esta funcion vale para socket AF_INET o AF_UNIX.
+*/
+int Acepta_Conexion_Cliente (int Descriptor)
+{
+ socklen_t Longitud_Cliente;
+ struct sockaddr Cliente;
+ int Hijo;
+
+ /*
+ * La llamada a la funcion accept requiere que el parametro
+ * Longitud_Cliente contenga inicialmente el tamano de la
+ * estructura Cliente que se le pase. A la vuelta de la
+ * funcion, esta variable contiene la longitud de la informacion
+ * util devuelta en Cliente
+ */
+ Longitud_Cliente = sizeof (Cliente);
+ Hijo = accept (Descriptor, &Cliente, &Longitud_Cliente);
+ if (Hijo == -1)
+ return -1;
+
+ /*
+ * Se devuelve el descriptor en el que esta "enchufado" el cliente.
+ */
+ return Hijo;
+}
+
+/*
+* Abre un socket servidor de tipo AF_INET. Devuelve el descriptor
+* del socket o -1 si hay probleamas
+* Se pasa como parametro el nombre del servicio. Debe estar dado
+* de alta en el fichero /etc/services
+*/
+int Abre_Socket_Inet (char *Servicio)
+{
+ struct sockaddr_in Direccion;
+ struct sockaddr Cliente;
+ socklen_t Longitud_Cliente;
+ struct servent *Puerto;
+ int Descriptor;
+
+ /*
+ * se abre el socket
+ */
+ Descriptor = socket (AF_INET, SOCK_STREAM, 0);
+ if (Descriptor == -1)
+ return -1;
+
+ /*
+ * Se obtiene el servicio del fichero /etc/services
+ */
+/*
+ Puerto = getservbyname (Servicio, "tcp");
+
+ Puerto = 15557;
+
+ if (Puerto == NULL)
+ return -1;
+*/
+ /*
+ * Se rellenan los campos de la estructura Direccion, necesaria
+ * para la llamada a la funcion bind()
+ */
+/*
+ struct hostent *Host;
+ Host = gethostbyname ("192.168.1.1");
+ if (Host == NULL)
+ return -1;
+*/
+
+ Direccion.sin_family = AF_INET;
+// Direccion.sin_port = Puerto->s_port;
+ Direccion.sin_port = htons(15557);
+ Direccion.sin_addr.s_addr =INADDR_ANY;
+// Direccion.sin_addr.s_addr = ((struct in_addr *)(Host->h_addr))->s_addr;
+ if (bind (
+ Descriptor,
+ (struct sockaddr *)&Direccion,
+ sizeof(struct sockaddr)) == -1)
+ {
+ close (Descriptor);
+ return -1;
+ }
+
+ /*
+ * Se avisa al sistema que comience a atender llamadas de clientes
+ */
+ if (listen (Descriptor, 1) == -1)
+ {
+ close (Descriptor);
+ return -1;
+ }
+
+ /*
+ * Se devuelve el descriptor del socket servidor
+ */
+ return Descriptor;
+}
+
+/**
+ * Abre un socket inet de udp.
+ * Se le pasa el nombre de servicio del socket al que debe atender.
+ * Devuelve el descriptor del socket abierto o -1 si ha habido algún error.
+ */
+int Abre_Socket_Udp (char *Servicio)
+{
+ struct sockaddr_in Direccion;
+ struct servent *Puerto = NULL;
+ int Descriptor;
+
+ /*
+ * se abre el socket
+ */
+ Descriptor = socket (AF_INET, SOCK_DGRAM, 0);
+ if (Descriptor == -1)
+ {
+ return -1;
+ }
+
+ /*
+ * Se obtiene el servicio del fichero /etc/services
+ */
+ Puerto = getservbyname (Servicio, "udp");
+ if (Puerto == NULL)
+ {
+ return -1;
+ }
+
+ /*
+ * Se rellenan los campos de la estructura Direccion, necesaria
+ * para la llamada a la funcion bind() y se llama a esta.
+ */
+ Direccion.sin_family = AF_INET;
+ Direccion.sin_port = Puerto->s_port;
+ Direccion.sin_addr.s_addr = INADDR_ANY;
+
+ if (bind (
+ Descriptor,
+ (struct sockaddr *)&Direccion,
+ sizeof (Direccion)) == -1)
+ {
+ close (Descriptor);
+ return -1;
+ }
+
+ /*
+ * Se devuelve el descriptor del socket servidor
+ */
+ return Descriptor;
+}
--- /dev/null
+/**
+ * Javier Abellán. 14 Abril 2003
+ *
+ * Funciones para que un servidor puede abrir sockets para atender un servicio y aceptar
+ * conexiones de un cliente.
+ */
+#ifndef _SOCKET_SERVIDOR_H
+#define _SOCKET_SERVIDOR_H
+
+/**
+ * Abre un socket INET para atender al servicio cuyo nombre es Servicio.
+ * El Servicio debe estar dado de alta en /etc/services como tcp.
+ * Devuelve el descriptor del socket que atiende a ese servicio o -1 si ha habido error.
+ */
+int Abre_Socket_Inet (char *Servicio);
+
+
+/**
+ * Abre un socket UDP para atender al servicio cuyo nombre es Servicio.
+ * El Servicio debe estar dado de alta en /etc/services como udp.
+ * Devuelve el descriptor del socket que atiende a ese servicio o -1 si ha habido error.
+ */
+int Abre_Socket_Udp (char *Servicio);
+
+
+/**
+ * Abre un socket UNIX para atender al servicio cuyo nombre es Servicio.
+ * Devuelve el descriptor del socket que atiende a ese servicio o -1 si ha habido error.
+ */
+int Abre_Socket_Unix (char *Servicio);
+
+/**
+ * Acepta un cliente para un socket INET.
+ * Devuelve el descriptor de la conexión con el cliente o -1 si ha habido error.
+ */
+int Acepta_Conexion_Cliente (int Descriptor);
+
+#endif
--- /dev/null
+/*
+ * Javier Abellán. 14 de Abril de 2003
+ *
+ * Ejemplo de como un servidor puede manejar varios clientes con select().
+ * Este programa hace de cliente de dicho servidor.
+ */
+#include "Socket.h"
+#include "Socket_Cliente.h"
+
+/* Programa principal. Abre la conexión, recibe su número de cliente y
+ * luego envía dicho número cada segundo */
+main()
+{
+ int sock; /* descriptor de conexión con el servidor */
+ struct s_msg *buffer; /* buffer de lectura de datos procedentes del servidor */
+ int error; /* error de lectura por el socket */
+ buffer = malloc(sizeof(struct s_msg));
+ /* Se abre una conexión con el servidor */
+ sock = Abre_Conexion_Inet ("localhost", "cpp_java");
+
+ /* Se lee el número de cliente, dato que nos da el servidor. Se escribe
+ * dicho número en pantalla.*/
+ error = ReadTcpSocket (sock, &buffer);
+// struct s_msg Datos;
+// *Datos = malloc(sizeof struct s_msg);
+// error = ReadTcpSocket (sock, &Datos);
+// printf("%d %d %s\n",Datos.type, Datos.command, Datos.data);
+ /* Si ha habido error de lectura lo indicamos y salimos */
+ if (error < 1)
+ {
+ printf ("Me han cerrado la conexión\n");
+ exit(-1);
+ }
+printf("Se leyeron %d bytes\n", error);
+ /* Se escribe el número de cliente que nos ha enviado el servidor */
+ printf ("type=%d\ncommand=%d\nlen=%d\ndata=%s\n", buffer->type, buffer->command, buffer->len, buffer->data);
+ printf ("Soy cliente\n%s\n", buffer);
+
+ /* Bucle infinito. Envia al servidor el número de cliente y espera un
+ * segundo */
+// while (1)
+// {
+// Escribe_Socket (sock, (char *)&buffer, sizeof(int));
+// sleep (1);
+// }
+}
+
--- /dev/null
+#include "remotectrl.h"
+
+int write_msg( struct rmt_socket_t *sckHnd, uint32_t id, uint32_t extra, char *message ){
+ msg_head_t header;
+ int rslt;
+ header.id = id;
+ header.len = strlen(message);
+ header.extra = extra;
+ rslt = send(sckHnd->fd,&header,sizeof(struct msg_head_t),0);
+ if (rslt != -1 && header.len > 0) {
+ sckHnd->Tx += rslt;
+ rslt = send(sckHnd->fd, message, header.len, 0);
+ if (rslt > 0)
+ {
+ sckHnd->Tx += rslt;
+ rslt += sizeof(struct msg_head_t);
+ }
+ }
+ return rslt;
+}
+
+int read_msg( struct rmt_socket_t *sckHnd, msg_head_t *head, char **message )
+{
+ msg_head_t header;
+ int rslt;
+ char *buffer;
+ int reading = 0;
+ int aux = 0;
+ rslt = recv(sckHnd->fd, head, sizeof(struct msg_head_t), 0);
+// printf("head->id=%d head->extra=%d head->len=%d\n",head->id,head->extra,head->len);
+ if (rslt == sizeof(struct msg_head_t) ) {
+ sckHnd->Rx += rslt;
+ buffer = malloc(head->len+1);
+ while ( reading < head->len ){
+ memset(buffer,'\0', head->len+1);
+ aux = recv(sckHnd->fd, buffer, head->len, 0);
+ switch ( aux ) {
+ case -1:
+ switch (errno){
+ case EINTR:
+ case EAGAIN:
+ usleep (100);
+ break;
+ default:
+ return -1;
+ }
+ break;
+ case 0: // mean socket was closed
+ sckHnd->Rx += reading;
+ return reading;
+ break;
+ break;
+ default:
+ if (reading == 0)
+ *message=malloc(aux+1);
+ else
+ *message=(char*)realloc(*message,(reading+aux+1)*sizeof(char));
+ memcpy(*message+reading, buffer, aux);
+ reading += aux;
+ }
+ }
+ free(buffer);
+ sckHnd->Rx += reading;
+ reading += rslt;
+ return reading;
+ }
+ return rslt;
+}
+
+void rmtctrl_srv(struct rmt_socket_t srv, struct rmt_socket_t *client, int *activeClients)
+{
+ fd_set fdRead;
+ int maxHnd;
+ int i;
+ struct timeval nowait;
+ memset((char *)&nowait,0,sizeof(nowait));
+
+ rmtctrl_cleanClients(client, activeClients);
+ FD_ZERO (&fdRead);
+ FD_SET (srv.fd, &fdRead);
+
+ for (i=0; i<*activeClients; i++)
+ FD_SET (client[i].fd, &fdRead);
+
+ maxHnd = rmtctrl_maxValue (client, *activeClients);
+
+ if (maxHnd < srv.fd)
+ maxHnd = srv.fd;
+
+ select (maxHnd + 1, &fdRead, NULL, NULL,&nowait);
+ for (i=0; i<*activeClients; i++)
+ {
+ if (FD_ISSET (client[i].fd, &fdRead))
+ {
+ rmtctrl_msg_proccess(&client[i]);
+ }
+ }
+ if (FD_ISSET (srv.fd, &fdRead))
+ rmtctrl_newClient(srv,client, &(*activeClients));
+}
+
+void rmtctrl_msg_proccess(struct rmt_socket_t *client)
+{
+ msg_head_t header;
+ char *msg=NULL;
+ int rslt;
+ rslt = read_msg(client,&header,&msg);
+ if (rslt > 0)
+ {
+ switch (header.id)
+ {
+ case QRY_STATUS:
+ rslt = write_msg(client,MSG_END,0, "Bienvenido a mi servidor.\nStatus\n" );
+ break;
+ case QRY_CONNECTED_LIST:
+ rslt = write_msg(client,MSG_START,0, "List of Connected\n" );
+ rslt = write_msg(client,MSG_PART,0, "Username IPAddrs Status\n" );
+ rslt = write_msg(client,MSG_PART,0, "pepe1 198.164.234.224 Authenticated\n" );
+ rslt = write_msg(client,MSG_PART,0, "pepe2 198.164.234.220 Authenticated\n" );
+ rslt = write_msg(client,MSG_PART,0, "pepe3 198.164.234.221 Authenticated\n" );
+ rslt = write_msg(client,MSG_PART,0, "pepe4 198.164.234.223 Authenticated\n" );
+ rslt = write_msg(client,MSG_PART,0, "pepe5 198.164.234.227 Authenticated\n" );
+ rslt = write_msg(client,MSG_END,0, "pepe6 198.164.234.224 Authenticated\n" );
+ break;
+ default:
+ rslt = write_msg(client,MSG_END,9, "Unknow command.\n" );
+ }
+ }
+ else
+ {
+ printf("Desde %s se recibieron %d bytes y se enviaron %d bytes\n",inet_ntoa(client->addr.sin_addr),client->Rx,client->Tx);
+ close(client->fd); /* cierra fd_rmt_client */
+ printf("Client cerro conexión desde %s\n",inet_ntoa(client->addr.sin_addr) );
+ client->fd = -1;
+ }
+ if ( msg != NULL) free(msg);
+}
+
+void rmtctrl_newClient(struct rmt_socket_t srv, struct rmt_socket_t *client, int *activeClients)
+{
+ int rslt;
+ int cli = (*activeClients);
+ rmtctrl_accept(srv,&client[cli]);
+ if (client[(*activeClients)].fd != -1)
+ {
+ (*activeClients)++;
+ }
+ if ((*activeClients) >= MAX_CLIENTS)
+ {
+ (*activeClients)--;
+ rslt = write_msg(&client[(*activeClients)],MSG_END,0, "Sorry Server is too Busy\n Try more late\n" );
+ if (rslt > 0) client[(*activeClients)].Tx += rslt;
+ rmtctrl_close(&client[(*activeClients)]);
+ }
+}
+
+void rmtctrl_close ( struct rmt_socket_t *client )
+{
+ printf("Desde %s se recibieron %d bytes y se enviaron %d bytes\n",inet_ntoa(client->addr.sin_addr),client->Rx,client->Tx);
+ close(client->fd); /* cierra fd_rmt_client */
+ printf("Se cerro conexión desde %s\n",inet_ntoa(client->addr.sin_addr) );
+ client->fd = -1;
+}
+
+void rmtctrl_accept (struct rmt_socket_t srv, struct rmt_socket_t *client )
+{
+ int sin_size=sizeof(struct sockaddr_in);
+ int int_Send;
+ struct sockaddr_in addr;
+
+ if ((client->fd = accept(srv.fd,(struct sockaddr *)&client->addr,&sin_size))!=-1)
+ {
+ client->Rx = 0;
+ client->Tx = 0;
+ unsigned char c = sizeof(uint32_t);
+ int_Send = send(client->fd, &c, 1, 0);
+ if (int_Send > 0) client->Tx += int_Send;
+ printf("Se abrió una conexión desde %s\n", inet_ntoa(client->addr.sin_addr));
+ }
+}
+
+struct rmt_socket_t initSrv(){
+ struct rmt_socket_t srv;
+ if ((srv.fd=socket(AF_INET, SOCK_STREAM, 0)) == -1 ) {
+ printf("error en socket()\n");
+ exit(-1);
+ }
+ srv.addr.sin_family = AF_INET;
+ srv.addr.sin_port = htons(PORT);
+ srv.addr.sin_addr.s_addr = INADDR_ANY;
+ bzero(&(srv.addr.sin_zero),8);
+
+ if(bind(srv.fd,(struct sockaddr*)&srv.addr,sizeof(struct sockaddr))==-1) {
+ printf("error en bind() \n");
+ exit(-1);
+ }
+
+ if(listen(srv.fd,BACKLOG) == -1) {
+ printf("error en listen()\n");
+ exit(-1);
+ }
+ return srv;
+}
+
+//void cleanClients (int *table, int *n)
+void rmtctrl_cleanClients (struct rmt_socket_t *client, int *n)
+{
+ int i,j;
+
+ if ((client == NULL) || ((*n) == 0))
+ return;
+
+ j=0;
+ for (i=0; i<(*n); i++)
+ {
+ if (client[i].fd != -1)
+ {
+ client[j].fd = client[i].fd;
+ client[j].addr = client[i].addr;
+ client[j].Rx = client[i].Rx;
+ client[j].Tx = client[i].Tx;
+ j++;
+ }
+ }
+
+ *n = j;
+}
+
+int rmtctrl_maxValue (struct rmt_socket_t *client, int n)
+{
+ int i;
+ int max;
+
+ if ((client == NULL) || (n<1))
+ return 0;
+
+ max = client[0].fd;
+ for (i=0; i<n; i++)
+ if (client[i].fd > max)
+ max = client[i].fd;
+
+ return max;
+}
+
+
+/*
+void main()
+{
+ rmtctrl_srv();
+}
+*/
--- /dev/null
+/* Estos son los ficheros de cabecera usuales */
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <errno.h>
+
+#define PORT 15557 /* El puerto que ser? abierto */
+#define BACKLOG 2 /* El n?mero de conexiones permitidas */
+#define MAX_CLIENTS 10
+
+enum
+{
+ MSG_OK = 0,
+ MSG_START = 1,
+ MSG_PART = 2,
+ MSG_END = 3,
+ QRY_STATUS = 100,
+ QRY_CONNECTED_LIST = 101,
+ QRY_MACADDR = 102,
+ QRY_IPADDR = 103,
+ QRY_USERNAME = 104,
+};
+
+typedef struct msg_head_t {
+ uint32_t id;
+ uint32_t extra;
+ uint32_t len;
+} msg_head_t;
+
+typedef struct rmt_socket_t {
+ int fd;
+ struct sockaddr_in addr;
+ int Rx;
+ int Tx;
+} rmt_socket_t;
+
+
+int write_msg( struct rmt_socket_t *sckHnd, uint32_t id, uint32_t extra, char *message );
+int read_msg( struct rmt_socket_t *sckHnd, msg_head_t *head, char **message );
+
+struct rmt_socket_t initSrv();
+void rmtctrl_srv(struct rmt_socket_t srv, struct rmt_socket_t *client, int *activeClients);
+
+void rmtctrl_accept (struct rmt_socket_t srv, struct rmt_socket_t *client );
+void rmtctrl_cleanClients (struct rmt_socket_t *client, int *n);
+void rmtctrl_msg_proccess(struct rmt_socket_t *client);
+void rmtctrl_newClient(struct rmt_socket_t srv, struct rmt_socket_t *client, int *activeClients);
+void rmtctrl_close ( struct rmt_socket_t *client );
--- /dev/null
+#include "remotectrl.h"
+
+int main(){
+ time_t tim;
+ struct rmt_socket_t srv;
+ struct rmt_socket_t client[MAX_CLIENTS];
+ int activeClients = 0; /* Número clientes conectados */
+
+ srv = initSrv();
+
+// client = initClients();
+
+
+ while (1){
+ tim=time(NULL);
+ printf("%s", ctime(&tim) );
+ rmtctrl_srv(srv,client,&activeClients);
+ usleep (100);
+ }
+ return 0;
+}
+
--- /dev/null
+/*
+ * Javier Abellán. 14 de Abril de 2003
+ *
+ * Ejemplo de como un servidor puede manejar varios clientes con select().
+ * Este programa hace de servidor.
+ */
+#include <sys/time.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <Socket_Servidor.h>
+#include <Socket.h>
+
+#define MAX_CLIENTES 10
+
+/* Prototipos de las funciones definidas en este fichero */
+void nuevoCliente (int servidor, int *clientes, int *nClientes);
+int dameMaximo (int *tabla, int n);
+void compactaClaves (int *tabla, int *n);
+
+/*
+ * Programa principal.
+ * Crea un socket servidor y se mete en un select() a la espera de clientes.
+ * Cuando un cliente se conecta, le atiende y lo añade al select() y vuelta
+ * a empezar.
+ */
+main()
+{
+ int socketServidor; /* Descriptor del socket servidor */
+ int socketCliente[MAX_CLIENTES];/* Descriptores de sockets con clientes */
+ int numeroClientes = 0; /* Número clientes conectados */
+ fd_set descriptoresLectura; /* Descriptores de interes para select() */
+ int buffer; /* Buffer para leer de los socket */
+ int maximo; /* Número de descriptor más grande */
+ int i; /* Para bubles */
+
+ /* Se abre el socket servidor, avisando por pantalla y saliendo si hay
+ * algún problema */
+ socketServidor = Abre_Socket_Inet ("cpp_java");
+ if (socketServidor == -1)
+ {
+ perror ("Error al abrir servidor");
+ exit (-1);
+ }
+
+ /* Bucle infinito.
+ * Se atiende a si hay más clientes para conectar y a los mensajes enviados
+ * por los clientes ya conectados */
+ while (1)
+ {
+ /* Cuando un cliente cierre la conexión, se pondrá un -1 en su descriptor
+ * de socket dentro del array socketCliente. La función compactaClaves()
+ * eliminará dichos -1 de la tabla, haciéndola más pequeña.
+ *
+ * Se eliminan todos los clientes que hayan cerrado la conexión */
+ compactaClaves (socketCliente, &numeroClientes);
+
+ /* Se inicializa descriptoresLectura */
+ FD_ZERO (&descriptoresLectura);
+
+ /* Se añade para select() el socket servidor */
+ FD_SET (socketServidor, &descriptoresLectura);
+
+ /* Se añaden para select() los sockets con los clientes ya conectados */
+ for (i=0; i<numeroClientes; i++)
+ FD_SET (socketCliente[i], &descriptoresLectura);
+
+ /* Se el valor del descriptor más grande. Si no hay ningún cliente,
+ * devolverá 0 */
+ maximo = dameMaximo (socketCliente, numeroClientes);
+
+ if (maximo < socketServidor)
+ maximo = socketServidor;
+
+ /* Espera indefinida hasta que alguno de los descriptores tenga algo
+ * que decir: un nuevo cliente o un cliente ya conectado que envía un
+ * mensaje */
+ select (maximo + 1, &descriptoresLectura, NULL, NULL, NULL);
+
+ /* Se comprueba si algún cliente ya conectado ha enviado algo */
+ for (i=0; i<numeroClientes; i++)
+ {
+ if (FD_ISSET (socketCliente[i], &descriptoresLectura))
+ {
+ /* Se lee lo enviado por el cliente y se escribe en pantalla */
+ if ((Lee_Socket1 (socketCliente[i], (char *)&buffer, 100) > 0))
+ printf ("Cliente %d envía %s\n", i+1, buffer);
+ else
+ {
+ /* Se indica que el cliente ha cerrado la conexión y se
+ * marca con -1 el descriptor para que compactaClaves() lo
+ * elimine */
+ printf ("Cliente %d ha cerrado la conexión\n", i+1);
+ socketCliente[i] = -1;
+ }
+ }
+ }
+
+ /* Se comprueba si algún cliente nuevo desea conectarse y se le
+ * admite */
+ if (FD_ISSET (socketServidor, &descriptoresLectura))
+ nuevoCliente (socketServidor, socketCliente, &numeroClientes);
+ }
+}
+
+/*
+ * Crea un nuevo socket cliente.
+ * Se le pasa el socket servidor y el array de clientes, con el número de
+ * clientes ya conectados.
+ */
+void nuevoCliente (int servidor, int *clientes, int *nClientes)
+{
+ /* Acepta la conexión con el cliente, guardándola en el array */
+ clientes[*nClientes] = Acepta_Conexion_Cliente (servidor);
+ (*nClientes)++;
+
+ /* Si se ha superado el maximo de clientes, se cierra la conexión,
+ * se deja todo como estaba y se vuelve. */
+ if ((*nClientes) >= MAX_CLIENTES)
+ {
+ close (clientes[(*nClientes) -1]);
+ (*nClientes)--;
+ return;
+ }
+
+ /* Envía su número de cliente al cliente */
+
+// Escribe_Socket1 (clientes[(*nClientes)-1], (char *)nClientes, sizeof(int));
+ char pepe[] = "Mensaje del server uno";
+/*
+ char mensa[] = "Mensaje del server uno";
+ struct s_msg *pepe;
+ pepe = calloc(pepe,12+strlen(mensa)+2);
+ pepe->type = 1;
+ pepe->command = 0;
+ pepe->len = strlen(mensa);
+ strcpy(pepe->data,mensa);
+ printf("int=%d s_msg=%d pepe=%d\n",sizeof(int),sizeof(struct s_msg), sizeof((struct s_msg *)pepe));
+ printf("type=%d command=%d len=%d data=%s\n", pepe->type, pepe->command, pepe->len, pepe->data);
+*///
+// pepe.data = strcpy(pepe.data,"Mensaje del server uno");
+ Escribe_Socket (clientes[(*nClientes)-1], pepe, strlen(pepe));
+ int escribio;
+// escribio = WriteTcpSocket (clientes[(*nClientes)-1], 0,0, "Connected Ok" );
+ /* Escribe en pantalla que ha aceptado al cliente y vuelve */
+// printf ("Aceptado cliente %d %d\n", *nClientes, escribio);
+ return;
+}
+
+/*
+ * Función que devuelve el valor máximo en la tabla.
+ * Supone que los valores válidos de la tabla son positivos y mayores que 0.
+ * Devuelve 0 si n es 0 o la tabla es NULL */
+int dameMaximo (int *tabla, int n)
+{
+ int i;
+ int max;
+
+ if ((tabla == NULL) || (n<1))
+ return 0;
+
+ max = tabla[0];
+ for (i=0; i<n; i++)
+ if (tabla[i] > max)
+ max = tabla[i];
+
+ return max;
+}
+
+/*
+ * Busca en array todas las posiciones con -1 y las elimina, copiando encima
+ * las posiciones siguientes.
+ * Ejemplo, si la entrada es (3, -1, 2, -1, 4) con *n=5
+ * a la salida tendremos (3, 2, 4) con *n=3
+ */
+void compactaClaves (int *tabla, int *n)
+{
+ int i,j;
+
+ if ((tabla == NULL) || ((*n) == 0))
+ return;
+
+ j=0;
+ for (i=0; i<(*n); i++)
+ {
+ if (tabla[i] != -1)
+ {
+ tabla[j] = tabla[i];
+ j++;
+ }
+ }
+
+ *n = j;
+}
+