Ramblings from the Mountains
Michael Hunter's Weblog

20050418 Monday April 18, 2005

SCTP API

SCTP support was integrated into Solaris 10. SCTP was originally designed for its use in telephony. Additionally work has been done to make SCTP work well in multi-homed environments. I'll spend a little time in a series of blog entries examining the SCTP API.

The API is being developed by the tsvwg and a draft is currently available as draft-ietf-tsvwg-sctpsocket-10.txt1. Unix Network Programming Volume 1 is often referred to as the sockets bible, but the SCTP API has been moving fast enough that its not completely up to date. If you are using it expect that there will be some things which have changed.

SCTP provides two different programming models: 1-1 and 1-many. Initially we will look at the 1-1 model as it closely maps to what people are use to when programming TCP socket applications. The main difference is that there is no half-close. If you are porting a TCP application that depends on the half-close you will need to recode it (probably using in band signaling).

Other then things should be pretty familiar. We are going to open a socket and connect on the client side. On the server side we will open a socket, bind to an address we can find, listen on that socket, and then wait for connections.

So the server code looks like this:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/sctp.h>

int main(int argc, char *argv[]) {
        int sd, s, len, addrlen;
        struct sockaddr_in servaddr, clientaddr;
        char buffer[128];

        if ((sd = socket(AF_INET, SOCK_STREAM, IPPROTO_SCTP)) == -1) {
                perror("socket");
                exit(EXIT_FAILURE);
        }

        memset((void *)&servaddr, 0, sizeof(servaddr));
        servaddr.sin_family = AF_INET;
        servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
        servaddr.sin_port = htons(30000);

        bind(sd, (struct sockaddr *)&servaddr, sizeof(servaddr));

        listen(sd, 1);

        for(;;) {
                addrlen = sizeof(clientaddr);
                if ((s = accept(sd, (struct sockaddr *)&clientaddr,
                    &addrlen)) == -1) {
                        perror("accept");
                        exit(EXIT_FAILURE);
                }

                while((len = read(s, buffer, sizeof(buffer))) > 0)
                        write(s, buffer, len);

                close(s);
        }
}

and the client code looks like this:

[edited 5/19/05 due to inserting the server code twice]

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/sctp.h>

int main(int argc, char *argv[]) {
        int sd, s, len;
        struct sockaddr_in servaddr;
        char buffer[128];
        const char msg[] = "Hello, World\n";

        if ((sd = socket(AF_INET, SOCK_STREAM, IPPROTO_SCTP)) == -1) {
                perror("socket");
                exit(EXIT_FAILURE);
        }

        memset((void *)&servaddr, 0, sizeof(servaddr));
        servaddr.sin_family = AF_INET;
        servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
        servaddr.sin_port = htons(30000);

        if (connect(sd, (struct sockaddr *)&servaddr, sizeof(servaddr)) == -1) {                perror("connect");
                exit(EXIT_FAILURE);
        }

        write(sd, msg, sizeof(msg));
        if ((len = read(sd, buffer, sizeof(buffer))) == -1) {
                perror("read");
                exit(EXIT_FAILURE);
        }
        buffer[len] = 0;
        printf("%s", buffer);
        return (EXIT_SUCCESS);
}

I've gone light on configuration (the addresses are hardcoded as the local machine port 30000) and on error handling. That should make it stand out clearly that other then the third argument to socket() and an extra header that this code looks exactly like the TCP equivalent.

So how do we know this is using SCTP? We can look at the output from 'netstat -an' when the server is running:

[...]
SCTP:
        Local Address                   Remote Address          Swind  Send-Q Rwind  Recv-Q StrsI/O  State
------------------------------- ------------------------------- ------ ------ ------ ------ ------- -----------
0.0.0.0                         0.0.0.0                              0      0 102400      0  32/32  CLOSED
      *.30000                   0.0.0.0                              0      0 102400      0  32/32  LISTEN
[...]

So far all that we have done is very straightforward to anybody who has written socket code in the past. But I think it will be easier to learn the unique features that SCTP offers from an existing knowledge base. In the future we will work on making these little code snippets do something interesting and learn about SCTP in the process.


1Guaranteed to become a dead link once the draft is rev'd. Do the obvious link manipulation if its no longer valid or search for the update. ( Apr 18 2005, 04:28:30 PM PDT ) Permalink Comments [1]


Archives
Links
Referrers