Featured Post

Trie implementation in C

SCTP Server Client Implementation in C

Here's a simple implementation of SCTP server and client in C

This is how the connection is established :

The Client initiates the connection with an INIT packet . Server replies back by sending the INIT-ACK.
This packet also contains a unique context which identifies this connection. This context is called as COOKIE. The client then responds with a COOKIE-ECHO with the cookie sent by the server.
Now the server allocates the necessary resources required by the connection and replies back to the client with COOKIE-ACK.

And this is how the connection is terminated.

 This is a detailed connection diagram for this program is as follows



//SCTPServer.C To compile - gcc sctpserver.c - o server - lsctp
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <time.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <netinet/sctp.h>
#define MAX_BUFFER 1024
#define MY_PORT_NUM 62324 /* This can be changed to suit the need and should be same in server and client */

int
main ()
{
  int listenSock, connSock, ret, in, flags, i;
  struct sockaddr_in servaddr;
  struct sctp_initmsg initmsg;
  struct sctp_event_subscribe events;
  struct sctp_sndrcvinfo sndrcvinfo;
  char buffer[MAX_BUFFER + 1];

  listenSock = socket (AF_INET, SOCK_STREAM, IPPROTO_SCTP);
  if(listenSock == -1)
  {
      printf("Failed to create socket\n");
      perror("socket()");
      exit(1);
  }

  bzero ((void *) &servaddr, sizeof (servaddr));
  servaddr.sin_family = AF_INET;
  servaddr.sin_addr.s_addr = htonl (INADDR_ANY);
  servaddr.sin_port = htons (MY_PORT_NUM);

  ret = bind (listenSock, (struct sockaddr *) &servaddr, sizeof (servaddr));

  if(ret == -1 )
  {
      printf("Bind failed \n");
      perror("bind()");
      close(listenSock);
      exit(1);
  }

  /* Specify that a maximum of 5 streams will be available per socket */
  memset (&initmsg, 0, sizeof (initmsg));
  initmsg.sinit_num_ostreams = 5;
  initmsg.sinit_max_instreams = 5;
  initmsg.sinit_max_attempts = 4;
  ret = setsockopt (listenSock, IPPROTO_SCTP, SCTP_INITMSG,
      &initmsg, sizeof (initmsg));

  if(ret == -1 )
  {
      printf("setsockopt() failed \n");
      perror("setsockopt()");
      close(listenSock);
      exit(1);
  }

  ret = listen (listenSock, 5);
  if(ret == -1 )
  {
      printf("listen() failed \n");
      perror("listen()");
      close(listenSock);
      exit(1);
  }

  while (1)
    {

      char buffer[MAX_BUFFER + 1];
      int len;

      //Clear the buffer
      bzero (buffer, MAX_BUFFER + 1);

      printf ("Awaiting a new connection\n");

      connSock = accept (listenSock, (struct sockaddr *) NULL, (int *) NULL);
      if (connSock == -1)
      {
 printf("accept() failed\n");
        perror("accept()");
        close(connSock);
        continue;
      }
      else
 printf ("New client connected....\n");

      in = sctp_recvmsg (connSock, buffer, sizeof (buffer),
    (struct sockaddr *) NULL, 0, &sndrcvinfo, &flags);

      if( in == -1)
      {
          printf("Error in sctp_recvmsg\n");
          perror("sctp_recvmsg()");
          close(connSock);
          continue;
      }
      else
      {
          //Add '\0' in case of text data
          buffer[in] = '\0';

          printf (" Length of Data received: %d\n", in);
          printf (" Data : %s\n", (char *) buffer);
      }
      close (connSock);
    }

  return 0;
}






//SCTPClient.C
// To compile - gcc sctpclt.c -o client -lsctp
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <netinet/sctp.h>
#include <arpa/inet.h>
#define MAX_BUFFER 1024
#define MY_PORT_NUM 62324 /* This can be changed to suit the need and should be same in server and client */

int
main (int argc, char* argv[])
{
  int connSock, in, i, ret, flags;
  struct sockaddr_in servaddr;
  struct sctp_status status;
  char buffer[MAX_BUFFER + 1];
  int datalen = 0;

  /*Get the input from user*/
  printf("Enter data to send: ");
  fgets(buffer, MAX_BUFFER, stdin);
  /* Clear the newline or carriage return from the end*/
  buffer[strcspn(buffer, "\r\n")] = 0;
  /* Sample input */
  //strncpy (buffer, "Hello Server", 12);
  //buffer[12] = '\0';
  datalen = strlen(buffer);

  connSock = socket (AF_INET, SOCK_STREAM, IPPROTO_SCTP);

  if (connSock == -1)
  {
      printf("Socket creation failed\n");
      perror("socket()");
      exit(1);
  }

  bzero ((void *) &servaddr, sizeof (servaddr));
  servaddr.sin_family = AF_INET;
  servaddr.sin_port = htons (MY_PORT_NUM);
  servaddr.sin_addr.s_addr = inet_addr ("127.0.0.1");

  ret = connect (connSock, (struct sockaddr *) &servaddr, sizeof (servaddr));

  if (ret == -1)
  {
      printf("Connection failed\n");
      perror("connect()");
      close(connSock);
      exit(1);
  }

  ret = sctp_sendmsg (connSock, (void *) buffer, (size_t) datalen,
        NULL, 0, 0, 0, 0, 0, 0);
  if(ret == -1 )
  {
    printf("Error in sctp_sendmsg\n");
    perror("sctp_sendmsg()");
  }
  else
      printf("Successfully sent %d bytes data to server\n", ret);

  close (connSock);

  return 0;
}


Note: To compile this code, sctp dev libraries are needed . 
For ubuntu : sudo apt-get install libsctp-dev 

Comments

  1. undefined reference to `sctp_recvmsg'

    i got this error it is not working

    will please solve this problem

    ReplyDelete
  2. undefined reference to `sctp_recvmsg'|


    solve this error

    ReplyDelete
  3. It seems that sctp header file is not included properly. Check if it is present in the standard location of gcc.

    ReplyDelete
  4. Thank you for writing this article, I have used it as a reference in my article: SCTP multi-homing with dynamic address reconfiguration http://rainbowtux.blogspot.be/2012/10/sctp-multi-homing-with-dynamic-address.html#.UIvlHtE7jTk

    Kind regards,

    ReplyDelete
    Replies
    1. It is no multi-homing. It is example of multi streams. It's different concepts.

      Delete
  5. In order to resolve the missing sctp.h file issue, you have to load the libsctp-dev. Use sudo apt-get install libsctp-dev on debian or Ubuntu and sudo yum install libsctp-dev on Fedora and Centos.
    To resolve the undefined reference to sctp_recvmsg, you have to link with libsctp. To do that, use the -l sctp switch to the compiler, e.g.

    gcc SCTP_server.c -l sctp -o SCTP_server

    ReplyDelete
  6. To clear the buffer,add code

    memset(buffer, 0, MAX_BUFFER + 1);

    between the "New client connected...." printf and the sctp_recvmsg.

    ReplyDelete
    Replies
    1. When the messages are text, the memset is OK, but not the quickest way. In general, use the message length as returned by sctp_recvmsg.

      In this case,
      in = sctp_recvmsg ....

      buffer[in] = (char) NULL;

      printf .....

      More robust code would deal with the fact that "The sctp_recvmsg() function returns -1 when an error occurs." (source: http://docs.oracle.com/cd/E19963-01/html/821-1602/sockets-17.html )

      Delete
  7. hi i tried to execute this but it is showing the following error on the client side
    connect : connection denied
    please resolve this problem

    ReplyDelete
    Replies
    1. Did you run the program as root ? what kind of platform are you using ?
      Also try debugging the code with gdb , it will tell you the exact error code.

      Delete
    2. hi, even i am facing the same problem. it says connection refused.i ran the program both on root as well as on the normal user mode. i even tried debugging the code,but it dint really work. Kindly help.

      Delete
  8. Hello folks, in my case the code runs perfectly but the output way different than expected.

    the server seems not to wait for the client to send data to it.. it comes blank and then on the client side i'm asked to enter data..
    For the server side -->
    $ ./bin/sctp_server
    Awaiting a new connection
    New client connected....
    Data :
    Awaiting a new connection

    For the Client side -->
    $ ./bin/sctp_client
    Data sent by Client : qwer


    ReplyDelete
  9. Some more Issues ::

    Server
    $ ./bin/sctp_server
    Awaiting a new connection
    New client connected...
    Data :
    Awaiting a new connection

    Client
    $./bin/sctp_client

    There is no point entering data when the client asks, the server always displays data as blank.

    ReplyDelete
  10. can you please guide on how to run this code?
    is there any order that has to be followed?

    ReplyDelete
  11. Please follow the instructions in the comments at the top of each file.

    To run server: ./server
    To run client: ./client

    ReplyDelete
  12. the server seems not to wait for the client to send data to it.. it comes blank and then on the client side i'm asked to enter data..
    For the server side -->
    $ ./bin/sctp_server
    Awaiting a new connection
    New client connected....
    Data :
    Awaiting a new connection

    please help!!!

    ReplyDelete
    Replies
    1. Hi,
      I have modified the code to handle text data. Please try the new one.

      Although, I was able to run the existing one perfectly fine.
      Also please post if you have made any modifications

      Delete
  13. Simple and Impressive.. worked just like that !!!

    ReplyDelete
  14. Hey, I am running the server code on a different machine and the client on my local machine. Both are in the same network. They are not able to connect. However, I can connect if use udp client-server sockets. Any help?

    ReplyDelete
  15. Note, make sure to set flags to 0 (`int flags = 0`), because otherwise the pointer might point to an address which is non-0 and it would set flags that you don't want to set:
    ```
    (...)
    man sctp_recvmsg
    (...)
    The value of msg_flags pointer should be initialized to 0 to avoid unexpected behavior
    ```

    ReplyDelete

Post a Comment

Please post your valuable suggestions