SCTP 套接字编程基础函数

    SCTP 服务器可以使用 sctp_bindx 函数捆绑与所在主机系统相关 IP 地址的一个子集,而 TCP 服务器和 UDP 服务器要么捆绑所在主机的某个地址,要么捆绑所有地址,而不能捆绑这些地址的一个子集。
#include <netinet/sctp.h>
int sctp_bindx(int sockfd, const struct sockaddr *addrs, int addrcnt, int flags);
                                       /* 返回值:若成功,返回 0;否则,返回 -1 */

    其中,sockfd 是 socket 函数返回的套接字描述符,addrs 是一个指向紧凑的地址列表的指针,地址个数由 addrcnt 参数指定。每个套接字地址结构紧跟在前一个之后,中间没有填充字节,如下图所示。

    flags 参数指导 sctp_bindx 调用执行下表所示的两种行为之一。

    sctp_bindx 调用既可用于已绑定的套接字,也可用于未绑定的套接字。对于未绑定的套接字,sctp_bindx 将把给定的地址集合捆绑到其上。对于已绑定的套接字,若指定 SCTP_BINDX_ADD_ADDR,则把额外的地址加入到套接字描述符,若指定 SCTP_BINDX_REM_ADDR,则从套接字描述符的已加入地址中移除给定的地址。如果在一个监听套接字上调用该函数,那么新的地址配置将只会影响新产生的关联。所有套接字地址结构的端口号必须相同,并且要与已经绑定的端口号相匹配,否则调用将产生 EINVAL 错误码。
    如果一个端点支持动态地址特性,那么 sctp_bindx 将导致该端点向对端发送一个合适的消息,以修改对端的地址列表。由于增减一个已连接关联的地址只是一个可选的功能,因此不支持此功能的实现将返回 EOPNOTSUPP。本特性对于支持动态接口供给的系统可能有用,比如如果调出一个新的以太网接口,那么应用进程可以指定 SCTP_BINDX_ADD_ADDR 标志来在已经存在的连接上启动使用这个接口。
    SCTP 中还有下面一组常用的函数。
#include <netinet/sctp.h>
int sctp_connectx(int sockfd, const struct sockaddr *addrs, int addrcnt);
                                       /* 返回值:若成功,返回 0;否则,返回 -1 */
int sctp_getpaddrs(int sockfd, sctp_assoc_t id, struct sockaddr **addrs);
            /* 返回值:若成功,返回存放在 addrs 中的对端地址数;否则,返回 -1 */
void sctp_freepaddrs(struct sockaddr *addrs);

int sctp_getladdrs(int sockfd, sctp_assoc_t id, struct sockaddr **addrs);
            /* 返回值:若成功,返回存放在 addrs 中的本端地址数;否则,返回 -1 */
void sctp_freeladdrs(struct sockaddr *addrs);

ssize_t sctp_sendmsg(int sockfd, const void *msg, size_t msgsz,
                     const struct sockaddr *to, socklen_t tolen,
                     uint32_t ppid, uint32_t flags, uint16_t stream,
                     uint32_t timetolive, uint32_t context);
ssize_t sctp_recvmsg(int sockfd, void *msg, size_t msgsz,
                     struct sockaddr *from, socklen_t *fromlen,
                     struct sctp_sndrcvinfo *sinfo, int *msg_flags);
             /* 两个函数的返回值:若成功,则为所写或所读的字节数;否则,为 -1 */

int sctp_opt_info(int sockfd, sctp_assoc_t assoc_id, int opt, void *arg, socklen_t *siz);
                                    /* 返回值:若成功,返回 0;否则,返回 -1 */
int sctp_peeloff(int sockfd, sctp_assoc_t id);
                   /* 返回值:若成功,返回一个新的套接字描述符;否则,返回 -1 */

    sctp_connectx 函数用于连接到一个多宿对端主机。该函数在 addrs 参数中指定 addrcnt 个全部属于同一对端的地址,addrs 中的所有地址都被会认为是有效的经过证实的地址,SCTP 栈使用其中一个或多个地址建立关联。
    由于 getpeername 函数用于 SCTP 时仅仅返回主目的地址,所以如果需要知道对端的所有地址,应该使用 sctp_getpaddrs 函数。其中的 id 参数是一到多式套接字的关联标识,一到一式套接字会忽略该字段。addrs 参数的地址内容是由本函数动态分配并填入的紧凑的地址列表,用完后应该使用 sctp_freepaddrs 函数释放所分配的资源。
    sctp_getladdrs 和 sctp_freeladdrs 函数的用法同 sctp_getpaddrs 和 sctp_freepaddrs,只是它们是针对本端的。
    相比较于 sendmsg 函数,sctp_sendmsg 函数以指定更多参数为代价简化了发送方法,它将长度为 msgsz 字节的缓冲区 msg 内容发送给对端 to,tolen 参数指定了存放在 to 中的地址长度。ppid 参数指定将随数据块传递的净荷协议标识符。flags 参数将传递给 SCTP 栈,用以标识任何 SCTP 选项(如果实现把 sctp_sendmsg 映射成 sendmsg 函数,则 sendmsg 的 flags 参数会被设为 0),其有效取值同 SCTP 套接字选项一节中提到的 sctp_sndrcvinfo 结构中的 sinfo_flags 字段。
    stream 参数指定一个 SCTP 流号。timetolive 参数以毫秒为单位指定消息的生命期,其中 0 表示无限生命期。context 参数用于指定可能有的用户上下文,用户上下文把通过消息通知机制收到的某次失败消息发送与某个特定于应用的本地上下文关联起来。
    类似于 sctp_sendmsg,sctp_recvmsg 函数也为 SCTP 的高级特性提供了一个更方便的接口。使用本函数不仅能获取对端的地址,也能获取通常伴随 recvmsg 函数调用返回的 msg_flags 参数,其中存放了可能有的消息标志。此外,如果使用 SCTP_EVENTS 套接字选项预订了 sctp_data_io_event(默认情况下开启),那么就会有与消息相关的细节信息来填充 sctp_sndrcvinfo 结构。
    sctp_opt_info 函数是为无法为 SCTP 使用 getsockopt 函数的那些实现提供的,因为有些 SCTP 套接字选项(如 SCTP_STATUS)需要一个入出(in_out)变量传递关联标识。对于无法为 getsockopt 函数提供入出变量的系统来说,就只能使用 sctp_opt_info 函数。这里的assoc_id 参数给出可能存在的关联标识,opt 参数是 SCTP 的套接字选项,arg 给出套接字选项参数,siz 则用于存放参数的大小。
    sctp_peeloff 函数可用于从一个一到多式套接字中抽取一个关联,单独构成一个一到一式套接字。其语义就像带有一个额外参数的 accept 函数,调用者把一个一到多式套接字的 sockfd 和待抽取的关联标识 id 传递给函数调用,调用结束时将返回一个新的套接字描述符,它是一个与所请求关联对应的一到一式套接字描述符。

猜你喜欢

转载自aisxyz.iteye.com/blog/2408054