[ Team LiB ] |
23.10 Peeling Off an AssociationWe have been focusing on the one-to-many-style interface provided by SCTP. This interface has several advantages over the more classic one-to-one style:
However, there is one major drawback to this style. It makes it difficult to build a concurrent server (either using threads or by forking children). This drawback has brought about the addition of the sctp_peeloff function. sctp_peeloff takes a one-to-many socket descriptor and an association ID and returns a new socket descriptor with just that association (plus any queued notifications and data on that association) attached in a one-to-one style. The original socket remains open, and any other associations represented by the one-to-many socket are left unaffected. This socket can then be handed off to either a thread or a child process to execute a concurrent server. Figure 23.15 illustrates a further modification to our server that processes the first message of a client, extracts the client socket descriptor using sctp_peeloff, forks a child, and calls our original TCP str_echo function introduced in Section 5.3. We use the address of the received message to call our function that gets us the association ID (Section 23.8). The association ID is also available in sri.sinfo_assoc_id; we show this method of determining the association ID from the IP address to illustrate another method. After forking the child, our server loops back to process the next message. Figure 23.15 A concurrent SCTP server.sctp/sctpserv_fork.c 23 for ( ; ; ) { 24 len = sizeof(struct sockaddr_in); 25 rd_sz = Sctp_recvmsg(sock_fd, readbuf, sizeof(readbuf), 26 (SA *) &cliaddr, &len, &sri, &msg_flags); 27 Sctp_sendmsg(sock_fd, readbuf, rd_sz, 28 (SA *) &cliaddr, len, 29 sri.sinfo_ppid, 30 sri.sinfo_flags, sri.sinfo_stream, 0, 0); 31 assoc = sctp_address_to_associd(sock_fd, (SA *) &cliaddr, len); 32 if ((int) assoc == 0) { 33 err_ret("Can't get association id"); 34 continue; 35 } 36 connfd = sctp_peeloff(sock_fd, assoc); 37 if (connfd == -1) { 38 err_ret("sctp_peeloff fails"); 39 continue; 40 } 41 if ( (childpid = fork()) == 0) { 42 Close(sock_fd); 43 str_echo(connfd); 44 exit(0); 45 } else { 46 Close(connfd); 47 } 48 } Receive and process first message from client26–30 The server receives and processes the first message a client sends. Translate address to association ID31–35 The server next uses our function from Figure 23.13 to translate the address to an association ID. If for some reason the server cannot get an association ID, it skips this attempt to fork a child and instead will try with the next message. Extract association36–40 The server extracts the association into its own socket descriptor with sctp_peeloff. This results in a one-to-one socket that can be passed to our earlier TCP version of str_echo. Delegate work to child41–47 The server forks a child and lets the child perform all future work on this new socket descriptor. |
[ Team LiB ] |