- 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 Aug 29 15:12:01 2002
- List-id: SCTP Discussions <discussion.sctp.de>
- Organization: University of Essen, Institute for Experimental Mathematics
-----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.
>
***********************************************************
>
#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 */
>
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;
>
>
/* 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-style */
>
if ((sock = ext_socket(AF_INET, SOCK_STREAM, IPPROTO_SCTP)) < 0)
>
{
>
DieWithError("socket() failed");
>
exit(1);
>
}
>
printf("Socket created.\n\n");
>
>
/* Setting socket options */
>
if (ext_setsockopt(IPPROTO_SCTP, SCTP_INITMSG, sim, sizeof(*sim)) <
>
0)
>
{
>
DieWithError("setsockopt() failed");
>
exit(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, ))
>
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);
>
}
>
**********************************************************
>
>
Desperately need some help here... Thanks a million!!! :)
>
>
>
>
Oon, Heok Kee
>
National University of Singapore
>
>
_________________________________________________________________
>
Chat with friends online, try MSN Messenger: http://messenger.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
iD8DBQE9bh6L32BbsHYPLWURAi6VAJ4h2FuQhverKBVcB0CJqWIbu0NxMACcDPkj
hz/9q4moMDXsNjhxa7qOhZ4=
=ZX7r
-----END PGP SIGNATURE-----
Archive powered by MHonArc 2.6.19+.