SCTP连接的关闭方式有两种:
- ABORT(暴力关闭):直接释放资源,应用层未被传输、接收的数据都会被丢弃
- SHUTDOWN(平滑关闭):通过三条消息,把该传的该发的数据先处理完,再关闭
1. ABORT
ABORT一般用于异常关闭一条SCTP连接,可能导致应用层丢消息。ABORT CHUNK的格式如下:
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Type = 6 |Reserved |T| Length |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
\ \
/ zero or more Error Causes /
\ \
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
在该CHUNK中,可以携带一个或多个导致关闭的Error Causes,Error Cause的定义如下:
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Cause Code | Cause Length |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
/ Cause-Specific Information /
\ \
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Cause Code
Value Cause Code
--------- ---------------
1 Invalid Stream Identifier
2 Missing Mandatory Parameter
3 Stale Cookie Error
4 Out of Resource
5 Unresolvable Address
6 Unrecognized Chunk Type
7 Invalid Mandatory Parameter
8 Unrecognized Parameters
9 No User Data
10 Cookie Received While Shutting Down
11 Restart of an Association with New Addresses
12 User Initiated Abort
13 Protocol Violation
SCTP异常关闭的故障分析一般需要分析ABORT的原因。
值得注意的是,ABORT也可能是应用程序主动发起的,此时的Cause Code是12。应用程序ABORT一条SCTP连接的方法如下:
void close_association(int fd, char model)
{
struct linger l_lger;
int ret;
if (fd <= 0) {
printf("[close a bad fd] fd = %d\n", fd);
return;
}
if (model == CLOSE_MD_ABORT) {
memset(&l_lger, 0, sizeof(l_lger));
l_lger.l_onoff = 1;
l_lger.l_linger = 0;
ret = setsockopt(fd, SOL_SOCKET, SO_LINGER, &l_lger, sizeof(l_lger));
if (ret < 0) {
printf("[set SO_LINGER error] %d:%s\n", errno, strerror(errno));
return;
}
}
clean(fd);
printf("[closed] fd = %d\n", fd);
}
把socket的SO_LINGER选项设置为1,则调用close()关闭连接的时候,会采用ABORT的方式;否则,采用SHUTDOWN的方式。
2. SHUTDOWN
SHUTDOWN方式,需要三条SCTP控制CHUNK(SHUTDOWN, SHUTDOWN ACK, SHUTDOWN COMPLETE)。
- SHUTDOWN: 主动关闭方的应用程序调用close()准备关闭连接的时候,SCTP在收到所有发送出去的DATA CHUNK的ACK之后(即应用层数据发送完毕),发送一个SHUTDOWN CHUNK给对端;
- SHUTDOWN ACK: 被动关闭方收到SHUTDOWN CHUNK之后,不再接收应用层的数据发送请求(此时应用层调用sctp_sendmsg()会失败),但是会把当前未发送完毕的数据发送到对端,直到收到对端的ACK,或者是重传次数超过了门限;然后向对端发送SHUTDOWN COMPLETE;
- SHUTDOWN COMPLETE:主动关闭方收到该CHUNK,表示连接关闭完成。
具体的描述可以参考RFC 4960的9.2节。
在看到SCTP连接是采用SHUTDOWN的方式关闭的时候,肯定是应用程序主动关闭的,而不是SCTP层检测到错误引起的。