Posted by: Airtower | 2010-06-19

Using a UDP socket as event source in GLib main loop

I’ve been rewriting a small UDP server using GLib. I found it difficult to get started with GLib, but well worth it – the code is a lot cleaner now. One thing that took me particularly long to figure out is how to integrate listening on a UDP socket into the GLib main loop. It’s not really complicated, but the parts are scattered in different parts of the GLib and GIO API documentation.

Obviously, a GSocket is necessary. I want my socket to listen on IPv6 UDP. I know that assertions are not the best error handling, but they are good enough for an example. 😉

GSocket *sock;
GError *err = NULL;
sock = g_socket_new(G_SOCKET_FAMILY_IPV6,
                    G_SOCKET_TYPE_DATAGRAM,
                    G_SOCKET_PROTOCOL_UDP,
                    &err);
g_assert(err == NULL);

Bind the socket (addr is the GInetSocketAddress* to listen on):

g_socket_bind(sock,
              G_SOCKET_ADDRESS(addr),
              TRUE,
              &err);
g_assert(err == NULL);

Hint: if you want to listen on all interfaces, use g_inet_address_new_any() to create the GInetAddress part of the socket’s address. Under Linux “any IPv6 address” includes IPv4, I don’t know if this applies on other platforms as well.

To get an event when the socket receives data, the following steps are necessary:

  1. Get a file descriptor for the socket.
  2. Use the file descriptor to create a GIOChannel for the socket.
  3. Add a watch for the G_IO_IN condition on the channel.
int fd = g_socket_get_fd(sock);
GIOChannel* channel = g_io_channel_unix_new(fd);
guint source = g_io_add_watch(channel, G_IO_IN,
                              (GIOFunc) callback_function, data);
g_io_channel_unref(channel);

The callback_function has to match the GIOFunc pattern. It must not block, so I use it to start a thread which will do the real work. The main loop needs to be initialized before attaching the event. After the event is attached, just run the main loop (if you need more info about that, look here). Cleaning up is pretty simple: Use g_source_remove(source) to disconnect the event source and g_object_unref() the objects.

Advertisements

Responses

  1. […] SCTP in GLib A while ago, I wrote about using a UDP socket as event source in GLib. Now, I’m migrating my program to SCTP. The main reason is that SCTP provides reliability for […]

  2. Hi.
    Has wondering if you could post a complete simple example for this. The documentation for the glib sockets is confusing me. I have tried to use the parts of the example you have shown but can’t quite get it to work

    Thanks
    Todd

    • It would probably take a while until I can get around to writing a complete example. Where do you get stuck?

      • That’s cool. I just managed to get it working. Got stuck in a fair few places but have managed to cheat in some places and got it to work a treat.

        Thanks for replyting

        Todd

  3. […] Before coming to Japan almost all of my posts were about Linux & programming, and “Using a UDP socket as event source in GLib main loop” is still the most visited post. Recently, however, I’ve been mostly writing about […]


Leave a Comment

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Categories

%d bloggers like this: