大家好,又见面了,我是你们的朋友全栈君。
###########################################################
SCTP套接字编程相关库函数
######################################################
新的传输层协议,需要安装库函数来支持。
SCTP的流是关联内部具有先后顺序的消息队列。
SCTP的多流特性可以减少头端阻塞,同一个流中的数据会延缓,不影响其他流。
SCTP的函数是第三方库函数,不在内核中。
sctp需要安装:
sudo apt-get install libsctp-dev libsctp1 lksctp-tools
编译sctp程序需要链接sctp库:
-lsctp
sctp有两种接口形式:
一到一(类似于TCP);主要为了一直TCP应用程序到SCTP。
一到多(类似于UDP);大多数sctp使用一到多接口。
客户端用socket函数来获取一个未命名套接字描述符:
服务端用socket函数来获取一个监听套接字描述符:
int listenfd = int socket(int family, int type, intprotocol);
socket的参数都是和协议相关的。
family:(网络层协议)
分两种,一般用地址族。
bsd和linux:(AF:地址族)
AF_INET(ipv4域)
AF_INET6(ipv6域)
AF_LOCAL(unix域)=AF_UNIX
AF_ROUTE(路由域)
AF_KEY(秘钥域)
svr4:(PF:协议族)
PF_INET
PF_INET6
PF_UNIX
PF_NCA
type:
SOCK_STREAM(字节流套接字)(tcp、sctp)
SOCK_DGRAM(数据报套接字)(udp)
SOCK_SEQPACKET(有序分组套接字)(sctp)
SOCK_RAW(原始套接字)(ipv4、ipv6)
SOCK_RDM(无序可靠数据报套接字)
protocol:(传输层协议)
0:tcp和udp,一般用这个,表示默认值
IPPROTO_SCTP: sctp用这个。
int sctp_bindx(int sockfd, const struct sockaddr *addrs, int addrcnt,int flags);
服务用来增加或移除套接字上的绑定地址,所有地址端口号要相同。
addrs:指向紧凑的通用套接字结构列表
addrcnt:结构的个数
flags:
SCTP_BINDX_ADD_ADDR:往套接字添加地址
SCTP_BINDX_REM_ADDR:往套接字删除地址
int sctp_connectx(int sockfd, const struct sockaddr *addrs, intaddrcnt);
客户用来连接到一个多宿的对端主机,列表中的地址都有效
addrs:指向紧凑的通用套接字结构列表
addrcnt:结构的个数
int sctp_getpaddrs(int sockfd,
sctp_assoc_t id, //一到多式的套接字的关联标识
struct sockaddr **addrs//存放返回的多个对端地址的通用套接字地址结构
);
返回存放在addrs中的对端地址数(类似于getpeername)
void sctp_freepaddrs(struct sockaddr *addrs);
释放上面函数分配的资源
int sctp_getladdrs(int sockfd,
sctp_assoc_t id, //一到多式的套接字的关联标识
struct sockaddr **addrs//存放返回的多个本地地址的通用套接字地址结构
);
返回存放在addrs中的本地的地址数(类似于getsockname)
void sctp_freeladdrs(int sockfd, sctp_assoc_t id, struct sockaddr**addrs);
释放上面函数分配的资源
ssize_t sctp_sendmsg(int sockfd,
const void *msg, size_t msgsz, //本地要发送的数据的缓冲区和长度
struct sockaddr *to, socklen_ttolen,//对端接收缓冲区的通用地址和长度
uint32_t ppid; //指定将随数据块传递的净荷协议标识符
uint32_t flags, //传递给SCTP栈,用以标识SCTP选项
uint16_t stream, //指定一个SCTP流号
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//存放可能有的消息标识
);
返回所读字节数。注意这个指针比较多。
int sctp_peeloff(int sockfd,
sctp_assoc_t id//带抽取的关联标识ID
);
从一到多式的套接字中抽取一个关联(类似于accept)
SCTP和TCP/UDP中的shutdown不同:
int shutdown(int sockfd, int how);
how:
SHUT_RD=0:套接字禁止后续接收操作,激活SCTP关联终止过程。
SHUT_WR=1:套接字禁止后续发送操作,激活SCTP关联终止过程。
SHUT_RDWR=2:禁止所有读写操作,激活SCTP关联终止过程。
当相互通信的两个sctp端点中的任何一个发起关联终止序列时,这两个端点都要把已排队的数据发送掉,然后关闭关联。
———————————————————–
SCTP的通知:
默认除了sctp_data_io_event以外的事件都是禁止的,sctp_data_io_event导致每次读入用户数据都收到一个sctp_sndrcvinfo结构。
struct sctp_sndrcvinfo {
__u16sinfo_stream;//SCTP流号
__u16sinfo_ssn;//流序列号
__u16sinfo_flags;//传递给SCTP栈,用以标识SCTP选项
__u32sinfo_ppid;//将随数据块传递的净荷协议标识符
__u32sinfo_context;//可能有的用户上下文
__u32sinfo_timetolive;//指定消息的生命期
__u32sinfo_tsn;
__u32sinfo_cumtsn;
sctp_assoc_tsinfo_assoc_id;//关联的ID
};
使用SCTP_EVENTS选项可以预订8个事件.
struct sctp_event_subscribe {
__u8sctp_data_io_event;//默认开启的,=1标识预订
//7个需要预订的事件的变量
__u8sctp_association_event;
__u8sctp_address_event;
__u8sctp_send_failure_event;
__u8sctp_peer_error_event;
__u8sctp_shutdown_event;
__u8sctp_partial_delivery_event;
__u8sctp_adaptation_layer_event;
//新增的事件,暂时忽略
__u8sctp_authentication_event;//ignore
__u8sctp_sender_dry_event;//ignore
};
通知的事件:
union sctp_notification
{
//通知
struct sctp_tlv sn_header;//解释类型值
//以下7个事件是通知的额外数据
struct sctp_sasoc_change sn_assoc_change;
struct sctp_paddr_change sn_paddr_change;
struct sctp_remote_error sn_remote_error;
sturct sctp_send_failed sn_send_failed;
struct sctp_shutdown_event sn_shutdown_event;
struct sctp_adaption_event sn_adaption_event;
struct sctp_pdapi_event sn_pdapi_event;
};
通知的结构:
struct sctp_tlv
{
u_int16_t sn_type;//7个事件的名称
u_int16_t sn_flags;
u_int32_t sn_length;
};
sn_type分别取值sctp_notification结构中的7个事件的结构名,每个结构名对应 sctp_event_subscribe结构中的变量,用该变量来预订相应的事件。
需要预订的7个事件的结构参考相关资料。
发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/148863.html原文链接:https://javaforall.cn