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;
}