#pragma module TCPIP$SCTP_SELECT_SERVER "V5.7-00" /* ** BUILD ENVIRONMENT: ** ** If the current version of DECC does not suport SCTP, then you must ** manually configure the environment as follows: ** ** $ define netinet tcpip$examples ** ** BUILD INSTRUCTIONS: ** ** $ cc tcpip$sctp_select_server ** $ link tcpip$sctp_select_server ** ** SYNTAX: ** ** sctp_server [port] ** ** EXAMPLE: ** ** Define a foreign symbol to point at the application. ** ** $ sctp_sel :== $TCPIP$EXAMPLES:tcpip$sctp_select_server ** $ sctp_sel */ #define _SOCKADDR_LEN #include #include #include #include #ifndef __VMS #include #else #include #endif typedef unsigned int socklen_t; /* usually defined in socket.h */ #include #include #include #include #include /* SCTP */ #ifndef IPPROTO_SCTP #define IPPROTO_SCTP 132 /* SCTP */ #endif #define MAXCLIENTS 5 #define DEF_PORT 55555 #define SA(x) ((struct sockaddr *)x) typedef struct client_s { int sd; char name[INET6_ADDRSTRLEN]; int port; } client_t; void clear_socket(int sd, fd_set *fds, client_t *cli) { printf("Closed connection to: %s:%d\n", cli->name, cli->port); close(sd); FD_CLR(sd, fds); cli->sd = -1; } int main(int argc, char *argv[]) { int listen_sd, sd, maxfd, cc, status, port, i; fd_set rset, wset, eset, allset; /* masks for select */ struct sockaddr_in local, peer; socklen_t peerlen = sizeof(peer); client_t client[MAXCLIENTS]; char buf[128]; if(argc == 2) port = atoi(argv[1]); else port = DEF_PORT; /* init to no clients connected */ for(i = 0; i < MAXCLIENTS; i++) client[i].sd = -1; /* setup the local address that we will bind to and listen on */ local.sin_len = sizeof(local); local.sin_family = AF_INET; local.sin_port = htons(port); local.sin_addr.s_addr = INADDR_ANY; /* create an SCTP listen socket */ listen_sd = socket(AF_INET, SOCK_STREAM, IPPROTO_SCTP); if(listen_sd == -1) {perror("STREAM socket"); return 1;} maxfd = listen_sd; /* for select mask */ /* bind to local port and address(es) */ if(bind(listen_sd, SA(&local), local.sin_len) == -1) {perror("bind"); return 1;} /* prepare to accept connections */ if(listen(listen_sd, 5) == -1) {perror("listen"); return 1;} /* prepare for select loop */ /* Set bits for all the listener sockets. */ FD_ZERO(&allset); FD_SET(listen_sd, &allset); FD_ZERO(&wset); /* not interested in write events for now */ printf("Waiting for connections on SCTP port %d ...\n", port); /* select loop */ for(;;) { rset = eset = allset; if((status = select(maxfd + 1, &rset, &wset, &eset, NULL)) < 0) { if(errno == EINTR) {printf("select returned EINTR\n"); continue;} else {perror("select"); return 1;} } if(FD_ISSET(listen_sd, &eset)) printf("Exception on listen socket\n"); /* new connection */ if(FD_ISSET(listen_sd, &rset)) { peerlen = sizeof(peer); if((sd = accept(listen_sd, (struct sockaddr *)&peer, &peerlen)) == -1) {perror("accept"); continue;} /* add new client to client array. */ for(i = 0; i < MAXCLIENTS; i++) { if(client[i].sd < 0) { client[i].sd = sd; break; } } if(i == MAXCLIENTS) {printf("Too many clients\n"); close(sd); continue;} /* save client's address and port number */ inet_ntop(AF_INET, &peer.sin_addr.s_addr, &client[i].name[0], INET6_ADDRSTRLEN); client[i].port = ntohs(peer.sin_port); printf("Accepted connection from: %s:%d\n", client[i].name, client[i].port); if(sd > maxfd) maxfd = sd; FD_SET(sd, &allset); /* add connected socket to select mask */ } /* check all clients for newly-arrived data */ for(i = 0; i < MAXCLIENTS; i++) { if((sd = client[i].sd) < 0) continue; if(FD_ISSET(sd, &eset)) printf("Exception on connected socket:%d\n", sd); if(FD_ISSET(sd, &rset)) { /* data arrived on socket */ cc = read(sd, &buf, sizeof(buf)); switch(cc) { case -1: /* error on socket */ perror("read"); clear_socket(sd, &allset, &client[i]); break; case 0: /* peer disconnect */ printf("%s closed connection.", client[i].name); clear_socket(sd, &allset, &client[i]); break; default: /* data available */ buf[cc] = '\0'; printf("%s:%d says: %s\n", client[i].name, client[i].port, buf); if(buf[0] == 'Q') clear_socket(sd, &allset, &client[i]); } /* end switch */ } /* client read ready */ } /* for all clients */ } /* select() for ever */ }