SCTP Discussions

Text archives Help


Re: [SCTP-Discussion] Problem trying to use multi-stream


Chronological Thread 
  • From: "Oon Heok Kee" <oonheokkee78 AT hotmail.com>
  • To: dreibh AT exp-math.uni-essen.de, discussion AT sctp.de
  • Subject: Re: [SCTP-Discussion] Problem trying to use multi-stream
  • Date: Fri Aug 30 08:07:02 2002
  • List-id: SCTP Discussions <discussion.sctp.de>

Hi,

Thanks to Thomas, there is now some results with the multi-stream function in my small program. But something weird is happening, because after doing the modifications that Thomas suggested, I need to comment off the whole part that initialises the sctp_initmsg struct, otherwise I'll get a segmentation fault. When it's commented away, there is then 59115 outbound and 41317 inbound streams initialised. (I checked this on Ethereal.) Can anyone please tell me what's wrong?

Just to confirm the optname parameter in ext_setsockopt(), should it be SCTP_INIT, or SCTP_INITMSG?

I have attached the modified code below so that it might be clearer for everyone. Thanks a million!!! :)


Oon, Heok Kee
National University of Singapore

*********************************************************************
/* Echo Client Example */

/* SCTP client */

/* Compile this file with "gcc -o sctp_client sctp_client.c -Wall -lsctpsocket -lsctp -lglib -lstdc++ -lpthread". */

#include <stdio.h> /* for printf() and fprintf() */
#include <sys/socket.h> /* for socket(), connect(), send(), and recv() */
#include <arpa/inet.h> /* for sockaddr_in and inet_addr() */
#include <stdlib.h> /* for atoi() */
#include <string.h> /* for memset() */
#include <unistd.h> /* for close() */
#include <sys/types.h>
#include <sys/time.h>
#include <ext_socket.h>
#include <net/route.h>
#include <net/if.h>
#include <netinet/in.h>
#include <sctp.h>

#define RCVBUFSIZE 16 /* Size of receive buffer */
#define OUTSTREAM 3 /* Number of out-bound streams */
#define INSTREAM 2 /* Number of in-bound streams */


void DieWithError(char *errorMessage)
{
perror(errorMessage);
exit(1);
}


int main(int argc, char *argv[])
{
int sock; /* Socket descriptor */
struct sockaddr_in echoServAddr;/* Echo server address */
unsigned short echoServPort; /* Echo server port */
char *servIP; /* Server IP address (dotted quad) */
char *echoString; /* String to send to echo server */
char echoBuffer[RCVBUFSIZE]; /* Buffer for echo string */
unsigned int echoStringLen; /* Length of string to echo */
int bytesRcvd, totalBytesRcvd; /* Bytes read in single recv() and total bytes read */
ssize_t nr;
struct sctp_initmsg *sim;
struct sctp_sndrcvinfo *sinfo;
struct msghdr msg[1];
struct cmsghdr *cmsg;
struct iovec iov[1];
char cbuf[sizeof(*cmsg) + sizeof(*sinfo)];
char *testbuf;

/* Test for correct number of arguments */
if ((argc < 3) || (argc > 4))
{
fprintf(stderr, "Usage: %s <Server IP> <Echo Word> [<Echo Port>]\n", argv[0]);
exit(1);
}

servIP = argv[1]; /* First arg: server IP address (dotted quad) */

echoString = argv[2]; /* Second arg: string to echo */

if (argc == 4)
echoServPort = atoi(argv[3]); /* Use given port, if any */
else
/* 7 is the well-known port for the echo service */
echoServPort = 7;

printf("\nCreating socket... ");
/* Create a reliable, stream socket using TCP */
if ((sock = ext_socket(AF_INET, SOCK_STREAM, IPPROTO_SCTP)) < 0)
{
DieWithError("socket() failed");
exit(1);
}
printf("Socket created.\n\n");

/* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% */

sim->sinit_num_ostreams = OUTSTREAM;
sim->sinit_max_instreams = INSTREAM;
sim->sinit_max_attempts = 3;
sim->sinit_max_init_timeo = 30;



/* Setting socket options */
if (ext_setsockopt(sock, IPPROTO_SCTP, SCTP_INITMSG, sim, sizeof(*sim)) < 0)
{
DieWithError("setsockopt() failed");
exit(1);
}


/* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% */


memset(msg, 0, sizeof(*msg));
msg->msg_control = cbuf;
msg->msg_controllen = sizeof(struct cmsghdr) + sizeof(struct sctp_sndrcvinfo);
msg->msg_flags = 0;

iov->iov_base = testbuf;
iov->iov_len = nr;

msg->msg_iov = iov;
msg->msg_iovlen = 1;

cmsg = (struct cmsghdr *)cbuf;
sinfo = (struct sctp_sndrcvinfo *)(cmsg + 1);

cmsg->cmsg_len = sizeof(struct cmsghdr) + sizeof(struct sctp_sndrcvinfo);
cmsg->cmsg_level = IPPROTO_SCTP;
cmsg->cmsg_type = SCTP_INITMSG;

sinfo->sinfo_assoc_id = 0;
sinfo->sinfo_stream = 0; /* streamNumber */
sinfo->sinfo_flags = 0;
sinfo->sinfo_ppid = 0; /* ppid */
sinfo->sinfo_context = (uint32_t)NULL;
sinfo->sinfo_timetolive = (unsigned int)-1;

/* Construct the server address structure */
/* Zero out structure */
memset(&echoServAddr, 0, sizeof(echoServAddr));

echoServAddr.sin_family = AF_INET; /* Internet address family */

/* Server IP address */
echoServAddr.sin_addr.s_addr = inet_addr(servIP);

echoServAddr.sin_port = htons(echoServPort); /* Server port */

printf("Connecting to server at %s:%u ... ", servIP, echoServPort);
/* Establish the connection to the echo server */
if (ext_connect(sock, (struct sockaddr *) &echoServAddr, sizeof(echoServAddr)) < 0)
DieWithError("connect() failed");
printf("Connected.\n\n");

echoStringLen = strlen(echoString); /* Determine input length */

printf("Sending message \"%s\" to server... ", echoString);
/* Send the string to the server */
if (ext_sendmsg(sock, msg, MSG_UNORDERED))
DieWithError("send() sent a diff. num. of bytes than expected");
printf("Message sent.\n\n");

/* Receive the same string back from the server */
totalBytesRcvd = 0;

printf("Receiving echo from server... ");
printf("Received: "); /* Setup to print the echoed string */

while (totalBytesRcvd < echoStringLen)
{
/* Receive up to the buffer size (minus 1 to leave space for a null terminator) bytes from the sender */
if ((bytesRcvd = ext_recv(sock, echoBuffer, RCVBUFSIZE - 1, 0)) <= 0)
DieWithError("recv() failed or conn. closed prematurely");

totalBytesRcvd += bytesRcvd; /* Keep tally of total bytes */

echoBuffer[bytesRcvd] = '\0'; /* Terminate the string! */

printf(echoBuffer); /* Print the echo buffer */
}

printf("\n\n"); /* Print a final linefeed */

ext_close(sock);

exit(0);
}


****************************************************************************



----Original Message Follows----
From: Thomas Dreibholz
<dreibh AT exp-math.uni-essen.de>
To: "Oon Heok Kee"
<oonheokkee78 AT hotmail.com>,

discussion AT sctp.de
Subject: Re: [SCTP-Discussion] Problem trying to use multi-stream
Date: Thu, 29 Aug 2002 15:15:55 +0200

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Am Donnerstag, 29. August 2002 14:18 schrieb Oon Heok Kee:
> Hi,
>
> I'm trying to write an echo program using TCP-style sockets in C and
> getting the program to use multi-stream instead of the default single
> stream. Problem is, I've read <draft-ietf-tsvwg-sctpsocket-04.txt> about 5
> times over, gone through sctpterminal.cc and sctpmultiserver.cc examples,
> and I still don't understand how to initiate a multi-stream socket.
>
> I've been trying at it for the past week but with no results, which is
> why I'm attaching my codes below, hoping that someone can point out what's
> wrong. My problem primary lies at the spot marked by "%%%". I don't know
> how to use sendmsg() because of all the struct msghdr and cmsghdr stated in
> the draft and initiating it.

You can see socket_programs/idexampletcp.c and socket_programs/idexampleudp.c
for a running example of the ext_recvmsg() case. These are the sources of the
examples in the draft.

The ext_sendmsg() case is quite similar:

/* Set up the msghdr structure for receiving */
memset(msg, 0, sizeof (*msg));
msg->msg_control = cbuf;
msg->msg_controllen = sizeof(struct cmsghdr) + sizeof(struct
sctp_sndrcvinfo);

msg_control contains a buffer with control information for the send call. In
our case, we only have to write sctp_sndrcvinfo and a cmsghdr header into
this buffer (see below).

msg->msg_flags = 0;

No flags.

iov->iov_base = buf;
iov->iov_len = nr;
msg->msg_iov = iov;
msg->msg_iovlen = 1;

You can specify multiple buffers of user data to send by one send call as a
single chunk. The data will be concatenated to the chunk in sequential order.
In our case, we only have one buffer "buf" with "nr" bytes. Therefore, the
array iov has only one entry: (buf, nr). msg->msg_iov gets the pointer to
this array, the number of entries is 1.

cmsg = (struct cmsghdr *)cbuf;
sinfo = (struct sctp_sndrcvinfo *)(cmsg + 1);

The control buffer now must contain a header for each control structure (only
sctp_sendrcvinfo in our case). In the C++ examples, this is realized by the
method addHeaderFirst() of the SocketMessage template:

cmsg->cmsg_len = sizeof(struct cmsghdr) + sizeof(struct sctp_sndrcvinfo);
cmsg->cmsg_level = IPPROTO_SCTP;
cmsg->cmsg_type = SCTP_INITMSG;

Now, we can set the sctp_sndrcvinfo data:

sinfo->sinfo_assoc_id = 0;
sinfo->sinfo_stream = streamNumber;
sinfo->sinfo_flags = 0;
sinfo->sinfo_ppid = ppid;
sinfo->sinfo_context = NULL;
sinfo->sinfo_timetolive = (unsigned int)-1;



> Perhaps someone can also point out some of the important points that I
> should note when coding the echo server program.
>

There is an error in:
"if (ext_setsockopt(IPPROTO_SCTP, SCTP_INITMSG, sim, sizeof(*sim)) > 0)"
ext_setsockopt() has 5, not 4 parameters. You must give the socket FD as
first parameter; the same as you have to do for setsockopt(). Try
"if (ext_setsockopt(sock,IPPROTO_SCTP, SCTP_INITMSG, sim, sizeof(*sim)) > 0)"
and setting the stream parameters should work.
Normally, your C compiler should at least print out a warning when it is
tried to use a function with too few parameters or wrong datatypes given.
Recommendation: Turn on all warnings; for gcc, the option -Wall does this.


_________________________________________________________________
Send and receive Hotmail on your mobile device: http://mobile.msn.com





Archive powered by MHonArc 2.6.19+.

Top of page