/* File : sctp_client_send_receive_echo_messages_from_one_stream.c Programmer : Nasif Ekiz Date : 9/27/2006 Description : This is a SCTP client application which establishes an association with server. It reads a message from the user and sends it to the server. The server than echoes the read message to client. This program is a SCTP one-to-many style application. */ #include #include #include #include #include #define SERV_PORT 7000 #define MAXLINE 4096 #define SCTP_MAXLINE 800 // this function is used to send and receive messages on one stream in the association void sctpstr_cli(FILE *fp, int sock_fd, struct sockaddr *to, socklen_t tolen) { struct sockaddr_in peeraddr; struct sctp_sndrcvinfo sri; // sctp_sndrcvinfo structure used to set default parameters for the association char sendline[MAXLINE], recvline[MAXLINE]; // send and receive message buffers socklen_t len; int out_sz, rd_sz; int msg_flags; // clear sctp_sndrcvinfo structure memset(&sri, 0, sizeof(sri)); while(fgets(sendline, MAXLINE, fp) != NULL) { // if stream number is not presented in [streamnum] format if(sendline[0] != '[') { printf("Error, line must be of the form '[streamnum]text' \n"); continue; } // set the stream number that the message will be sent sri.sinfo_stream = strtol(&sendline[1], NULL, 0); out_sz = strlen(sendline); // send a message that will be echoed by the server sctp_sendmsg(sock_fd, sendline, out_sz, to, tolen, 0, 0, sri.sinfo_stream, 0, 0); len = sizeof(peeraddr); // read the echoed message from the server rd_sz = sctp_recvmsg(sock_fd, recvline, sizeof(recvline), (struct sockaddr *) &peeraddr, &len, &sri, &msg_flags); // print stream number, stream sequence number and association id printf("From str:%d seq:%d (assoc:0x%x):", sri.sinfo_stream, sri.sinfo_ssn, (u_int) sri.sinfo_assoc_id); // print the received echoed message printf("%.*s", rd_sz, recvline); } } int main(int argc, char **argv) { int sock_fd; // socket identifier struct sockaddr_in servaddr; // address structure to keep server's IPv4 address info struct sctp_event_subscribe evnts; // this structure is used to enable/disable various SCTP // notifications int echo_to_all=0; // variable used to determine wheather to send data from // one or multiple streams // server address is missing if(argc < 2) printf("Missing host argument - use '%s host [echo]'\n", argv[0]); // open a socket // AF_INET - IPv4 protocol // SOCK_SEQPACKET - sequenced packet socket // IPPROTO_SCTP - SCTP transport protocol sock_fd = socket(AF_INET, SOCK_SEQPACKET, IPPROTO_SCTP); // check for error if (sock_fd < 0) { perror("Client can't open socket!"); exit(1); } // clear server address structure memset(&servaddr, 0, sizeof(servaddr)); // set server address information servaddr.sin_family = AF_INET; // IPv4 protocol servaddr.sin_addr.s_addr = htonl(INADDR_ANY); // in the case of multiple interfaces accept // connection on any host interface servaddr.sin_port = htons(SERV_PORT); // server application port number inet_pton(AF_INET, argv[1], &servaddr.sin_addr); // convert the string server address(argv[1]) to // host byte order (servaddr.sin_addr) // clear sctp_event_subscribe structure memset(&evnts, 0, sizeof(evnts)); // enable sctp_sndrcvinfo to come with each sctp_recvmsg function evnts.sctp_data_io_event = 1; // set the options for the socket // SCTP_EVENTS option allows a caller to fetch, enable/disable various SCTP notifications if ((setsockopt(sock_fd,IPPROTO_SCTP, SCTP_EVENTS, &evnts, sizeof(evnts))) < 0) { perror("Error in setsockopt!"); exit(1); } // message is echoed on just one stream if(echo_to_all == 0) sctpstr_cli(stdin,sock_fd,(struct sockaddr *)&servaddr,sizeof(servaddr)); // close the socket if ((close(sock_fd)) < 0) { perror("Can't close socket!"); exit(1); } return(0); }