2012-03-01 12 views
7

Vorrei creare un server e un'applicazione client che comunichi tramite socket utilizzando GIO. GSocketService e GSocketClient sembrano perfetti per questo scopo ma sfortunatamente non sono riuscito a trovare qualche tutorial o codice di esempio (che un GLib, GIO, ... newbie possa capire). Qualcuno conosce delle buone risorse o può pubblicare un codice di esempio qui?GIO socket-server/-esempio client

+0

Avete fatto qualche progresso? Sto cercando la stessa cosa. Oltre alla [API] (http://developer.gnome.org/gio/stable/highlevel-socket.html) e questa [SO risposta] (http://stackoverflow.com/a/2145259/545442) I haven ' Ho trovato qualcosa. – noisebleed

+0

@noisebleed: Sì, ho davvero fatto progressi. In realtà non capisco perché non sia stato in grado di creare sia server che client al primo tentativo. Probabilmente non dovrei provare a imparare C, glib e OGRE allo stesso tempo. – drakide

risposta

17

Sono finalmente riuscito a creare sia un semplice server che un client utilizzando glib e gio.
Il mio server è simile al seguente:

#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; 
} 

e questo è il corrispondente cliente:

#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; 
} 

nota, però, che io sono ancora nuovo per glib, gio e persino C, in modo da controllare due volte il mio codice prima di usarlo.

+0

Grazie per aver condiviso questo. Sarà una risorsa inestimabile per i nuovi arrivati ​​di GIO. La documentazione di riferimento è buona ma mancano esempi. – noisebleed

+0

@noisebleed: la stessa opinione sulla documentazione qui. – drakide

+0

, in realtà, è possibile utilizzare tale comando "echo anyword | nc localhost 1500" come client per testare se il server funziona. – mxi1

5

Il callback dall'ingresso non deve bloccare, dalla documentazione di gio: "Il gestore deve iniziare la gestione della connessione, ma non può bloccare, in sostanza, devono essere utilizzate operazioni asincrone."

Ho avuto qualche problema con la connessione nella versione asincrona, deve essere riferito dall'utente o la connessione verrà chiusa dopo il ritorno della richiamata in entrata.

Un esempio completo di un server che non blocca, sulla base dell'esempio dato prima:

#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; 
} 
Problemi correlati