`

linux c学习笔记----SCTP基础客户/服务编程(setsockopt,sctp_sendmsg等)

阅读更多

在编程之前先了解一下sctp套接字选项

 

setsockopt(设置socket状态)

 

相关函数
getsockopt
表头文件
#include<sys/types.h>
#include<sys/socket.h>
定义函数
int setsockopt(int s,int level,int optname,const void * optval,,socklen_toptlen);
函数说明
setsockopt()用来设置参数s所指定的socket状态。参数level代表欲设置的网络层,一般设成SOL_SOCKET以存取socket层。参数optname代表欲设置的选项,有下列几种数值:
SO_DEBUG 打开或关闭排错模式
SO_REUSEADDR 允许在bind()过程中本地地址可重复使用
SO_TYPE 返回socket形态。
SO_ERROR 返回socket已发生的错误原因
SO_DONTROUTE 送出的数据包不要利用路由设备来传输。
SO_BROADCAST 使用广播方式传送
SO_SNDBUF 设置送出的暂存区大小
SO_RCVBUF 设置接收的暂存区大小
SO_KEEPALIVE 定期确定连线是否已终止。
SO_OOBINLINE 当接收到OOB 数据时会马上送至标准输入设备
SO_LINGER 确保数据安全且可靠的传送出去。
参数
optval代表欲设置的值,参数optlen则为optval的长度。
返回值
成功则返回0,若有错误则返回-1,错误原因存于errno。
附加说明
EBADF 参数s并非合法的socket处理代码
ENOTSOCK 参数s为一文件描述词,非socket
ENOPROTOOPT 参数optname指定的选项不正确。
EFAULT 参数optval指针指向无法存取的内存空间。

设置 sctp时level为IPPROTO_SCTP,optname即为sctp套接字选项

这里只介绍SCTP_INITMSG选项:

本套接字选项用于获取或设置某个SCTP套接字在发送INIT消息时所用的默认初始参数。作为本选项的输入的是sctp_initmsg结构(即为setsockopt函数的第五个参数)。其定义如下:

struct sctp_initmsg{

      uint16_t sinit_num_ostream;

      uint16_t sinit_max_instream;

      unit16_t sinit_max_attempts;

      unit16_t sinit_max_init_timeo;

}

这些字段的含义如下:

sinit_num_ostream表示应用进程想要请求的外出sctp流的数目。该值要等到相应关联完成初始握手后才得到确认,而且可能因为对端的限制而向下协调。

sinit_max_instream表示应用进程准备允许的外来SCTP流的最大数目。如果该值大于SCTP协议栈支持的最大允许流数,那么它将被为这个最大数。

sinit_max_attempts表示SCTP协议栈应该重传多少次初始INIT消息才认为对端不可达。

sinit_max_init_timeo表示用于INIT定时器的最大RTO值。在初始定时器进行指数退避期间,该值将替代RTO.max作为重传RTO极限。该值以毫秒为单位。

注意:当设置这些字段时,SCTP将忽略其中的任何0值。一到多式套接字的用户在关联隐性建立期间也可能在辅助数据中传递一个sctp_initmsg结构。

 

 

 

SCTP 套接字接口

当 socket() 调用为 IPPROTO_SCTP 创建套接字时,它会调用特定于 SCTP 的套接字创建例程。针对 SCTP 套接字执行的套接字调用会自动调用相应的 SCTP 套接字例程。在一对一套接字中,每个套接字都对应一个 SCTP 关联。可以通过调用以下函数来创建一对一套接字:

socket(AF_INET[6], SOCK_STREAM, IPPROTO_STCP); 

在一对多风格套接字中,每个套接字都处理多个 SCTP 关联。每个关联都具有一个名为 sctp_assoc_t 的关联标识符。可以通过调用以下函数来创建一对多套接字:

socket(AF_INET[6], SOCK_SEQPACKET, IPPROTO_STCP); 

sctp_bindx()

int sctp_bindx(int sock, void *addrs, int addrcnt, int flags); 

sctp_bindx() 函数管理 SCTP 套接字上的地址。如果 sock 参数为 IPv4 套接字,则传送给 sctp_bindx() 函数的地址必须为 IPv4 地址。如果 sock 参数为 IPv6 套接字,则传送给 sctp_bindx() 函数的地址可以为 IPv4 或 IPv6 地址。当传送给 sctp_bindx() 函数的地址为INADDR_ANY 或 IN6ADDR_ANY 时,此套接字将绑定到所有可用地址。可以使用 bind(3SOCKET) 绑定 SCTP 端点。

*addrs 参数的值是指向包含一个或多个套接字地址的数组的指针。每个地址都包含在其相应的结构中。如果地址为 IPv4 地址,则它们可以包含在sockaddr_in 结构或 sockaddr_in6 结构中。如果地址为 IPv6 地址,则它们可以包含在 sockaddr_in6 结构中。可以通过地址类型系列区分地址长度。调用方使用 addrcnt 参数指定数组中的地址数。

如果成功,则 sctp_bindx() 函数将返回 0。如果失败,则 sctp_bindx() 函数将返回 -1,并将 errno 的值设置为相应的错误代码。

如果没有为每个套接字地址提供同一端口,则 sctp_bindx() 函数将失败,并将 errno 的值设置为 EINVAL

通过对以下零个或多个当前定义的标志执行按位 OR 运算,即可形成 flags 参数:

  • SCTP_BINDX_ADD_ADDR

  • SCTP_BINDX_REM_ADDR

SCTP_BINDX_ADD_ADDR 指示 SCTP 将给定地址添加到关联中。SCTP_BINDX_REM_ADDR 指示 SCTP 从关联中删除给定地址。这两个标志相互排斥。如果同时提供这两个标志,则 sctp_bindx() 将失败,并将 errno 的值设置为 EINVAL

调用方无法删除关联中的所有地址。sctp_bindx() 函数拒绝此类尝试的表现为:函数失败并将 errno 的值设置为 EINVAL。应用程序可以在调用 bind() 函数之后使用 sctp_bindx(SCTP_BINDX_ADD_ADDR),将其他地址与端点关联。应用程序可以使用sctp_bindx(SCTP_BINDX_REM_ADDR) 删除与侦听套接字关联的地址。使用 sctp_bindx(SCTP_BINDX_REM_ADDR) 删除地址之后,接受新关联将不会重新关联已删除的地址。如果端点支持动态地址,则可以使用 SCTP_BINDX_REM_ADDR 或 SCTP_BINDX_ADD_ADDR 向对等方发送消息来更改对等方的地址列表。在已连接的关联中添加和删除地址为可选功能。不支持此功能的实现将返回 EOPNOTSUPP

如果地址族不是 AF_INET 或 AF_INET6,则 sctp_bindx() 函数将失败并返回 EAFNOSUPPORT。如果 sock 参数中传递给 sctp_bindx() 的文件描述符无效,则 sctp_bindx() 函数将失败并返回 EBADF

sctp_opt_info()

int sctp_opt_info(int sock, sctp_assoc_id_t id, int opt, void *arg, socklen_t *len); 

sctp_opt_info() 函数将返回与 sock 参数中所述的套接字关联的 SCTP 级别选项。如果此套接字为一对多风格 SCTP 套接字,则 id 参数的值是某个特定关联。对于一对一风格 SCTP 套接字,将忽略 id 参数。opt 参数的值指定要获取的 SCTP 套接字选项。arg 参数的值是为调用程序而分配的特定于选项的结构缓冲区。*len 参数的值为选项长度。

opt 参数可以采用以下值:

SCTP_RTOINFO

返回用于初始化和绑定重新传输超时 (retransmission timeout, RTO) 可调参数的协议参数。这些协议参数使用以下结构:

struct sctp_rtoinfo {

       sctp_assoc_t srto_assoc_id;

       uint32_t     srto_initial;

       uint32_t     srto_max; 

       uint32_t     srto_min;

};
srto_assoc_id

调用程序提供此值,它指定所关注的关联。

srto_initial

此值为初始 RTO 值。

srto_max

此值为最大 RTO 值。

srto_min

此值为最小 RTO 值。

SCTP_ASSOCINFO

返回特定于关联的参数。这些参数使用以下结构:

struct sctp_assocparams {

     sctp_assoc_t sasoc_assoc_id;

     uint16_t     sasoc_asocmaxrxt;

     uint16_t     sasoc_number_peer_destinations;

     uint32_t     sasoc_peer_rwnd;

     uint32_t     sasoc_local_rwnd;

     uint32_t     sasoc_cookie_life;

};
sasoc_assoc_id

调用程序提供此值,它指定所关注的关联。

sasoc_assocmaxrxt

此值指定关联的最大重新传输计数。

sasoc_number_peer_destinations

此值指定对等方具有的地址数。

sasoc_peer_rwnd

此值指定对等方接收窗口的当前值。

sasoc_local_rwnd

此值指定对等方传输到的上一个已报告的接收窗口。

sasoc_cookie_life

此值指定关联 cookie 的生命周期。可在发出 cookie 时使用此值。

所有使用时间值的参数均以毫秒为单位。

SCTP_DEFAULT_SEND_PARAM

返回 sendto(3SOCKET) 函数调用在此关联中使用的缺省参数集。这些参数使用以下结构:

struct sctp_sndrcvinfo {

     uint16_t     sinfo_stream;

     uint16_t     sinfo_ssn;

     uint16_t     sinfo_flags;

     uint32_t     sinfo_ppid;

     uint32_t     sinfo_context;

     uint32_t     sinfo_timetolive;

     uint32_t     sinfo_tsn;

     uint32_t     sinfo_cumtsn;

     sctp_assoc_t sinfo_assoc_id;

};
sinfo_stream

此值指定 sendmsg() 调用的缺省流。

sinfo_ssn

此值始终为 0。

sinfo_flags

此值包含 sendmsg() 调用的缺省标志。此标志可以采用以下值:

  • MSG_UNORDERED

  • MSG_ADDR_OVER

  • MSG_ABORT

  • MSG_EOF

  • MSG_PR_SCTP

sinfo_ppid

此值为 sendmsg() 调用的缺省有效负荷协议标识符。

sinfo_context

此值为 sendmsg() 调用的缺省上下文。

sinfo_timetolive

此值指定时间段(以毫秒为单位)。在此时间段过后,如果消息传输尚未开始,则消息将过期。值为 0 指示消息尚未过期。如果设置了MSG_PR_SCTP 标志,当消息传输未在 sinfo_timetolive 所指定的时间段内成功完成时,消息将过期。

sinfo_tsn

此值始终为 0。

sinfo_cumtsn

此值始终为 0。

sinfo_assoc_id

此值由调用程序填充。它指定所关注的关联。

SCTP_PEER_ADDR_PARAMS

返回所指定对等地址的参数。这些参数使用以下结构:

struct sctp_paddrparams {

     sctp_assoc_t            spp_assoc_id;

     struct sockaddr_storage spp_address;

     uint32_t                spp_hbinterval;

     uint16_t                spp_pathmaxrxt;

};
spp_assoc_id

调用程序提供此值,它指定所关注的关联。

spp_address

此值指定所关注的对等地址。

spp_hbinterval

此值指定心跳间隔(以毫秒为单位)。

spp_pathmaxrxt

此值指定在认为地址不可访问之前针对此地址尝试的最大重新传输数。

SCTP_STATUS

返回有关关联的当前状态信息。这些参数使用以下结构:

struct sctp_status {

     sctp_assoc_t          sstat_assoc_id;

     int32_t               sstat_state;

     uint32_t              sstat_rwnd;

     uint16_t              sstat_unackdata;

     uint16_t              sstat_penddata;

     uint16_t              sstat_instrms;

     uint16_t              sstat_outstrms;

     uint32_t              sstat_fragmentation_point;

     struct sctp_paddrinfo sstat_primary;

};
sstat_assoc_id

调用程序提供此值,它指定所关注的关联。

sstat_state

此值为关联的当前状态。关联可以采用以下状态:

SCTP_IDLE

SCTP 端点没有任何与其关联的关联。一旦 socket() 函数调用打开一个端点或端点关闭,则端点便会处于此状态。

SCTP_BOUND

SCTP 端点在调用 bind() 之后绑定到一个或多个本地地址。

SCTP_LISTEN

此端点在等待来自任何远程 SCTP 端点的关联请求。

SCTP_COOKIE_WAIT

此 SCTP 端点已发送 INIT 块并在等待 INIT-ACK 块。

SCTP_COOKIE_ECHOED

此 SCTP 端点已将从其对等方的 INIT-ACK 块接收的 cookie 回显到对等方。

SCTP_ESTABLISHED

此 SCTP 端点可以与其对等方交换数据。

SCTP_SHUTDOWN_PENDING

此 SCTP 端点已从其上层接收了 SHUTDOWN 元语。此端点不再从其上层接受数据。

SCTP_SHUTDOWN_SEND

处于 SCTP_SHUTDOWN_PENDING 状态的 SCTP 端点已向其对等方发送了 SHUTDOWN 块。仅在确认所有从此端点到其对等方的未完成数据之后,才发送 SHUTDOWN 块。当此端点的对等方发送 SHUTDOWN ACK 块时,此端点会发送 SHUTDOWN COMPLETE 块并认为关联已关闭。

SCTP_SHUTDOWN_RECEIVED

SCTP 端点已从其对等方接收了 SHUTDOWN 块。此端点不再从其用户接受新数据。

SCTP_SHUTDOWN_ACK_SEND

处于 SCTP_SHUTDOWN_RECEIVED 状态的 SCTP 端点已向其对等方发送了 SHUTDOWN ACK 块。此端点仅在其对等方确认来自此端点的所有未完成数据之后发送 SHUTDOWN ACK 块。当此端点的对等方发送 SHUTDOWN COMPLETE 块时,将关闭关联。

sstat_rwnd

此值为关联对等方的当前接收窗口。

sstat_unackdata

此值为未确认的 DATA 块数。

sstat_penddata

此值为等待接收的 DATA 块数。

sstat_instrms

此值为传入的流数。

sstat_outstrms

此值为外发的流数。

sstat_fragmentation_point

如果消息、SCTP 数据包头和 IP 数据包头的组合大小超出 sstat_fragmentation_point 的值,则消息会分段。此值等于包目标地址的路径最大传输单元 (Path Maximum Transmission Unit, P-MTU)。

sstat_primary

此值包含有关主要对等地址的信息。此信息使用以下结构:

struct sctp_paddrinfo {

     sctp_assoc_t            spinfo_assoc_id;

     struct sockaddr_storage spinfo_address;

     int32_t                 spinfo_state;

     uint32_t                spinfo_cwnd;

     uint32_t                spinfo_srtt;

     uint32_t                spinfo_rto;

     uint32_t                spinfo_mtu;

};
spinfo_assoc_id

调用程序提供此值,它指定所关注的关联。

spinfo_address

此值为主要对等地址。

spinfo_state

此值可以采用 SCTP_ACTIVE 或 SCTP_INACTIVE 两个值中的任意一个。

spinfo_cwnd

此值为对等地址的拥塞窗口。

spinfo_srtt

此值为对等地址的当前平滑往返时间计算结果,以毫秒为单位。

spinfo_rto

此值为对等地址的当前重新传输超时值,以毫秒为单位。

spinfo_mtu

此值为对等地址的 P-MTU。

如果成功,则 sctp_opt_info() 函数将返回 0。如果失败,则 sctp_opt_info() 函数将返回 -1,并将 errno 的值设置为相应的错误代码。如果 sock 参数中传递给 sctp_opt_info() 的文件描述符无效,则 sctp_opt_info() 函数将失败并返回 EBADF。如果 sock 参数中传递给 sctp_opt_info() 函数的文件描述符没有描述套接字,则 sctp_opt_info() 函数将失败并返回 ENOTSOCK。如果关联 ID 对于一对多风格 SCTP 套接字而言无效,则 sctp_opt_info() 函数将失败,并将 errno 的值设置为 EINVAL。如果输入缓冲区长度对于指定的选项而言过短,则 sctp_opt_info() 函数将失败,并将 errno 的值设置为 EINVAL。如果对等地址的地址族不是 AF_INET 或 AF_INET6,则sctp_opt_info() 函数将失败,并将 errno 的值设置为 EAFNOSUPPORT

sctp_recvmsg()

ssize_t sctp_recvmsg(int s, void *msg, size_t len, struct sockaddr *from, socklen_t *fromlen, struct sctp_sndrcvinfo *sinfo, int *msg_flags); 

使用 sctp_recvmsg() 函数,可以从 s 参数所指定的 SCTP 端点接收消息。调用程序可以指定以下属性:

msg

此参数为消息缓冲区的地址。

len

此参数为消息缓冲区的长度。

from

此参数为指向包含发送主机地址的地址的指针。

fromlen

此参数为与 from 参数中的地址关联的缓冲区的大小。

sinfo

此参数仅在调用程序启用 sctp_data_io_events 时处于活动状态。要启用 sctp_data_io_events,请使用套接字选项SCTP_EVENTS 调用 setsockopt() 函数。如果启用了 sctp_data_io_events,则应用程序将接收每个传入消息的sctp_sndrcvinfo 结构的内容。此参数为指向 sctp_sndrcvinfo 结构的指针。此结构将在接收消息时进行填充。

msg_flags

此参数包含所有存在的消息标志。

sctp_recvmsg() 函数将返回其接收的字节数。sctp_recvmsg() 函数将在出现错误时返回 -1。

如果在 s 参数中传递的文件描述符无效,则 sctp_recvmsg() 函数将失败,并将 errno 的值设置为 EBADF。如果在 s 参数中传递的文件描述符没有描述套接字,则 sctp_recvmsg() 函数将失败,并将 errno 的值设置为 ENOTSOCK。如果 msg_flags 参数包括值 MSG_OOB,则sctp_recvmsg() 函数将失败,并将 errno 的值设置为 EOPNOTSUPP。如果没有建立关联,则 sctp_recvmsg() 函数将失败,并将 errno的值设置为 ENOTCONN

sctp_sendmsg()

ssize_t sctp_sendmsg(int s, const void *msg, size_t len, const struct sockaddr *to, socklen_t tolen, uint32_t ppid, uint32_t flags, uint16_tstream_no, uint32_t timetolive, uint32_t context); 

sctp_sendmsg() 函数在发送来自 SCTP 端点的消息时启用高级 SCTP 功能。

s

此值指定发送消息的 SCTP 端点。

msg

此值包含 sctp_sendmsg() 函数所发送的消息。

len

此值为消息的长度,以字节为单位。

to

此值为消息的目标地址。

tolen

此值为目标地址的长度。

ppid

此值为应用程序指定的有效负荷协议标识符。

stream_no

此值为此消息的目标流。

timetolive

此值为消息未能成功发送到对等方的情况下消息过期之前可以等待的时间段,以毫秒为单位。

context

如果在发送消息时出现错误,则返回此值。

flags

此值在将逻辑运算 OR 以按位形式应用于以下零个或多个标志位时形成:

MSG_UNORDERED

设置此标志之后,sctp_sendmsg() 函数将无序传送消息。

MSG_ADDR_OVER

设置此标志之后,sctp_sendmsg() 函数将使用 to 参数中的地址,而不使用关联的主要目标地址。此标志仅用于一对多风格 SCTP 套接字。

MSG_ABORT

设置此标志之后,指定的关联将异常中止,同时向其对等方发送 ABORT 信号。此标志仅用于一对多风格 SCTP 套接字。

MSG_EOF

设置此标志之后,指定的关联将进入正常关机状态。此标志仅用于一对多风格 SCTP 套接字。

MSG_PR_SCTP

设置此标志之后,如果消息传输未在 timetolive 参数所指定的时间段内成功完成,则消息将过期。

sctp_sendmsg() 函数将返回其发送的字节数。sctp_sendmsg() 函数将在出现错误时返回 -1。

如果在 s 参数中传递的文件描述符无效,则 sctp_sendmsg() 函数将失败,并将 errno 的值设置为 EBADF。如果在 s 参数中传递的文件描述符没有描述套接字,则 sctp_sendmsg() 函数将失败,并将 errno 的值设置为 ENOTSOCK。如果 flags 参数包括值 MSG_OOB,则sctp_sendmsg() 函数将失败,并将 errno 的值设置为 EOPNOTSUPP。如果一对一风格套接字的 flags 参数包括 MSG_ABORT 或 MSG_EOF值,则 sctp_sendmsg() 函数将失败,并将 errno 的值设置为 EOPNOTSUPP。如果没有建立关联,则 sctp_sendmsg() 函数将失败,并将errno 的值设置为 ENOTCONN。如果套接字关闭,禁止进一步写入,则 sctp_sendmsg() 函数将失败,并将 errno 的值设置为 EPIPE。如果套接字为非阻止套接字并且传输队列已满,则 sctp_sendmsg() 函数将失败,并将 errno 的值设置为 EAGAIN

如果控制消息长度不正确,则 sctp_sendmsg() 函数将失败,并将 errno 的值设置为 EINVAL。如果指定的目标地址不属于关联,则sctp_sendmsg() 函数将失败,并将 errno 的值设置为 EINVAL。如果 stream_no 的值不在关联所支持的外发流数之内,则sctp_sendmsg() 函数将失败,并将 errno 的值设置为 EINVAL。如果所指定的目标地址的地址族不是 AF_INET 或 AF_INET6,则sctp_sendmsg() 函数将失败,并将 errno 的值设置为 EINVAL

sctp_send()

ssize_t sctp_send(int s, const void *msg, size_t len, const struct sctp_sndrcvinfo *sinfo, int flags); 

sctp_send() 函数可供一对一及一对多风格套接字使用。sctp_send() 函数在发送来自 SCTP 端点的消息时启用高级 SCTP 功能。

s

此值指定 socket() 函数所创建的套接字。

msg

此值包含 sctp_send() 函数所发送的消息。

len

此值为消息的长度,以字节为单位。

sinfo

此值包含用于发送消息的参数。对于一对多风格套接字,此值可以包含消息所发送到的关联 ID。

flags

此值与 sendmsg() 函数中的标志参数相同。

sctp_send() 函数将返回其发送的字节数。sctp_send() 函数将在出现错误时返回 -1。

如果在 s 参数中传递的文件描述符无效,则 sctp_send() 函数将失败,并将 errno 的值设置为 EBADF。如果在 s 参数中传递的文件描述符没有描述套接字,则 sctp_send() 函数将失败,并将 errno 的值设置为 ENOTSOCK。如果 sinfo 参数的 sinfo_flags 字段包括值 MSG_OOB,则sctp_send() 函数将失败,并将 errno 的值设置为 EOPNOTSUPP。如果一对一风格套接字中 sinfo 参数的 sinfo_flags 字段包括 MSG_ABORT 或MSG_EOF 值,则 sctp_send() 函数将失败,并将 errno 值的设置为 EOPNOTSUPP。如果没有建立关联,则 sctp_send() 函数将失败,并将 errno 的值设置为 ENOTCONN。如果套接字关闭,禁止进一步写入,则 sctp_send() 函数将失败,并将 errno 的值设置为 EPIPE。如果套接字为非阻止套接字并且传输队列已满,则 sctp_send() 函数将失败,并将 errno 的值设置为 EAGAIN

如果控制消息长度不正确,则 sctp_send() 函数将失败,并将 errno 的值设置为 EINVAL。如果指定的目标地址不属于关联,则sctp_send() 函数将失败,并将 errno 的值设置为 EINVAL。如果 stream_no 的值不在关联所支持的外发流数之内,则 sctp_send() 函数将失败,并将 errno 的值设置为 EINVAL。如果所指定的目标地址的地址族不是 AF_INET 或 AF_INET6,则 sctp_send() 函数将失败,并将 errno 的值设置为 EINVAL

分叉关联

应用程序可以将一对多风格套接字上已建立的关联分叉为独立的套接字和文件描述符。对于具有多个偶发消息发送者或接收者的应用程序,如果这些发送者或接收者需要存在于原始一对多风格套接字之下,则独立的套接字和文件描述符非常有用。应用程序会将传输大量数据通信流量的关联分叉为独立的套接字描述符。应用程序使用 sctp_peeloff() 调用将关联分叉为独立的套接字。新套接字为一对一风格套接字。sctp_peeloff() 函数的语法如下:

int sctp_peeloff(int sock, sctp_assoc_t id); 

sock

从 socket() 系统调用返回的原始一对多风格套接字描述符

id

要分叉为独立的文件描述符的关联的标识符

如果在 sock 参数中传递的套接字描述符不是一对多风格 SCTP 套接字,则 sctp_peeloff() 函数将失败并返回 EOPTNOTSUPP。如果 id 的值为 0 或者 id 的值大于在 sock 参数中传递的套接字描述符的最大关联数,则 sctp_peeloff() 函数将失败并返回 EINVAL。如果 sctp_peeloff()函数无法创建新的用户文件描述符或文件结构,则此函数将失败并返回 EMFILE

sctp_getpaddrs()

sctp_getpaddrs() 函数将返回关联中的所有对等地址。

int sctp_getpaddrs(int sock, sctp_assoc_t id, void **addrs); 

当 sctp_getpaddrs() 函数成功返回时,**addrs 参数的值将指向每个地址相应类型的动态分配的压缩 sockaddr 结构数组。调用线程使用sctp_freepaddrs() 函数释放内存。**addrs 参数的值不能为 NULL。如果 sock 中给定的套接字描述符用于 IPv4 套接字,则sctp_getpaddrs() 函数将返回 IPv4 地址。如果 sock 中给定的套接字描述符用于 IPv6 套接字,则 sctp_getpaddrs() 函数将同时返回 IPv4 和 IPv6 地址。对于一对多风格套接字,id 参数指定要查询的关联。对于一对一风格套接字,sctp_getpaddrs() 函数将忽略 id 参数。当sctp_getpaddrs() 函数成功返回时,它将返回关联中的对等地址数。如果此套接字上没有关联,则 sctp_getpaddrs() 函数将返回 0,并且不定义 **addrs 参数的值。如果出现错误,则 sctp_getpaddrs() 函数将返回 -1,并且不定义 **addrs 参数的值。

如果 sock 参数中传递给 sctp_getpaddrs() 函数的文件描述符无效,则 sctp_getpaddrs() 函数将失败并返回 EBADF。如果 sock 参数中传递给 sctp_getpaddrs() 函数的文件描述符没有描述套接字,则 sctp_getpaddrs() 函数将失败并返回 ENOTSOCK。如果 sock 参数中传递给sctp_getpaddrs() 函数的文件描述符描述了未连接的套接字,则 sctp_getpaddrs() 函数将失败并返回 ENOTCONN

sctp_freepaddrs()

sctp_freepaddrs() 函数将释放所有由之前的 sctp_getpaddrs() 调用所分配的资源。sctp_freepaddrs() 函数的语法如下:

void sctp_freepaddrs(void *addrs); 

*addrs 参数为包含 sctp_getpaddrs() 函数所返回的对等地址的数组。

sctp_getladdrs()

sctp_getladdrs() 函数将返回套接字上的所有本地绑定的地址。sctp_getladdrs() 函数的语法如下:

int sctp_getladdrs(int sock, sctp_assoc_t id, void **addrs); 

当 sctp_getladdrs() 函数成功返回时,addrs 的值将指向动态分配的压缩 sockaddr 结构数组。sockaddr 结构为每个本地地址的相应类型。调用应用程序使用 sctp_freeladdrs() 函数释放内存。addrs 参数的值不能为 NULL。

如果 sd 参数引用的套接字为 IPv4 套接字,则 sctp_getladdrs() 函数将返回 IPv4 地址。如果 sd 参数引用的套接字为 IPv6 套接字,则sctp_getladdrs() 函数将同时返回相应的 IPv4 或 IPv6 地址。

针对一对多风格套接字调用 sctp_getladdrs() 函数时,id 参数的值指定要查询的关联。sctp_getladdrs() 函数在一对一套接字上运行时将忽略 id 参数。

当 id 参数的值为 0 时,无论为何种特定关联,sctp_getladdrs() 函数都将返回本地绑定的地址。当 sctp_getladdrs() 函数成功返回时,它将报告绑定到套接字的本地地址数。如果未绑定套接字,则 sctp_getladdrs() 函数将返回 0,并且不定义 *addrs 的值。如果出现错误,则sctp_getladdrs() 函数将返回 -1,并且不定义 *addrs 的值。

sctp_freeladdrs()

sctp_freeladdrs() 函数将释放所有由之前的 sctp_getladdrs() 调用所分配的资源。sctp_freeladdrs() 函数的语法如下:

void sctp_freeladdrs(void *addrs); 

*addrs 参数为包含 sctp_getladdrs() 函数所返回的对等地址的数组。

 

 

 

实例server.c

 

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <time.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <netinet/sctp.h>
// #include "common.h"
#define MAX_BUFFER 256 
#define MY_PORT_NUM 2222
#define LOCALTIME_STREAM 256
#define GMT_STREAM 256
int main()
{
  int listenSock, connSock, ret;
  struct sockaddr_in servaddr;
  struct sctp_initmsg initmsg;
  char buffer[MAX_BUFFER+1];
  time_t currentTime;

  /* Create SCTP TCP-Style Socket */
  listenSock = socket( AF_INET, SOCK_STREAM, IPPROTO_SCTP );

  /* Accept connections from any interface */
  bzero( (void *)&servaddr, sizeof(servaddr) );
  servaddr.sin_family = AF_INET;
  servaddr.sin_addr.s_addr = htonl( INADDR_ANY );
  servaddr.sin_port = htons(MY_PORT_NUM);

  ret = bind( listenSock, (struct sockaddr *)&servaddr, sizeof(servaddr) );

  /* Specify that a maximum of 5 streams will be available per socket */
  memset( &initmsg, 0, sizeof(initmsg) );
  initmsg.sinit_num_ostreams = 5;
  initmsg.sinit_max_instreams = 5;
  initmsg.sinit_max_attempts = 4;
  ret = setsockopt( listenSock, IPPROTO_SCTP, SCTP_INITMSG, 
                     &initmsg, sizeof(initmsg) );

  /* Place the server socket into the listening state */
  listen( listenSock, 5 );

  /* Server loop... */
  while( 1 ) {

    /* Await a new client connection */
    printf("Awaiting a new connection\n");
    connSock = accept( listenSock, (struct sockaddr *)NULL, (int *)NULL );

    /* New client socket has connected */

    /* Grab the current time */
    currentTime = time(NULL);

    /* Send local time on stream 0 (local time stream) */
    snprintf( buffer, MAX_BUFFER, "%s\n", ctime(&currentTime) );
    ret = sctp_sendmsg( connSock, (void *)buffer, (size_t)strlen(buffer),
                         NULL, 0, 0, 0, LOCALTIME_STREAM, 0, 0 );

    /* Send GMT on stream 1 (GMT stream) */
    snprintf( buffer, MAX_BUFFER, "%s\n", asctime( gmtime( &currentTime ) ) );
    ret = sctp_sendmsg( connSock, (void *)buffer, (size_t)strlen(buffer),
                         NULL, 0, 0, 0, GMT_STREAM, 0, 0 );

    /* Close the client connection */
    close( connSock );

  }

  return 0;
}

 client.c

 

 

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <netinet/sctp.h>
#include <arpa/inet.h>
// #include "common.h"
#define MAX_BUFFER 256 
#define MY_PORT_NUM 2222
#define LOCALTIME_STREAM 256
#define GMT_STREAM 256
int main()
{
  int connSock, in, i, ret, flags;
  struct sockaddr_in servaddr;
  struct sctp_status status;
  struct sctp_sndrcvinfo sndrcvinfo;
  struct sctp_event_subscribe events;
  struct sctp_initmsg initmsg;
  char buffer[MAX_BUFFER+1];

  /* Create an SCTP TCP-Style Socket */
  connSock = socket( AF_INET, SOCK_STREAM, IPPROTO_SCTP );

  /* Specify that a maximum of 5 streams will be available per socket */
  memset( &initmsg, 0, sizeof(initmsg) );
  initmsg.sinit_num_ostreams = 5;
  initmsg.sinit_max_instreams = 5;
  initmsg.sinit_max_attempts = 4;
  ret = setsockopt( connSock, IPPROTO_SCTP, SCTP_INITMSG,
                     &initmsg, sizeof(initmsg) );

  /* Specify the peer endpoint to which we'll connect */
  bzero( (void *)&servaddr, sizeof(servaddr) );
  servaddr.sin_family = AF_INET;
  servaddr.sin_port = htons(MY_PORT_NUM);
  servaddr.sin_addr.s_addr = inet_addr( "127.0.0.1" );

  /* Connect to the server */
  ret = connect( connSock, (struct sockaddr *)&servaddr, sizeof(servaddr) );

  /* Enable receipt of SCTP Snd/Rcv Data via sctp_recvmsg */
  memset( (void *)&events, 0, sizeof(events) );
  events.sctp_data_io_event = 1;
  ret = setsockopt( connSock, SOL_SCTP, SCTP_EVENTS,
                     (const void *)&events, sizeof(events) );

  /* Read and emit the status of the Socket (optional step) */
  in = sizeof(status);
  ret = getsockopt( connSock, SOL_SCTP, SCTP_STATUS,
                     (void *)&status, (socklen_t *)&in );

  printf("assoc id = %d\n", status.sstat_assoc_id );
  printf("state = %d\n", status.sstat_state );
  printf("instrms = %d\n", status.sstat_instrms );
  printf("outstrms = %d\n", status.sstat_outstrms );

  /* Expect two messages from the peer */

  for (i = 0 ; i < 2 ; i++) {

    in = sctp_recvmsg( connSock, (void *)buffer, sizeof(buffer),
                        (struct sockaddr *)NULL, 0, &sndrcvinfo, &flags );

    if (in > 0) {
      buffer[in] = 0;
      if (sndrcvinfo.sinfo_stream == LOCALTIME_STREAM) {
        printf("(Local) %s\n", buffer);
      } else if (sndrcvinfo.sinfo_stream == GMT_STREAM) {
        printf("(GMT ) %s\n", buffer);
      }
    }

  }

  /* Close our socket and exit */
  close(connSock);

  return 0;
}

 

 

 

分享到:
评论

相关推荐

    sctp.rar_NS2 for mobile_SCTP tcl_SCTP.rar_linux SC_流控

    标题中的“sctp.rar_NS2 for mobile_SCTP tcl_SCTP.rar_linux SC_流控”揭示了几个关键概念,这些概念都是关于网络通信和流控制技术的。首先,“sctp”指的是Stream Control Transmission Protocol(流控制传输协议...

    sctp.rar_NS2 SCTP_SCTP in ns2_SCTP ns2_in_sctp

    标题中的“sctp.rar_NS2 SCTP_SCTP in ns2_SCTP ns2_in_sctp”表明这是一个关于在NS2网络模拟器中实现SCTP(Stream Control Transmission Protocol)的压缩包。NS2是一个广泛使用的开源网络模拟工具,而SCTP是一种...

    sctp.rar_Transmission_sctp_sctp programming

    1. API接口:Linux提供了libsocket库中的SCTP编程接口,包括socket()、bind()、listen()、connect()、sendmsg()、recvmsg()等函数,与TCP/IP编程类似但有一些差异。 2. SCTP socket类型:在创建socket时,使用AF_...

    sctp.rar_SCTP ns2_ns2 example_sctp tcl_sctp tcl codes_sctp wire

    用户可以通过阅读和分析此脚本来学习SCTP在NS2中的实现细节,如建立和维护关联(association)、数据包的发送与接收、错误恢复机制(如部分确认PMTUD、Selective Acknowledgments SACK)以及多宿主和多路径传输等...

    sctp-0.2.27.tar.gz_ST_sctp_sctp linux

    "sctp" 和 "sctp_linux" 标签则明确指出了这是与SCTP协议和Linux相关的资源。 在压缩包内文件名列表只给出了 "sctp-0.2.27",这通常是一个包含源代码文件、编译脚本、配置文件和文档的顶级目录。源代码包可能包括...

    sctp.rar_SIP-T_UDP 可靠_ipsec_sctp

    SCTP(Stream Control Transmission Protocol,流控制传输协议)是一种位于网络层之上的传输层协议,与TCP(传输控制协议)和UDP(用户数据报协议)一样,它为应用程序提供了在互联网上传输数据的机制。SCTP的设计...

    SCTP链路测试工具源码(lksctp-tools)

    7. Linux内核中的SCTP API:如`sctp_connectx()`, `sctp_sendmsg()` 和 `sctp_recvmsg()`等函数。 通过分析`lksctp-tools`的源码,开发者不仅可以掌握SCTP协议的工作原理,还可以学习如何在实际项目中应用这些知识...

    sctp.tar.gz_linux server_sctp_udp 重传_拥赛控制协议

    标题中的“sctp.tar.gz”是一个压缩文件,通常在Linux环境下使用,包含了关于SCTP(Stream Control Transmission Protocol)协议的资料。SCTP是一种面向连接的、可靠的传输层协议,设计初衷是为了提供比TCP...

    netty-transport-sctp-4.1.73.Final-API文档-中英对照版.zip

    赠送jar包:netty-transport-sctp-4.1.73.Final.jar; 赠送原API文档:netty-transport-sctp-4.1.73.Final-javadoc.jar; 赠送源代码:netty-transport-sctp-4.1.73.Final-sources.jar; 赠送Maven依赖信息文件:...

    NS2.rar_NS2 SCTP_SCTP ns2_ns2 wireless_sctp_wireless

    总的来说,这个压缩包提供了一个研究和学习SCTP在无线网络环境下行为的平台,利用NS2的仿真能力,用户可以通过TCL脚本调整网络条件和SCTP参数,从而获得有价值的洞察和实验结果。这对于网络协议开发者、科研人员以及...

    xt_sctp.rar_matched_sctp

    标题中的"xt_sctp.rar_matched_sctp"暗示了这是一个与SCTP(Stream Control Transmission Protocol)相关的项目,可能是一个特定的软件模块或者实现,而"matched_sctp"可能指的是匹配SCTP数据块的特定策略或功能。...

    sctp.rar_NS2 SCTP_sctp

    标题中的“sctp.rar_NS2 SCTP_sctp”表明这是一个关于网络模拟器NS-2(Network Simulator 2)中用于SCTP(Stream Control Transmission Protocol)仿真的压缩包。SCTP是一种面向连接的传输层协议,设计目的是提供比...

    nf_nat_proto_sctp.rar_V2 _cpm

    标题中的"nf_nat_proto_sctp.rar_V2_cpm"表明...通过分析这些文件,开发者可以学习到如何在Linux内核中实现NAT规则,特别是针对SCTP协议,这对于那些需要在网络编程和Linux内核开发领域工作的人来说是非常宝贵的知识。

    linux环境下sctp开源代码

    在Linux环境下,SCTP(Stream Control Transmission Protocol)是一种面向连接的、可靠的传输协议,它在互联网协议栈中位于传输层,与TCP和UDP并列。SCTP的设计旨在提供比TCP更高级别的可靠性,同时避免了UDP的无...

    sctp-transport.zip_sctp

    SCTP(Stream Control Transmission Protocol,流控制传输协议)是一种面向连接、可靠的数据传输协议,主要设计用于在IP网络上提供电话服务,但其特性也使其适用于其他需要高可靠性、低延迟和多路径传输的应用场景。...

    xt_sctp.rar_Reached

    SCTP是一种面向连接的传输协议,设计用于在Internet上提供可靠的数据传输服务,类似于TCP(传输控制协议),但它更先进,支持多宿主和多流特性,使得它在VoIP和多媒体通信等领域非常有用。 在提供的文件列表中,...

    YDT 1444-2006 流控制传送协议(SCTP)测试方法 .rar

    流控制传送协议(Stream Control Transmission Protocol,简称SCTP)是一种网络传输协议,设计用于提供比TCP更可靠的传输服务,特别是在IP网络上处理电话语音和其他实时数据时。YDT 1444-2006是中国通信标准化协会...

    softap_ap6212a0_tinav2.1_验证通过_旧版本的系统_20170915_1223没有外层目录.7z

    &lt; &gt; SCTP protocol connection tracking support (EXPERIMENTAL) &lt; &gt; UDP-Lite protocol connection tracking support &lt; &gt; Amanda backup protocol support &lt; &gt; FTP protocol support &lt; &gt; H.323 protocol ...

Global site tag (gtag.js) - Google Analytics