- 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: Fri Aug 30 11:52:00 2002
- List-id: SCTP Discussions <discussion.sctp.de>
- Organization: University of Essen, Institute for Experimental Mathematics
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
Am Freitag, 30. August 2002 08:04 schrieb Oon Heok Kee:
>
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?
You have to use malloc() to allocate memory for your sctp_initmsg structure.
In the source code below, the pointer sim points to a random value. When you
try to set a value of this structure, you will get a segmentation fault. If
commented out, your system seems to read random values from somewhere. In
your case 59115 outbound and 41317 inbound streams.
A very useful tool for debugging such and many other memory-releated problems
is the Open Source memory debugger Valgrind:
http://developer.kde.org/~sewardj/
Simplest solution to the sctp_initmsg problem: Do not use a pointer, create
the strucure directly on the stack. Then, it will be automatically removed
when the function (main() in this case) is complete, making a free() call
unnecessary.
Example:
struct sctp_initmsg sim;
...
sim.sinit_num_ostreams = OUTSTREAM;
sim.sinit_max_instreams = INSTREAM;
sim.sinit_max_attempts = 3;
sim.sinit_max_init_timeo = 30;
if(ext_setsockopt(sock, IPPROTO_SCTP, SCTP_INITMSG, &sim, sizeof(sim)) < 0) {
...
Now, take care to use &sim and sizeof(sim) instead of sim and sizeof(*sim)
for the ext_setsockopt call.
>
Just to confirm the optname parameter in ext_setsockopt(), should it be
>
SCTP_INIT, or SCTP_INITMSG?
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
>
>
_______________________________________________
>
discussion mailing list
>
discussion AT sctp.de
>
http://www.sctp.de/mailman/listinfo/discussion
Best regards
- --
=======================================================================
Dipl.-Inform. Thomas Dreibholz
University of Essen, Room ES210
Inst. for Experimental Mathematics Ellernstraße 29
Computer Networking Technology Group D-45326 Essen/Germany
- -----------------------------------------------------------------------
E-Mail:
dreibh AT exp-math.uni-essen.de
Homepage:
http://www.exp-math.uni-essen.de/~dreibh
=======================================================================
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.0.6 (GNU/Linux)
Comment: For info see
http://www.gnupg.org
iD8DBQE9b0JU32BbsHYPLWURAmo5AKCiEVnqKbGWWm6RYBxbDrXsOL70WQCglo33
/UGqR53ub56cjjLq06Swa3k=
=XKJT
-----END PGP SIGNATURE-----
Archive powered by MHonArc 2.6.19+.