Posted by: Airtower | 2010-07-01

SCTP socket in stream mode

SCTP sockets can operate in two modes: SOCK_SEQPACKET or SOCK_STREAM. When migrating my server from UDP to SCTP, I initially used the sequential packet mode. However, changing to stream mode offered me two significant advantages:

  1. I use threads to process data from different clients. With sequential packet mode, the callback for new data has to store the data and meta information in a custom structure and pass that to the handler thread. With stream mode, the callback uses g_socket_accept() and passes the resulting GSocket to the thread which will take care of the rest.

  2. Some of the target platforms do not support SCTP. With stream mode, only minimal changes are necessary to make the server use TCP. Of course, this means that the SCTP features are lost, but it is better than nothing.

The only change compared to the example code in the previous post is that the socket has to be created in stream mode:

GSocket *sock;
GError *err = NULL;
sock = g_socket_new(G_SOCKET_FAMILY_IPV6,
                    G_SOCKET_TYPE_STREAM,
                    G_SOCKET_PROTOCOL_SCTP,
                    &err);
g_assert(err == NULL);

The changes in the callback went deeper. My event callback has access to the listening socket through a data structure passed via the data pointer (see the GIOFunc definition), I’ll just assume a GSocket * for this example callback:

gboolean new_message_callback(GIOChannel *source,
                        GIOCondition condition,
                        gpointer data)
{
        GSocket *sock = data;
        g_assert(G_IS_SOCKET(sock));

        GError *err = NULL;
        GSocket *new_sock = g_socket_accept(sock,
                                        NULL,
                                        &err);
        g_assert(err == NULL);

        /* start handler thread */
        g_thread_create((GThreadFunc) handler_thread_func,
                        new_sock,
                        FALSE,
                        &err);
        g_assert(err == NULL);

        return TRUE;
}

The thread can now read from and write to the socket as usual. An additional advantage is that each thread gets its own socket: No need to lock it. In my server, the handler threads close and unref the sockets when done. You might want to keep the connections alive, if that’s the case you’ll have to handle connection end and memory freeing some other way.

Advertisements

Responses

  1. Hi Airtower, nice blog, very useful informations.
    But I have a problem with gtk, gio and socket and would like to ask you for your support.
    as a start: I have a label and would like to update this label via a listen TCP socket over threading. I have something which works as single thread, but the GTK freezes until next request comes in. So I saw your blow entry above and that’s almost what i need. But have have no clue how to combine all together.
    So, have a nice day, neighbor.
    Regard from Dortmund 🙂
    DJ

    • The issue is probably that your one thread blocks until it receives an incoming message. Instead, you should let the GLib main loop take care of that for you (UDP example here), so it will call some kind of callback function as in the example above to accept the connection. That callback can then start a handler thread.
      Good luck!


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: