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)
74 char mostrar[80]; /* mensajes en la pantalla */
75 int sockfd; /* socket que sirve como template */
76 struct sockaddr_in serv_addr;
78 bzero ((char *)&serv_addr, sizeof (serv_addr));
79 serv_addr.sin_family = AF_INET; /* Familia protocolos TCP/IP */
80 serv_addr.sin_addr.s_addr = htonl (INADDR_ANY); /* Cualquier cliente */
81 serv_addr.sin_port = htons ((unsigned short)port); /* Port en formato red */
83 /* Crea un socket para TCP (un Internet stream socket) */
84 if ((sockfd = socket (AF_INET, SOCK_STREAM, 0)) < 0) {
90 if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (char *) &yes,
93 perror ("setsockopt");
98 sprintf (mostrar, "LibTcp::ServerPasivo: socket creado %d\n", sockfd);
99 write (fileno(stdout), mostrar, strlen (mostrar));
101 /* Vincular el socket con la direccion local */
102 if (bind (sockfd, (struct sockaddr *) &serv_addr, sizeof (serv_addr)) < 0) {
106 sprintf (mostrar, "LibTcp::Server: se hizo el bind\n");
107 write(fileno(stdout), mostrar, strlen(mostrar));
109 /* Definir la cola de espera = hasta 5 clientes */
112 sprintf (mostrar, "LibTcp::Server: se hizo el listen con el socket %d\n", sockfd);
113 write(fileno(stdout), mostrar, strlen(mostrar));
118 /** Lee de a un byte por vez a un buffer hasta encontrar un "\n".
120 * La cadena leída es terminada en "\0".
122 * \return El tamaño, en caracteres, de la cadena leida.
123 * \param fd Descriptor del socket
124 * \param ptr Puntero al buffer
125 * \param maxlong Tamaño del buffer (en bytes)
126 * \TODO Soporte de caracteres multibyte
128 int libtcp_receive (int fd, char *ptr, unsigned int maxlong)
134 for (n = 0; n < maxlong; n++) {
135 if ((car = read (fd, &c, sizeof (char))) == 1) {
139 } else if (car == 0) {
141 /* EOF, sin datos leidos */
144 break; /* EOF, se leyo algo */
153 /** Lee una informacion binaria */
154 int libtcp_receive_bin (int fd, void *ptr, unsigned int n)
156 int nfaltan, nrecibidos;
157 char *p = (char*) ptr;
160 while (nfaltan > 0) {
161 nrecibidos = read (fd, p, nfaltan);
165 nfaltan -= nrecibidos;
173 /** Escribe n bytes sobre un descriptor.
175 * Si no se escribieron n bytes, trata de repetir hasta que se hayan escrito
178 * Se debe usar esta funcion cuando el descriptor en un stream socket.
180 * \param fd Descriptor del socket
181 * \param ptr Puntero al mensaje
182 * \param n cantidad de bytes
184 int libtcp_send (int fd, const void *ptr, unsigned int n)
186 int nfaltan, nenviados;
187 const char *p = (const char *) ptr;
190 while (nfaltan > 0) {
191 nenviados = write (fd, p, nfaltan);
195 nfaltan -= nenviados;