1 / 43

Chapter 10

Chapter 10. SCTP Client / Server example. Simple echo server using SCTP protocol Send line of text from client to server Server sends the same line back to the client Iterative server. Client. Client reads a single line of text from standard input Text is send in [#]text format.

ayala
Download Presentation

Chapter 10

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Chapter 10 SCTP Client / Server example

  2. Simple echo server using SCTP protocol • Send line of text from client to server • Server sends the same line back to the client • Iterative server

  3. Client • Client reads a single line of text from standard input • Text is send in [#]text format. • # represents SCTP stream number where text is sent

  4. Server • Reads the text from the network • Increases the SCTP stream number by one (# in [#]text) • Sends the message back to the client on this new stream

  5. Client • Reads the reply message and prints it to standard output • Stream number, sequence number and text string is printed

  6. #include "unp.h" • int • { • int sock_fd,msg_flags; • char readbuf[BUFFSIZE]; • struct sockaddr_in servaddr, cliaddr; • main(int argc, char **argv) • struct sctp_sndrcvinfo sri; • struct sctp_event_subscribe evnts; • int stream_increment=1; • socklen_t len; • size_t rd_sz; • if (argc == 2) • stream_increment = atoi(argv[1]); • sock_fd = Socket(AF_INET, SOCK_SEQPACKET, IPPROTO_SCTP); • bzero(&servaddr, sizeof(servaddr)); • servaddr.sin_family = AF_INET; • servaddr.sin_addr.s_addr = htonl(INADDR_ANY); • servaddr.sin_port = htons(SERV_PORT); • Bind(sock_fd, (SA *) &servaddr, sizeof(servaddr)); • bzero(&evnts, sizeof(evnts)); • evnts.sctp_data_io_event = 1; • Setsockopt(sock_fd, IPPROTO_SCTP, SCTP_EVENTS, • &evnts, sizeof(evnts)); • Listen(sock_fd, LISTENQ); • for ( ; ; ) { • len = sizeof(struct sockaddr_in); • rd_sz = Sctp_recvmsg(sock_fd, readbuf, sizeof(readbuf), • (SA *)&cliaddr, &len, • &sri,&msg_flags); • if(stream_increment) { • sri.sinfo_stream++; • if(sri.sinfo_stream >= sctp_get_no_strms(sock_fd,(SA *)&cliaddr, len)) • sri.sinfo_stream = 0; • } • Sctp_sendmsg(sock_fd, readbuf, rd_sz, • (SA *)&cliaddr, len, • sri.sinfo_ppid, • sri.sinfo_flags, • sri.sinfo_stream, • 0, 0); • } • }

  7. Server: Stream increment • Stream increment option • If command line option is passed to program, program decides whether to increment stream number of incoming messages • if (argc == 2) • stream_increment = atoi(argv[1]);

  8. Server: Create an SCTP socket • sock_fd = Socket(AF_INET, SOCK_SEQPACKET, IPPROTO_SCTP);

  9. Server: Bind address • Bind any incoming address to certain server port. • bzero(&servaddr, sizeof(servaddr)); • servaddr.sin_family = AF_INET; • servaddr.sin_addr.s_addr = htonl(INADDR_ANY); • servaddr.sin_port = htons(SERV_PORT); • Bind(sock_fd, (SA *) &servaddr, sizeof(servaddr));

  10. Server: Set up for notification • Server changes its notification subscription for the one-to-many SCTP socket. • This allows server to see the stream number where the message arrived. • bzero(&evnts, sizeof(evnts)); • evnts.sctp_data_io_event = 1; • Setsockopt(sock_fd, IPPROTO_SCTP, SCTP_EVENTS, &evnts, sizeof(evnts));

  11. Server: Incoming associations • Server enables incoming associations so it can listen the server socket for incoming messages. • Listen(sock_fd, LISTENQ); • After which server will enter the main loop

  12. Server: Wait for messages • Initialize size of client socket address structure. • Block until message arrives. • len = sizeof(struct sockaddr_in); • rd_sz = Sctp_recvmsg(sock_fd, readbuf, sizeof(readbuf), (SA *)&cliaddr, &len, &sri,&msg_flags);

  13. Server: Increment stream number • Check increment flag and increase stream stream number is flag is set. • If number is too large then number is set to 0. • if(stream_increment) { • sri.sinfo_stream++; • if(sri.sinfo_stream >= sctp_get_no_strms(sock_fd, (SA *)&cliaddr, len)) • sri.sinfo_stream = 0; • }

  14. Server: Send message back • Sending back the message to the client • Sctp_sendmsg(sock_fd, readbuf, rd_sz, • (SA *)&cliaddr, len, • sri.sinfo_ppid, • sri.sinfo_flags, • sri.sinfo_stream, • 0, 0);

  15. Server: Finish? • Program runs forever until it is shutdown with an external signal. • for ( ; ; ) { • … • }

  16. #include "unp.h" • int • main(int argc, char **argv) • { • int sock_fd; • struct sockaddr_in servaddr; • struct sctp_event_subscribe evnts; • int echo_to_all=0; • if(argc < 2) • err_quit("Missing host argument - use '%s host [echo]'\n", • argv[0]); • if(argc > 2) { • printf("Echoing messages to all streams\n"); • echo_to_all = 1; • } • sock_fd = Socket(AF_INET, SOCK_SEQPACKET, IPPROTO_SCTP); • bzero(&servaddr, sizeof(servaddr)); • servaddr.sin_family = AF_INET; • servaddr.sin_addr.s_addr = htonl(INADDR_ANY); • servaddr.sin_port = htons(SERV_PORT); • Inet_pton(AF_INET, argv[1], &servaddr.sin_addr); • bzero(&evnts, sizeof(evnts)); • evnts.sctp_data_io_event = 1; • Setsockopt(sock_fd,IPPROTO_SCTP, SCTP_EVENTS, • &evnts, sizeof(evnts)); • if(echo_to_all == 0) • sctpstr_cli(stdin,sock_fd,(SA *)&servaddr,sizeof(servaddr)); • else • sctpstr_cli_echoall(stdin,sock_fd,(SA *)&servaddr,sizeof(servaddr)); • Close(sock_fd); • return(0); • }

  17. Client: Validate arguments • Arguments: host and echo flag. • if(argc < 2) • err_quit("Missing host argument - use '%s host [echo]'\n", argv[0]); • if(argc > 2) { • printf("Echoing messages to all streams\n"); • echo_to_all = 1; • }

  18. Client: Create a socket • Create an SCTP socket • sock_fd = Socket(AF_INET, SOCK_SEQPACKET, IPPROTO_SCTP);

  19. Client: Set up server address • Use given server address and well known port number to construct server address structure using Inet_pton(). • bzero(&servaddr, sizeof(servaddr)); • servaddr.sin_family = AF_INET; • servaddr.sin_addr.s_addr = htonl(INADDR_ANY); • servaddr.sin_port = htons(SERV_PORT); • Inet_pton(AF_INET, argv[1], &servaddr.sin_addr);

  20. Client: Set up for notifications • Explicitly setting notification subscription for one-to-many socket. • bzero(&evnts, sizeof(evnts)); • evnts.sctp_data_io_event = 1; • Setsockopt(sock_fd,IPPROTO_SCTP, SCTP_EVENTS, &evnts, sizeof(evnts));

  21. Client: Echo processing • If flag is not set then sctpstrcli() is called. • Else sctpstr_cli_echoall() is called. • if(echo_to_all == 0) • sctpstr_cli(stdin,sock_fd,(SA *)&servaddr,sizeof(servaddr)); • else • sctpstr_cli_echoall(stdin,sock_fd,(SA *)&servaddr,sizeof(servaddr)); • These functions are shown later.

  22. Client: Finish • When all is done, client closes socket and returns zero. • Close(sock_fd); • return(0);

  23. Client: sctpstr_cli() • #include "unp.h" • void • sctpstr_cli(FILE *fp, int sock_fd, struct sockaddr *to, socklen_t tolen) • { • struct sockaddr_in peeraddr; • struct sctp_sndrcvinfo sri; • char sendline[MAXLINE], recvline[MAXLINE]; • socklen_t len; • int out_sz,rd_sz; • int msg_flags; • bzero(&sri,sizeof(sri)); • while (fgets(sendline, MAXLINE, fp) != NULL) { • if(sendline[0] != '[') { • printf("Error, line must be of the form '[streamnum]text'\n"); • continue; • } • sri.sinfo_stream = strtol(&sendline[1],NULL,0); • out_sz = strlen(sendline); • Sctp_sendmsg(sock_fd, sendline, out_sz, • to, tolen, • 0, 0, • sri.sinfo_stream, • 0, 0); • len = sizeof(peeraddr); • rd_sz = Sctp_recvmsg(sock_fd, recvline, sizeof(recvline), • (SA *)&peeraddr, &len, • &sri,&msg_flags); • printf("From str:%d seq:%d (assoc:0x%x):", • sri.sinfo_stream,sri.sinfo_ssn, • (u_int)sri.sinfo_assoc_id); • printf("%.*s",rd_sz,recvline); • } • }

  24. Client: Initialize • Initialize structure and enter loop. • Block until user inputs line of text. • bzero(&sri,sizeof(sri)); • while (fgets(sendline, MAXLINE, fp) != NULL) {

  25. Client: Validate input • Validate given input from the user. • if(sendline[0] != '[') { • printf("Error, line must be of the form '[streamnum]text'\n"); • continue; • }

  26. Client: Stream number • Stream number is translated from the user input and put into the structure. • sri.sinfo_stream = strtol(&sendline[1],NULL,0);

  27. Client: Send message • Message is sent. • out_sz = strlen(sendline); • Sctp_sendmsg(sock_fd, sendline, out_sz, • to, tolen, 0, 0, • sri.sinfo_stream, 0, 0);

  28. Client: Wait for response • Program blocks until message is received back from the server. • len = sizeof(peeraddr); • rd_sz = Sctp_recvmsg(sock_fd, recvline, sizeof(recvline), • (SA *)&peeraddr, &len, • &sri,&msg_flags);

  29. Client: Display message • Received message is displayed to standard output. • printf("From str:%d seq:%d (assoc:0x%x):", • sri.sinfo_stream,sri.sinfo_ssn, • (u_int)sri.sinfo_assoc_id); • printf("%.*s",rd_sz,recvline);

  30. Client: Finish? • Program reads lines from user until it is terminated by an external signal.

  31. Head-of-Line blocking • Head-of-Line blocking occurs when TCP segment is lost and latter segments arrive out of order. • All the subsequent segments are held until the lost segment is retransmitted. • This ensures data arrives to the application in the order it was sent.

  32. SCTP blocking of streams • SCTP allows multiple streams over single connection. • Each stream can be transmitted independent of other streams. • Blocking of one stream for retransmission does not block other streams.

  33. Client: sctpstr_cli_echoall() • #include "unp.h" • #define SCTP_MAXLINE 800 • void • sctpstr_cli_echoall(FILE *fp, int sock_fd, struct sockaddr *to, socklen_t tolen) • { • struct sockaddr_in peeraddr; • struct sctp_sndrcvinfo sri; • char sendline[SCTP_MAXLINE], recvline[SCTP_MAXLINE]; • socklen_t len; • int rd_sz,i,strsz; • int msg_flags; • bzero(sendline,sizeof(sendline)); • bzero(&sri,sizeof(sri)); • while (fgets(sendline, SCTP_MAXLINE - 9, fp) != NULL) { • strsz = strlen(sendline); • if(sendline[strsz-1] == '\n') { • sendline[strsz-1] = '\0'; • strsz--; • } • for(i=0;i<SERV_MAX_SCTP_STRM;i++) { • snprintf(sendline + strsz, sizeof(sendline) - strsz, • ".msg.%d", i); • Sctp_sendmsg(sock_fd, sendline, sizeof(sendline), • to, tolen, • 0, 0, • i, • 0, 0); • } • for(i=0;i<SERV_MAX_SCTP_STRM;i++) { • len = sizeof(peeraddr); • rd_sz = Sctp_recvmsg(sock_fd, recvline, sizeof(recvline), • (SA *)&peeraddr, &len, • &sri,&msg_flags); • printf("From str:%d seq:%d (assoc:0x%x):", • sri.sinfo_stream,sri.sinfo_ssn, • (u_int)sri.sinfo_assoc_id); • printf("%.*s\n",rd_sz,recvline); • } • } • }

  34. Client: Initialize and read input • Initialize data structures. • Enter loop and read user input. • bzero(sendline,sizeof(sendline)); • bzero(&sri,sizeof(sri)); • while (fgets(sendline, SCTP_MAXLINE - 9, fp) != NULL) {

  35. Client: Process user input • Process given user input. • strsz = strlen(sendline); • if(sendline[strsz-1] == '\n') { • sendline[strsz-1] = '\0'; • strsz--; • }

  36. Client: Send message • Send message to each stream. • Append .msg. and stream number to each message for visual help of tracking messages. • for(i=0;i<SERV_MAX_SCTP_STRM;i++) { • snprintf(sendline + strsz, sizeof(sendline) - strsz, • ".msg.%d", i); • Sctp_sendmsg(sock_fd, sendline, sizeof(sendline), • to, tolen, 0, 0, i, 0, 0); • }

  37. Client: Read, display and loop • Block until incoming data comes from streams. • Display message and move to read next. • for(i=0;i<SERV_MAX_SCTP_STRM;i++) { • len = sizeof(peeraddr); • rd_sz = Sctp_recvmsg(sock_fd, recvline, sizeof(recvline), • (SA *)&peeraddr, &len, &sri,&msg_flags); • printf("From str:%d seq:%d (assoc:0x%x):", • sri.sinfo_stream,sri.sinfo_ssn, (u_int)sri.sinfo_assoc_id); • printf("%.*s\n",rd_sz,recvline); • } • After last message is read, loop back to user input.

  38. Client: Modifications • Send two messages to each stream to see messages are being held for reordering. • for(i=0;i<SERV_MAX_SCTP_STRM;i++) { • snprintf(sendline + strsz, sizeof(sendline) - strsz, ".msg.%d 1", i); • Sctp_sendmsg(sock_fd, sendline, sizeof(sendline), • to, tolen, 0, 0, i, 0, 0); • snprintf(sendline + strsz, sizeof(sendline) - strsz, ".msg.%d 2", i); • Sctp_sendmsg(sock_fd, sendline, sizeof(sendline), • to, tolen, 0, 0, i, 0, 0); • } • for(i=0;i<SERV_MAX_SCTP_STRM*2;i++) { • len = sizeof(peeraddr);

  39. Number of streams • FreeBSD KAME implementation: default 10 streams at start. • Change must be made on the socket before an association is made. • if (argc == 2) • stream_increment = atoi(argv[1]); • sock_fd = Socket(AF_INET, SOCK_SEQPACKET, IPPROTO_SCTP); • bzero(&initm,sizeof(initm)); • initm.sinit_num_ostreams = SERV_MORE_STRMS_SCTP; • Setsockopt(sock_fd, IPPROTO_SCTP, SCTP_INITMSG, • &initm, sizeof(initm));

  40. Termination • Two possible methods for closing one-to-many association: • Close after sending message (eof) • Close immediately (abort)

  41. Termination: eof • Server wishes to shutdown an association after sending message • Set flag MSG_EOF in the reply message structure. • Sctp_sendmsg(sock_fd, readbuf, rd_sz, • (SA *)&cliaddr, len, sri.sinfo_ppid, • (sri.sinfo_flags | MSG_EOF), sri.sinfo_stream, 0, 0); • }

  42. Termination: abort • Server wishes to shutdown an association immediately. • Set flag MSG_ABORT in the reply message structure. • Forces immediate termination with an ABORT chunk. • Any data not transmitted will be discarded. • strcpy(byemsg,"goodbye"); • Sctp_sendmsg(sock_fd, byemsg, strlen(byemsg), • (SA *)&servaddr, sizeof(servaddr), 0, MSG_ABORT, 0, 0, 0); • Close(sock_fd); • Even if association has been aborted, socket descriptor still needs to be freed with Close().

  43. Summary • Simple SCTP client and iterative server • Head-of-Line blocking problem • Number of streams • Shutdown and abort associations • More on SCTP on chapter 23

More Related