jueves, 26 de enero de 2012

Sockets multiplataforma con GTK+

Recientemente hemos visto como realizar compilación cruzada con GTK+. Esto nos permite escribir aplicaciones que se ejecutan en diferentes plataformas, almenos a nivel gráfico.

Vamos a ver ahora como usar sockets TCP, algo que habitualmente suele estar muy ligado a una plataforma concreta. GTK+ (de hecho es GLIB) nos proporciona una API para acceder a la red. Esta API, al igual que GTK+ es multiplataforma.

Escribiremos un cliente TCP sencillo, que se conectará a un puerto, escribirá un mensaje, y leerá la respuesta.

Primero incluimos las cabeceras habituales en un programa C, junto con las cabeceras de GTK+.

#include <stdio.h>
#include <string.h>
#include <gtk/gtk.h>

Necesitamos las siguientes variables;

GError *err = NULL;
GSocket *sock = NULL;
GInetAddress *iaddr = NULL;
GSocketAddress *saddr = NULL;
GCancellable *cancel = NULL;

Usamos las siguientes funciones para inicializar las variables que contienen las direcciones de red. Lògicamente con la IP y puerto que convenga:

g_type_init();
iaddr = g_inet_address_new_from_string("192.168.1.1");
saddr = g_inet_socket_address_new(iaddr, 23);

Abrimos el socket y nos conectamos a el:

sock = g_socket_new(
   G_SOCKET_FAMILY_IPV4,
   G_SOCKET_TYPE_STREAM,
   G_SOCKET_PROTOCOL_TCP,
   &err);

f(!g_socket_connect(sock, saddr, cancel, &err))
{
   printf("Cannot connect\n");
   return -1;
}

Y finalmente, enviamos y recibimos datos:

   char buf[256];
   strncpy(buf, "lst\n", sizeof(buf));
   g_socket_send(sock, buf, strlen(buf), cancel, &err);
   g_socket_receive(sock, buf, sizeof(buf), cancel, &err);

   printf("received:\n%s\n", buf);


Sencillo, ¿no?


7 comentarios:

MaG dijo...

¿ Libnet ?

Miguel dijo...

Hola Daniel, genial el articulo de sockets en GTK.

Decirte que lo estoy haciendo pero para la parte server, al poner mi ip "81.xx.xx.xx" el bin me da error:"No se puede asignar la dirección solicitada" pero si pongo 127.0.0.1 todo ok.
Estoy buscando donde puede estar el error pero no lo veo.

Gracias, me ha sido muy util.
Un saludo

Miguel dijo...

Hola Daniel, genial tu articulo.
Estoy haciendo la version server y en el bind me lanza ub error:"No se puede asignar la dirección solicitada" al poner una ip del tipo "81.xxx.xxx.xxx" pero si pongo 127.0.0.1 sin problemas. Estoy buscando donde puede estar el error pero no lo veo, hay poca docu por la red sobre este tema.

Gracias y un saludo.

Daniel Lerch dijo...

Hola Miguel,
Que IP tiene tu equipo? tiene la 81.x.x.x en la interfaz de red que usas?

Miguel dijo...

Hola Daniel, ya está corregido; me estaba liando con la parte cliente, el server lleva la 192.1681.101 (no la del router).

Ahora tengo un problema tipico de GTK, ¿como saber cuando llegan datos al socket?
Mi cliente (el Navegador) manda datos cuando quiere, pero no se como hacer para que GTK se de cuenta que ha llegado algo. Me paso lo mismo con un puerto serie, pero no se si la solucion puede ser la misma: utilizar la funcion "gdk-input-add()"

Bueno sigo investigando.
Gracias por responder.

Miguel dijo...

Daniel, esa funcion que te he comentado antes está descatalogada; creo que la solución está en:

g_io_add_watch ()

Ya te contaré si lo consigo.

Saludos.

Daniel Lerch dijo...

ok,suerte!