sockets client gio

sockets - Ejemplo de GIO socket-server/-client



(2)

Me gustaría crear una aplicación de servidor y cliente que se comunique a través de sockets usando GIO. GSocketService y GSocketClient parecen ser perfectos para este propósito, pero desafortunadamente no pude encontrar algún tutorial o código de ejemplo (que un GLib, GIO, ... novato pueda entender). ¿Alguien sabe algunos recursos buenos o puede publicar código de ejemplo aquí?


Finalmente logré crear un servidor simple y un cliente usando glib y gio.
Mi servidor se ve así:

#include <glib.h> #include <gio/gio.h> /* this function will get called everytime a client attempts to connect */ gboolean incoming_callback (GSocketService *service, GSocketConnection *connection, GObject *source_object, gpointer user_data) { g_print("Received Connection from client!/n"); GInputStream * istream = g_io_stream_get_input_stream (G_IO_STREAM (connection)); gchar message[1024]; g_input_stream_read (istream, message, 1024, NULL, NULL); g_print("Message was: /"%s/"/n", message); return FALSE; } int main (int argc, char **argv) { /* initialize glib */ g_type_init(); GError * error = NULL; /* create the new socketservice */ GSocketService * service = g_socket_service_new (); /* connect to the port */ g_socket_listener_add_inet_port ((GSocketListener*)service, 1500, /* your port goes here */ NULL, &error); /* don''t forget to check for errors */ if (error != NULL) { g_error (error->message); } /* listen to the ''incoming'' signal */ g_signal_connect (service, "incoming", G_CALLBACK (incoming_callback), NULL); /* start the socket service */ g_socket_service_start (service); /* enter mainloop */ g_print ("Waiting for client!/n"); GMainLoop *loop = g_main_loop_new(NULL, FALSE); g_main_loop_run(loop); return 0; }

y este es el cliente correspondiente:

#include <glib.h> #include <gio/gio.h> int main (int argc, char *argv[]) { /* initialize glib */ g_type_init (); GError * error = NULL; /* create a new connection */ GSocketConnection * connection = NULL; GSocketClient * client = g_socket_client_new(); /* connect to the host */ connection = g_socket_client_connect_to_host (client, (gchar*)"localhost", 1500, /* your port goes here */ NULL, &error); /* don''t forget to check for errors */ if (error != NULL) { g_error (error->message); } else { g_print ("Connection successful!/n"); } /* use the connection */ GInputStream * istream = g_io_stream_get_input_stream (G_IO_STREAM (connection)); GOutputStream * ostream = g_io_stream_get_output_stream (G_IO_STREAM (connection)); g_output_stream_write (ostream, "Hello server!", /* your message goes here */ 13, /* length of your message */ NULL, &error); /* don''t forget to check for errors */ if (error != NULL) { g_error (error->message); } return 0; }

Sin embargo, tenga en cuenta que todavía soy nuevo en glib, gio e incluso en C, así que revise mi código antes de usarlo.


La devolución de llamada de entrada no debe bloquear, desde la documentación de gio: "El controlador debe iniciar el manejo de la conexión, pero no puede bloquear, en esencia, se deben utilizar operaciones asíncronas".

Tuve algún problema con la conexión en la versión asíncrona, debe ser referido por el usuario o la conexión se cerrará después de que regrese la devolución de llamada entrante.

Un ejemplo completo de un servidor que no bloquea, basado en el ejemplo anterior:

#include <gio/gio.h> #include <glib.h> #define BLOCK_SIZE 1024 #define PORT 2345 struct ConnData { GSocketConnection *connection; char message[BLOCK_SIZE]; }; void message_ready (GObject * source_object, GAsyncResult *res, gpointer user_data) { GInputStream *istream = G_INPUT_STREAM (source_object); GError *error = NULL; struct ConnData *data = user_data; int count; count = g_input_stream_read_finish (istream, res, &error); if (count == -1) { g_error ("Error when receiving message"); if (error != NULL) { g_error ("%s", error->message); g_clear_error (&error); } } g_message ("Message was: /"%s/"/n", data->message); g_object_unref (G_SOCKET_CONNECTION (data->connection)); g_free (data); } static gboolean incoming_callback (GSocketService *service, GSocketConnection * connection, GObject * source_object, gpointer user_data) { g_message ("Received Connection from client!/n"); GInputStream *istream = g_io_stream_get_input_stream (G_IO_STREAM (connection)); struct ConnData *data = g_new (struct ConnData, 1); data->connection = g_object_ref (connection); g_input_stream_read_async (istream, data->message, sizeof (data->message), G_PRIORITY_DEFAULT, NULL, message_ready, data); return FALSE; } int main () { GSocketService *service; GError *error = NULL; gboolean ret; service = g_socket_service_new (); ret = g_socket_listener_add_inet_port (G_SOCKET_LISTENER (service), PORT, NULL, &error); if (ret && error != NULL) { g_error ("%s", error->message); g_clear_error (&error); return 1; } g_signal_connect (service, "incoming", G_CALLBACK (incoming_callback), NULL); g_socket_service_start (service); GMainLoop *loop = g_main_loop_new(NULL, FALSE); g_main_loop_run(loop); /* Stop service when out of the main loop*/ g_socket_service_stop (service); return 0; }