I would like to create a server and client application that communicate via sockets using GIO. GSocketService and GSocketClient seem be perfect for this purpose but unfortunately I couldn't find some tutorial or example code (that a GLib, GIO,... newbie can understand). Does anybody know some good resources or can post example code here?
Asked
Active
Viewed 1.7k times
17
-
Did you make any progress? I'm looking for the same thing. Besides the [API](http://developer.gnome.org/gio/stable/highlevel-socket.html) and this [SO answer](http://stackoverflow.com/a/2145259/545442) I haven't found anything. – noisebleed Apr 09 '12 at 15:33
-
@noisebleed: Yes I indeed did make progress. I actually don't get why I wasn't able to create both server and client at my first try. Probably I shouldn't try to learn C, glib, and OGRE at the same time. – drakide Apr 10 '12 at 08:33
-
1First place to look for any gio examples nowadays is the glib repo's gio/tests. There are socket examples there. – dhanushka Oct 02 '21 at 01:50
2 Answers
28
I finally managed to create both a simple server and client using glib and gio.
My server looks like this:
#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;
}
and this is the corresponding client:
#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;
}
Note though, that I am still new to glib, gio and even C, so double check my code before using it.

Wander Nauta
- 18,832
- 1
- 45
- 62

drakide
- 1,757
- 2
- 15
- 23
-
Thanks for sharing this. It will be an invaluable resource for GIO newcomers. Reference documentation is good but examples are lacking. – noisebleed Apr 10 '12 at 09:15
-
1
-
1actually, you can use such one command "echo anyword |nc localhost 1500" as the client to testify if the server works. – mxi1 Apr 08 '14 at 05:37
-
1
-
-
1
-
Thanks for the example! Notice that both example are may leak memory. If the GError's are set because two programs try to listen on the same address and port. You should use g_clear_error(&error) or a similar function in order to free the memory if you get one. – hetepeperfan Jul 25 '23 at 09:18
6
The callback from incoming should not block, from gio documentation: "The handler must initiate the handling of connection , but may not block; in essence, asynchronous operations must be used."
I had some issue with connection in the async version, it has to be referred by the user or the connection will close after the incoming callback returns.
A full example of a server that does not block, based on the example given before:
#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;
}