1 /* LibTcp - Released underOpen Software License v. 2.0
3 * This Open Software License (the "License") applies to any original work of authorship
4 * (the "Original Work") whose owner (the "Licensor") has placed the following notice
5 * immediately following the copyright notice for the Original Work:
7 * Licensed under the Open Software License version 2.0
9 * See http://www.opensource.org/licenses/osl-2.0.php or the LICENSE file for more
15 /** Abre un socket en modo activo para establecer una conexión con un servidor.
17 * Esta función es utilizada por los clientes para establecer una conexión TCP
20 * \param servidor Nombre del host server
21 * \param port Número del puerto
22 * \return >0 El descriptor del socket, si se conecto al servidor.
23 * \return -2 Si no existe el nombre del servidor.
24 * \return -1 Si hubo error en la conexion y se debe consultar errno.
26 int libtcp_open_activo (const char *server, int port)
28 int sockfd; /* socket de la conexion */
29 struct sockaddr_in serv_addr;
30 struct hostent *ptr_server; /*puntero a dir del server(gethostbyname)*/
32 /* Borrar la estructura (poner en cero) */
33 bzero ((char *) &serv_addr, sizeof(serv_addr));
35 /* Inicializo familia de direcciones (protocolo IP) */
36 serv_addr.sin_family = AF_INET;
38 /* Cargar port en el socket: Convertir Host-TO-Network-Short integer */
39 serv_addr.sin_port = htons (port);
41 /* Cargo dirección del server en el socket. Convertir nombre del host en su direccion */
42 ptr_server = gethostbyname (server);
43 if (ptr_server == NULL) {
44 /* No existe nombre de host. Posible falla en resolución de nombre */
47 memcpy (&serv_addr.sin_addr, ptr_server->h_addr, ptr_server->h_length);
49 /* Abro como un socket de TCP (Internet stream socket) */
50 if ((sockfd = socket (AF_INET, SOCK_STREAM, 0)) < 0) {
51 /* Error en la creacion del socket */
55 if (connect (sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) {
56 /* TODO : Deberia ser un codigo de error diferente, asi puedo diferenciarlos */
63 /** Abre un socket en modo pasivo usando protocolo TCP.
65 * La función se encarga de inicializar y crear el socket, y
66 * luego enlazarla con el SO.
68 * \param port Puerto sobre el cual atiende este servidor
69 * \return >0 El socket, si la operacion fue exitosa
70 * \return <0 Si hubo un error (ver errno)
72 int libtcp_open_pasivo (int port)
75 char mostrar[80]; /* mensajes en la pantalla */
77 int sockfd; /* socket que sirve como template */
78 struct sockaddr_in serv_addr;
80 bzero ((char *)&serv_addr, sizeof (serv_addr));
81 serv_addr.sin_family = AF_INET; /* Familia protocolos TCP/IP */
82 serv_addr.sin_addr.s_addr = htonl (INADDR_ANY); /* Cualquier cliente */
83 serv_addr.sin_port = htons ((unsigned short)port); /* Port en formato red */
85 /* Crea un socket para TCP (un Internet stream socket) */
86 if ((sockfd = socket (AF_INET, SOCK_STREAM, 0)) < 0) {
92 if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (char *) &yes,
95 perror ("setsockopt");
101 sprintf (mostrar, "LibTcp::ServerPasivo: socket creado %d\n", sockfd);
102 write (fileno(stdout), mostrar, strlen (mostrar));
105 /* Vincular el socket con la direccion local */
106 if (bind (sockfd, (struct sockaddr *) &serv_addr, sizeof (serv_addr)) < 0) {
111 sprintf (mostrar, "LibTcp::Server: se hizo el bind\n");
112 write(fileno(stdout), mostrar, strlen(mostrar));
115 /* Definir la cola de espera = hasta 5 clientes */
119 sprintf (mostrar, "LibTcp::Server: se hizo el listen con el socket %d\n", sockfd);
120 write(fileno(stdout), mostrar, strlen(mostrar));
126 /** Lee de a un byte por vez a un buffer hasta encontrar un "\n".
128 * La cadena leída es terminada en "\0".
130 * \return El tamaño, en caracteres, de la cadena leida.
131 * \param fd Descriptor del socket
132 * \param ptr Puntero al buffer
133 * \param maxlong Tamaño del buffer (en bytes)
134 * \TODO Soporte de caracteres multibyte
136 int libtcp_receive (int fd, char *ptr, unsigned int maxlong)
142 for (n = 0; n < maxlong; n++) {
143 if ((car = read (fd, &c, sizeof (char))) == 1) {
147 } else if (car == 0) {
149 /* EOF, sin datos leidos */
152 break; /* EOF, se leyo algo */
161 /** Lee una informacion binaria */
162 int libtcp_receive_bin (int fd, void *ptr, unsigned int n)
164 int nfaltan, nrecibidos;
165 char *p = (char*) ptr;
168 while (nfaltan > 0) {
169 nrecibidos = read (fd, p, nfaltan);
173 nfaltan -= nrecibidos;
181 /** Escribe n bytes sobre un descriptor.
183 * Si no se escribieron n bytes, trata de repetir hasta que se hayan escrito
186 * Se debe usar esta funcion cuando el descriptor en un stream socket.
188 * \param fd Descriptor del socket
189 * \param ptr Puntero al mensaje
190 * \param n cantidad de bytes
192 int libtcp_send (int fd, const void *ptr, unsigned int n)
194 int nfaltan, nenviados;
195 const char *p = (const char *) ptr;
198 while (nfaltan > 0) {
199 nenviados = write (fd, p, nfaltan);
203 nfaltan -= nenviados;