2 * Javier Abellan, 20 Jun 2000
4 * Funciones de lectura y escritura en sockets
7 * 4 Septiembre 2003: Añadidas funciones para sockets UDP.
10 #include <sys/socket.h>
11 #include <netinet/in.h>
20 #define BUFFER_SIZE 13
22 int ReadTcpSocket (int fd
, char **Datos
)
27 char buffer
[BUFFER_SIZE
];
29 message
= malloc(BUFFER_SIZE
);
31 bzero(buffer
, BUFFER_SIZE
);
32 Aux
= read(fd
, buffer
, BUFFER_SIZE
-1);
34 message
= memcpy(message
, buffer
, Aux
);
35 head
= malloc(sizeof(struct head_t
));
36 head
= memcpy(head
,buffer
,Aux
);
38 message
= realloc(message
,(strlen(message
)+Aux
));
39 if (Aux
== BUFFER_SIZE
-1)
40 message
= strcat(message
,buffer
);
42 message
= strncat(message
,buffer
,Aux
);
46 printf("msg=%s Leido=%d\n", message
, Leido
);
47 if (Aux
< BUFFER_SIZE
-1 || Leido
== head
->len
)
50 *Datos
=realloc(*Datos
,Leido
+1);
51 memcpy(*Datos
,head
,sizeof(struct head_t
));
52 memcpy(*Datos
+12, message
, Leido
);
56 int WriteTcpSocket(int fd
, int type
, int command
, char *data
){
60 int Longitud
= (sizeof(int)*3)+strlen((char *)data
);
62 Datos
= malloc(Longitud
);
64 Datos
->command
= command
;
65 Datos
->len
= Longitud
;
66 strcpy(Datos
->data
, data
);
67 printf("Longitud=%d convertido Type=%d Command=%d Len=%d Data=%s\n",Longitud
, Datos
->type
, Datos
->command
, Datos
->len
, Datos
->data
);
68 printf("Longitud=%d int=%d\n", Longitud
,sizeof(int));
70 if ((fd == -1) || (Datos == NULL) || (Longitud < 1))
74 //printf("Data:%s", *Datos);
75 while (Escrito
< Longitud
)
77 Aux
= write (fd
, Datos
+ Escrito
, Longitud
- Escrito
);
80 Escrito
= Escrito
+ Aux
;
95 * Lee datos del socket. Supone que se le pasa un buffer con hueco
96 * suficiente para los datos. Devuelve el numero de bytes leidos o
97 * 0 si se cierra fichero o -1 si hay error.
99 int Lee_Socket1 (int fd
, char *Datos
, int Longitud
)
106 * Comprobacion de que los parametros de entrada son correctos
108 if ((fd
== -1) || (Datos
== NULL
) || (Longitud
< 1))
112 * Mientras no hayamos leido todos los datos solicitados
115 while (Leido
< Longitud
)
117 Aux
= read (fd
, Datos
+ Leido
, Longitud
- Leido
);
121 * Si hemos conseguido leer datos, incrementamos la variable
122 * que contiene los datos leidos hasta el momento
129 * Si read devuelve 0, es que se ha cerrado el socket. Devolvemos
130 * los caracteres leidos hasta ese momento
137 * En caso de error, la variable errno nos indica el tipo
139 * El error EINTR se produce si ha habido alguna
140 * interrupcion del sistema antes de leer ningun dato. No
141 * es un error realmente.
142 * El error EGAIN significa que el socket no esta disponible
143 * de momento, que lo intentemos dentro de un rato.
144 * Ambos errores se tratan con una espera de 100 microsegundos
145 * y se vuelve a intentar.
146 * El resto de los posibles errores provocan que salgamos de
147 * la funcion con error.
163 * Se devuelve el total de los caracteres leidos
169 * Escribe dato en el socket cliente. Devuelve numero de bytes escritos,
172 int Escribe_Socket (int fd
, char *Datos
, int Longitud
)
178 * Comprobacion de los parametros de entrada
180 if ((fd
== -1) || (Datos
== NULL
) || (Longitud
< 1))
184 * Bucle hasta que hayamos escrito todos los caracteres que nos han
187 while (Escrito
< Longitud
)
189 Aux
= write (fd
, Datos
+ Escrito
, Longitud
- Escrito
);
193 * Si hemos conseguido escribir caracteres, se actualiza la
196 Escrito
= Escrito
+ Aux
;
201 * Si se ha cerrado el socket, devolvemos el numero de caracteres
203 * Si ha habido error, devolvemos -1
213 * Devolvemos el total de caracteres leidos
219 * Lee un mensaje de un socket udp. Los parámetros que se pasan son:
220 * - Descriptor fd del socket del que se quiere leer.
221 * - Estructura Remoto, en la que se devolverá los datos del que ha enviado el
222 * mensaje que acabamos de leer.
223 * - Longitud_Remoto de la estructura anterior. Debe pasarse relleno con el tamaño
224 * de Remoto y se devolverá rellena con el tamaño de los datos en Remoto.
225 * - Buffer de Datos donde se quiere que aparezca el mensaje.
226 * - Longitud_Datos del buffer anterior.
228 * Devuelve el número de bytes leidos o -1 en caso de error.
231 int fd
, struct sockaddr
*Remoto
, socklen_t
*Longitud_Remoto
,
232 char *Datos
, int Longitud_Datos
)
238 * Comprobacion de que los parametros de entrada son correctos
240 if ((fd
== -1) || (Datos
== NULL
) || (Longitud_Datos
< 1)
241 || (Remoto
== NULL
) || (Longitud_Remoto
== NULL
))
247 * Mientras no hayamos leido todos los datos solicitados
249 while (Leido
< Longitud_Datos
)
251 Aux
= recvfrom (fd
, Datos
+ Leido
, Longitud_Datos
- Leido
, 0,
252 Remoto
, Longitud_Remoto
);
257 * Si hemos conseguido leer datos, incrementamos la variable
258 * que contiene los datos leidos hasta el momento
265 * Si read devuelve 0, es que se ha cerrado el socket. Devolvemos
266 * los caracteres leidos hasta ese momento
273 * En caso de error, la variable errno nos indica el tipo
275 * El error EINTR se produce si ha habido alguna
276 * interrupcion del sistema antes de leer ningun dato. No
277 * es un error realmente.
278 * El error EGAIN significa que el socket no esta disponible
279 * de momento, que lo intentemos dentro de un rato.
280 * Ambos errores se tratan con una espera de 100 microsegundos
281 * y se vuelve a intentar.
282 * El resto de los posibles errores provocan que salgamos de
283 * la funcion con error.
299 * Se devuelve el total de los caracteres leidos
305 * Escribe dato en el socket cliente. Devuelve numero de bytes escritos,
307 * - fd es el descriptor del socket.
308 * - Remoto es el destinatario del mensaje, a quién se lo queremos enviar.
309 * - Longitud_Remoto es el tamaño de Remoto en bytes.
310 * - Datos es el mensaje que queremos enviar.
311 * - Longitud_Datos es el tamaño del mensaje en bytes.
313 int Escribe_Socket_Udp (int fd
, struct sockaddr
*Remoto
,
314 socklen_t Longitud_Remoto
, char *Datos
, int Longitud_Datos
)
320 * Comprobacion de los parametros de entrada
322 if ((fd
== -1) || (Datos
== NULL
) || (Longitud_Datos
< 1)
323 || (Remoto
== NULL
) )
329 * Bucle hasta que hayamos escrito todos los caracteres que nos han
332 while (Escrito
< Longitud_Datos
)
334 Aux
= sendto (fd
, Datos
+ Escrito
, Longitud_Datos
- Escrito
, 0,
335 Remoto
, Longitud_Remoto
);
340 * Si hemos conseguido escribir caracteres, se actualiza la
343 Escrito
= Escrito
+ Aux
;
348 * Si se ha cerrado el socket, devolvemos el numero de caracteres
350 * Si ha habido error, devolvemos -1
362 * Devolvemos el total de caracteres leidos
369 * Rellena una estructura sockaddr_in con los datos que se le pasan. Esta estrutura es
370 * útil para el envio o recepción de mensajes por sockets Udp o para abrir conexiones.
371 * Se le pasa el host. Puede ser NULL (para abrir socket servidor Udp o para recepción de
372 * mensajes de cualquier host).
373 * Se le pasa el servicio. Puede ser NULL (para abrir socket cliente Udp).
374 * Se le pasa una estructura sockaddr_in que devolverá rellena.
375 * Se le pasa una Longitud. Debe contener el tamaño de la estructura sockaddr_in y
376 * devolverá el tamaño de la estructura una vez rellena.
377 * Devuelve -1 en caso de error.
379 int Dame_Direccion_Udp (char *Host
, char *Servicio
, struct sockaddr_in
*Servidor
,
380 int *Longitud_Servidor
)
382 struct servent
*Puerto
;
383 struct hostent
*Maquina
;
385 /* Comprobación de parámetros */
386 if (Servidor
== NULL
) return -1;
388 /* Relleno del primer campo de la estructura */
389 Servidor
->sin_family
= AF_INET
;
391 /* Si nos han pasado un host ... */
394 /* ... obtenemos la dirección del host y la ponemos en la estructura */
395 Maquina
= gethostbyname (Host
);
399 Servidor
->sin_addr
.s_addr
= ((struct in_addr
*)(Maquina
->h_addr
))->s_addr
;
402 /* Si no nos han pasado un host, ponemos cualquier host. */
403 Servidor
->sin_addr
.s_addr
= INADDR_ANY
;
405 /* Si servicio en NULL, hacemos que el puerto lo eliga el sistema operativo
407 if (Servicio
== NULL
)
408 Servidor
->sin_port
= 0;
411 /* Si el servicio no es NULL, lo obtenemos. */
412 Puerto
= getservbyname (Servicio
, "udp");
415 Servidor
->sin_port
= Puerto
->s_port
;