SCTP和TCP、UDP有些不一样,在写应用程序的时候需要注意一下。
1. 可以bind多个IP地址
这个是SCTP的特点,两端都可以用多个IP地址和对端来通信,因此不管是client端,还是server端,都可以bind多个IP地址(端口号必须相同)。
比如:
// bind第一个地址
bind(fd, (struct sockaddr *)&cliaddr1, sizeof(cliaddr));
// bind第二个地址
sctp_bindx(fd, (struct sockaddr *)&cliaddr2, 1, SCTP_BINDX_ADD_ADDR);
cliaddr1和cliaddr2里面,IP地址不同,PORT相同。
2. 需要注册事件通知
为了能调用sctp_recvmsg()收到对端发送的DATA,需要事先为该socket注册一个事件通知功能:
struct sctp_event_subscribe events;
events.sctp_data_io_event = 1;
setsockopt(fd, SOL_SCTP, SCTP_EVENTS, (const void *)&events, sizeof(events));
不注册这个事件通知,是不能通过调用sctp_recvmsg()接收对端的DATA的。
类似的,注册其他事件类型之后,可以通过sctp_recvmsg()收到SCTP_COMM_UP(连接建立完成)、SCTP_SHUTDOWN_EVENT(连接被关闭)等通知。
events.sctp_association_event = 1;
events.sctp_shutdown_event = 1;
sctp_recvmsg()接口使用方法如下:
ret = sctp_recvmsg((int) fd,
(void *)buf,
(size_t)MAX_BUFF_SIZE,
(struct sockaddr *)from,
&fromlen,
(struct sctp_sndrcvinfo *)&rcvinfo,
(int *)&l_msg_flags);
通过l_msg_flags就能知道收到的buf中,到底是NOTIFICATION还是DATA(对端应用层的一条消息),以及DATA有没有接收完整:
if (l_msg_flags & MSG_NOTIFICATION) { //收到一条通知消息
l_notif = (union sctp_notification *)buf;
if (l_notif->sn_header.sn_type == SCTP_ASSOC_CHANGE) {
l_asschg = &l_notif->sn_assoc_change;
switch (l_asschg->sac_state) {
case SCTP_COMM_UP:
...
}
} else if (l_notif->sn_header.sn_type == SCTP_SHUTDOWN_EVENT) {
l_shutdown = &l_notif->sn_shutdown_event;
if (l_shutdown->sse_type == SCTP_SHUTDOWN_EVENT) {
DEBUG_PRINT(fd, "notification = SCTP_SHUTDOWN_EVENT\n");
clean_fd(fd);
}
}
} else if (l_msg_flags & MSG_EOR) { //收到一条完整的DATA
if (!g_data_performance_test) {
printf("[sctp_recvmsg] fd = %d, %s\n", fd, buf);
} else { //收到一条不完整的DATA
g_message_received++;
g_message_total_size += ret;
}