SCTP中的流不同于TCP中的字节流,它是关联内部具有先后顺序的一个消息序列。这种以流本身而不是以流所在关联为单位进行消息排序的做法用于避免仅使用单个TCP字节流导致的头端阻塞现象。
SCTP流可以说是一个既能避免头端阻塞又能在相关的消息之间保持顺序的有效机制(如同一个流内的消息会按顺序到达)
控制流的数目:
允许在关联启动阶段增长端点请求的流数目;但需注意,这个变动必须针对尚未建立关联的套接字进行
/*
* if(argc == 2)
* stream_increment = atoi(argv[1]);
* struct sctp_initmsg initm;
* int sock_fd = Socket(AF_INET, SOCK_SEQPACKET, IPPROTO_SCTP);
* bzero(&initm, sizeof(initm));
* initm.sinit_num_ostreams = SERV_MORE_STRMS_SCTP;
* Setsockopt(sockfd_fd, IPPROTO_SCTP, SCTP_INITMSG, &initm, sizeof(initm))
* /
服务器先清零sctp_initmsg结构,以确保setsockopt调用不会无意中改动任何其他值。服务器接着把sinit_num_ostreams字段设置成期望请求的流数目,然后以初始消息参数设置套接字选项。
设置套接字选项的另一种方法是:使用sendmsg函数并提供辅助数据以请求不同于默认设置的流参数。这种类型的辅助数据仅仅适用于一到多式套接字。
如果服务器希望在发送完一个应答消息后终止一个关联,那么可以在与该消息对应的sctp_sndrcvinfo结构的sinfo_flags字段中设置MSG_EOF标志。该标志迫使所发送消息被客户确认之后,相应关联也被终止。
另一个方法是把MSG_ABORT标志应用于sinfo_flags字段。该标志将以ABORT块迫使立即终止关联。SCTP的ABORT块类似TCP的RST分节,能够无延迟地中止任何关联,尚未发送的任何数据都被丢弃。然而以ABORT块关闭一个SCTP会话并没有诸如防止TCP的TIME_WAIT状态之类的不良影响, ABORT 块导致的是直接性的中止性关闭。
/* 服务器程序应答同时终止关联的改动,仅仅是给sctp_sendmsg函数的标志参数或上MSG_EOF标志。该标志促成服务器在应答消息被客户成功确认之后关闭关联。
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 | MSG_EOF, sri.sinfo_stream, 0, 0));
}
*/
/*客户预先终止关联,发送ABORT块,立即终止当前关联。
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));
strcpy(byemsg, "goodbye");
Sctp_sendmsg(sock_fd, byemsg, strlen(byemsg), (SA *)&servaddr, sizeof(servaddr), 0, MSG_ABORT, 0 ,0 ,0);
Close(sock_fd);
*/
小结:
客户端和服务器程序都使用一到多式SCTP接口。服务器程序按照迭代式样构造,这也是使用一到多式接口时的常用式样。服务器接受每个请求消息之后,应答消息或者发送到请求消息到来的流上,或者发送到编号稍高的流上。
我们接着查看了头端阻塞问题。通过修改客户程序强调本问题,我们表明SCTP流可用于避免这个问题。我们使用众多可用于控制SCTP行为的套接字选项之一查看了如何操纵流的数目。
最后,我们再次修改服务器和客户程序,使得它们或能中止一个关联(并包含一个用户上层原因代码),或能(对于我们的服务器情形)在发送一个消息之后优雅地终止关联。