Jump to content United States-English
HP.com Home Products and Services Support and Drivers Solutions How to Buy
» Contact HP
More options
HP.com home
SCTP Programmer's Guide: HP-UX 11i v2, HP-UX 11i v3 > Appendix A SCTP Sample Programs

Sample Server Programs

» 

Technical documentation

» Feedback
Content starts here

 » Table of Contents

 » Glossary

 » Index

This section lists the sample server programs in one-to-one and one-to-many associations.

This section addresses the following topics:

One-to-One Server Program

The following sample program is an implementation of an echo server over SCTP in a one-to-one association:

#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <unistd.h>
#include <netinet/sctp.h>
#include <sys/uio.h>

#define BUFLEN  100

int debug=0;

static void
handle_event(void *buf)
{
	struct sctp_assoc_change *sac;
	struct sctp_send_failed *ssf;
	struct sctp_paddr_change *spc;
	struct sctp_remote_error *sre;
	union sctp_notification *snp;
	char addrbuf[INET6_ADDRSTRLEN];
	const char *ap;
	struct sockaddr_in *sin;
	struct sockaddr_in6 *sin6;

	snp = buf;

	switch (snp->sn_header.sn_type) {
	case SCTP_ASSOC_CHANGE:
		sac = &snp->sn_assoc_change;
		printf("^^^ assoc_change: state=%hu, error=%hu, instr=%hu "
		"outstr=%hu\n", sac->sac_state, sac->sac_error,
		sac->sac_inbound_streams, sac->sac_outbound_streams);
		break;

	case SCTP_SEND_FAILED:
		ssf = &snp->sn_send_failed;
		printf("^^^ sendfailed: len=%hu err=%d\n", ssf->ssf_length,
		ssf->ssf_error);
		break;

	case SCTP_PEER_ADDR_CHANGE:
		spc = &snp->sn_paddr_change;
		if (spc->spc_aaddr.ss_family == AF_INET) {
		sin = (struct sockaddr_in *)&spc->spc_aaddr;
		ap = inet_ntop(AF_INET, &sin->sin_addr,
			    addrbuf, INET6_ADDRSTRLEN);
		} else {
		sin6 = (struct sockaddr_in6 *)&spc->spc_aaddr;
		ap = inet_ntop(AF_INET6, &sin6>sin6_addr,
			    addrbuf, INET6_ADDRSTRLEN);
		}
		printf("^^^ intf_change: %s state=%d, error=%d\n", ap,
		  spc->spc_state, spc->spc_error);
		break;

	case SCTP_REMOTE_ERROR:
		sre = &snp->sn_remote_error;
		printf("^^^ remote_error: err=%hu len=%hu\n",
		ntohs(sre->sre_error), ntohs(sre->sre_length));
		break;

	case SCTP_SHUTDOWN_EVENT:
		printf("^^^ shutdown event\n");
		break;

	default:
		printf("unknown type: %hu\n", snp->sn_header.sn_type);
		break;
	}
}

int main(int argc, char **argv)
{
	int fd, new_fd, sz, len, msg_flags;
	int idleTime = 20;
	struct sockaddr_in sin[1], cli_addr;
	struct sctp_event_subscribe event;
	char readbuf[100];
	struct sctp_sndrcvinfo sri;
	fd_set fdset;

	if (argc < 2) {
		printf ("\nUsage: <%s> \n\n", argv[0]);
		return -1;
	}

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

	sin->sin_family = AF_INET;
	sin->sin_port = htons(atoi(argv[1]));
	sin->sin_addr.s_addr = INADDR_ANY;
	if (bind(fd, (struct sockaddr *)sin, sizeof (*sin)) == -1) {
		perror("bind");
		exit(1);
	}

	/* Allow new associations to be accepted */
	if (listen(fd, 1) < 0) {
		perror("listen");
		exit(1);
	}

	memset (&sri, 0, sizeof(sri));

	printf ("{one-to-one}: Waiting for associations ...\n");

	FD_ZERO(&fdset);
	FD_SET(fd, &fdset);

	/* Wait for new associations */
	while(1) {
		if (select (fd+1, &fdset, 0, 0, 0) <= 0)
			continue;

		new_fd = accept (fd, (struct sockaddr *) &cli_addr, (socklen_t *) &le);
		if (new_fd >=0 )
			printf ("\n Connection from: %s\n", inet_ntoa(cli_addr.sin_addr));

		/* Not interested in any events for now */
		memset (&event, 0, sizeof(event));
		if (setsockopt(new_fd, IPPROTO_SCTP, SCTP_EVENTS, &event, sizeof(event)) != 0) {
			perror("setevent failed");
			exit(1);
		}

		while (1) {
			/* Echo back any and all data */
			memset (readbuf, 0, sizeof(readbuf));
			len = sizeof (struct sockaddr_in);

#if 0
			sz = recv(new_fd, readbuf, sizeof(readbuf), 0);
			if (debug)
				printf ("recv:[%d,e:%d]: ", sz, errno);
#endif
			sz = sctp_recvmsg (new_fd, readbuf, sizeof(readbuf), 
						0, 0, &sri, 0);
			if (debug) printf ("sctp_recvmsg:[%d,e:%d,fl:%X]: ", sz, errno, msg_flags);
			if (sz <= 0)
				break;
			printf ("<-- %s      on str: %d\n", readbuf, 
						sri.sinfo_stream);
			sz = sctp_sendmsg (new_fd, readbuf, sz, 0, len, 0, 0,
					sri.sinfo_stream, 0, 0);
			if (debug)
				printf ("sctp_sendmsg:[%d,e:%d]\n", sz, errno);
		}
		close(new_fd);
	}

	/* unreachable */
	close(fd);
}


One-to-Many Server Program

The following sample program is an implementation of an echo server over SCTP in a one-to-many association:

#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <unistd.h>
#include <netinet/sctp.h>
#include <sys/uio.h>

#define BUFLEN  100

int debug=0;

static void
handle_event(void *buf)
{
	struct sctp_assoc_change *sac;
	struct sctp_send_failed *ssf;
	struct sctp_paddr_change *spc;
	struct sctp_remote_error *sre;
	union sctp_notification *snp;
	char addrbuf[INET6_ADDRSTRLEN];
	const char *ap;
	struct sockaddr_in *sin;
	struct sockaddr_in6 *sin6;

	snp = buf;

	switch (snp->sn_header.sn_type) {
	case SCTP_ASSOC_CHANGE:
		sac = &snp->sn_assoc_change;
		printf("^^^ assoc_change: state=%hu, error=%hu, instr=%hu "
		"outstr=%hu\n", sac->sac_state, sac->sac_error,
		sac->sac_inbound_streams, sac->sac_outbound_streams);
		break;

	case SCTP_SEND_FAILED:
		ssf = &snp->sn_send_failed;
		printf("^^^ sendfailed: len=%hu err=%d\n", ssf->ssf_length,
		ssf->ssf_error);
		break;

	case SCTP_PEER_ADDR_CHANGE:
		spc = &snp->sn_paddr_change;
		if (spc->spc_aaddr.ss_family == AF_INET) {
		sin = (struct sockaddr_in *)&spc->spc_aaddr;
		ap = inet_ntop(AF_INET, &sin->sin_addr,
			    addrbuf, INET6_ADDRSTRLEN);
		} else {
		sin6 = (struct sockaddr_in6 *)&spc->spc_aaddr;
		ap = inet_ntop(AF_INET6, &sin6>sin6_addr,
			    addrbuf, INET6_ADDRSTRLEN);
		}
		printf("^^^ intf_change: %s state=%d, error=%d\n", ap,
		  spc->spc_state, spc->spc_error);
		break;

	case SCTP_REMOTE_ERROR:
		sre = &snp->sn_remote_error;
		printf("^^^ remote_error: err=%hu len=%hu\n",
		ntohs(sre->sre_error), ntohs(sre->sre_length));
		break;

	case SCTP_SHUTDOWN_EVENT:
		printf("^^^ shutdown event\n");
		break;

	default:
		printf("unknown type: %hu\n", snp->sn_header.sn_type);
		break;
	}
}

int main(int argc, char **argv)
{
	int fd, sz, len, msg_flags;
	int idleTime = 20;
	struct sockaddr_in sin[1], cli_addr;
	struct sctp_event_subscribe event;
	char readbuf[100];
	struct sctp_sndrcvinfo sri;

	if (argc < 2) {
		printf ("\nUsage: <%s> <port>\n\n", argv[0]);
		return -1;
	}

	if ((fd = socket(AF_INET, SOCK_SEQPACKET, IPPROTO_SCTP)) == -1) {
		perror("socket");
		exit(1);
	}

	sin->sin_family = AF_INET;
	sin->sin_port = htons(atoi(argv[1]));
	sin->sin_addr.s_addr = INADDR_ANY;
	if (bind(fd, (struct sockaddr *)sin, sizeof (*sin)) == -1) {
		perror("bind");
		exit(1);
	}

#if 0
	/* Not interested in any events for now */
	memset (&event, 0, sizeof(event));
#else
	/* Enable all events */
	event.sctp_data_io_event = 1;
	event.sctp_association_event = 1;
	event.sctp_address_event = 1;
	event.sctp_send_failure_event = 1;
	event.sctp_peer_error_event = 1;
	event.sctp_shutdown_event = 1;
	event.sctp_partial_delivery_event = 1;
	event.sctp_adaption_layer_event = 1;
#endif
	if (setsockopt(fd, IPPROTO_SCTP, SCTP_EVENTS, &event, sizeof(event)) != 0) {
		perror("setevent failed");
		exit(1);
	}

	/* Set associations to auto-close in 20 seconds of
	* inactivity
	*/
	if (setsockopt(fd, IPPROTO_SCTP, SCTP_AUTOCLOSE,
		   &idleTime, 4) < 0) {
		perror("setsockopt SCTP_AUTOCLOSE");
		exit(1);
	}

	/* Allow new associations to be accepted */
	if (listen(fd, 1) < 0) {
		perror("listen");
		exit(1);
	}

	memset (&sri, 0, sizeof(sri));

	printf ("{one-to-many}: Waiting for associations ...\n");

	/* Wait for new associations */
	while(1) {
		/* Echo back any and all data */
		memset (readbuf, 0, sizeof(readbuf));
		len = sizeof (struct sockaddr_in);
		sz = sctp_recvmsg (fd, readbuf, sizeof(readbuf), 
					&cli_addr, &len, &sri, &msg_flags);
		if (debug)
			printf ("sctp_recvmsg:[%d,e:%d,fl:%X]: ", sz, errno, msg_flags);
		if (sz <= 0)
			break;
		if (msg_flags & MSG_NOTIFICATION) {
			handle_event(readbuf);
			continue;
		}
		printf ("<-- %s      on str: %d\n", readbuf, sri.sinfo_stream);
		sz = sctp_sendmsg (fd, readbuf, sz, &cli_addr, len, 
				sri.sinfo_ppid, sri.sinfo_flags, 
				sri.sinfo_stream, 0, 0);
		if (debug)
			printf ("sctp_sendmsg:[%d,e:%d]\n", sz, errno);
	}
	close(fd);
}


Printable version
Privacy statement Using this site means you accept its terms Feedback to webmaster
© 2007–2008 Hewlett-Packard Development Company, L.P.