【UNIX网络编程】|【07】SCTP协议探究

article/2025/9/27 14:54:18

文章目录

    • 1、概述
    • 2、接口模型
        • 2.1 一到一形式
        • 2.2 一到多形式
    • 3、sctp_bindx函数
    • 4、sctp_connectx函数
    • 5、sctp_getpaddrs函数
    • 6、sctp_freepaddrs函数
    • 7、sctp_getladdrs函数
    • 8、sctp_freelpaddrs
    • 9、sctp_sendmsg
    • 10、sctp_recvmsg
    • 11、sctp_opt_info
    • 12、sctp_peeloff函数
    • 13、shudown
    • 14、通知
    • 15、SCTP c/s程序
    • 16、SCTP一到多式流分回射服务器程序
    • 17、SCTP流分回射客户程序
    • 18、sctpstr_cli函数
    • 19、探究头端阻塞
    • 20、控制流的数目
    • 21、控制终结

1、概述

SCTP是一个较新的传输协议;是一个可靠的面向消息的协议;在端点之间提供多个流,并为多宿提供传输级支持;	

2、接口模型

可分为:- 一到一套接字:对应一个单独的SCTP关联;- 一到多套接字:一个给定套接字从若干个同时在发送数据的远程UDP端点接收彼此交错的数据报;

在决定使用哪种接口形式时,考虑应用程序的因素

- 所编写的服务器程序是迭代的还是并发;
- 服务器希望管理多少套接字描述符;
- 优化关联建立的四路握手过程,使得能够在其中第三个分组交换用户数据,这一点很重要吗;
- 应用进程希望维护多少个连接状态;

2.1 一到一形式

该形式是为了方便将TCP应用程序移植到SCTP上;
- 任何套接字选项都必须由TCP转换成SCTP,常见的是TCP_NODELAY和TCP_MAXSEG,应该映射成SCTP_NODELAY和SCTP_MAXSEGO;
- SCTP保存消息边界,因而应用层消息边界并非必需;如:基于TCP的某个应用协议可能先执行一个双字节的write系统调用,给出消息的长度x,再调用一个x字节的write系统调用,写出消息数据本身;改用SCTP后,接收端SCTP将收到两个独立的消息也就是说得有两次read系统调用才能返回全部数据:第一次返回一个双字节数据,第二次返回一个x字节消息);
- 有些TCP应用进程使用半关闭来告知对端去往它的数据流已经结束;将这样的应用程序移植到SCTP需要额外重写应用层协议,让应用进程在应用数据流中告知对端该传输数据流已经结束;
- send能够以普通方式使用,使用sendto或sendmsg时,指定的任何地址都被认为是对目的地主地址的重写;【典型用法】:服务器启动后,打开一个套接字,bind一个地址,等待accept客户关联;客户启动后,打开一个套接字,并初始化与服务器的一个关联;若客户想服务器发送一个请求,服务器处理该请求后向客户发回一个应答;该循环持续到客户开始终止该关联为止;

2.2 一到多形式

【开发】:编写的服务器无需管理大量的套接字描述符,当个套接字描述符将代表多个关联,即一个UDP套接字能从多个客户接收消息;
在一到多式套接字上,用于标识单个关联的是一个关联标识(类型为sctp_ASSOC_T的值);

在这里插入图片描述

- 当一个客户关闭其关联时,其服务器自动关闭同一个关联,且内核中不再有该关联的状态;
- 四路握手的第三个或第四个分组中捎带用户数据的唯一办法就是使用一到多形式;
- 对于与它还没有关联存在的IP,任何以它为目的地的sendto、sendmsg或sctp_sendmsg将导致对主动打开的尝试,从而建立一个与该地址的新关联;该行为的发送与执行分组发送的这个应用进程是否曾调用过listen函数以请求被动打开无关;
- 用户必须使用sendto、sendmsg或sctp_sendmsg这3个分组发送函数,而不能使用send或write,除非已使用sctp_peeloff函数从一个一到多式套接字剥离出一个一到一式套接字;
- 任何时候调用其中任何一个分组发送函数时,所用的目的地址是由系统在关联建立阶段选定的主目的地址;除非调用者在所提供的sctp_sndrcvinfo中设置了MSG_ADDR_OVER;且必须伴随使用sendmsg或sctp_sendmsg函数;
- 关联事件可能被启用,因此要应用进程不要收到这些事件,使用SCTP_EVENTS显示禁止;默认下是sctp_data_io_event,它给recvmsg和sctp_recvmsg调用辅助数据;

在这里插入图片描述

上述为迭代服务器,许多关联的消息能够由单个控制线程处理;
在SCTP中,一个一到多套接字也能够结合使用sctp_peeloff函数以允许组合迭代服务器莫西和并发服务器模型;
- sctp_peeloff函数用于从一个一到多套接字剥离出某个特定的关联,独自构成一个一到一式套接字;
- 剥离出的关联所在的一到一套接字随后就可以遣送给它自己的线程,或者遣送给为它派生的进程;
- 与此同时,主线程继续在原来的套接字上以迭代方式处理来自任何剩余关联的消息,一到多式SCTP套接字是一个类型为SOCK_SEQPACKET,协议为IPPROTO_SCTP的网际网套接字;

3、sctp_bindx函数

#include <netinet/sctp.h>int sctp_bindx(int sockfd, const struct sockaddr *addr, int addrcnt, int flags);
/**
@func: 该函数允许SCTP套接字捆绑一个特定地址子集;
@param sockfd: socket函数返回的描述符;
@param addrs: 一个指向紧凑的地址列表的指针;
@param addrcnt: 指定地址个数;
@param flags: 指导sctp_bindx调用;
*/

在这里插入图片描述

sctp_bindx调用既可用于已绑定的套接字,也可用于未绑定的套接字;
【未绑定套接字】:sctp_bindx调用将把给定的地址集合捆绑到其上;
【已绑定套接字】:若指定SCTP_BINDX_ADD_ADDR则把额外的地址加入到套接字描述符,若指定SCTP_BINDX_REM_ADDR则从套接字描述符的已加入地址中移除给定的地址l;
如果在一个监听套接字上执行sctp_bindx调用,产生的关联将使用新的地址配置,已经存在的关联则不受影响;
传递给sctp_bindx的两个标志是互斥的,若同时指定,则调用失败返回的EINVALO;
所有套接字地址结构的端口号必须相同,且必须与已经绑定的端口号相匹配,否则调用就会失败,返回EINVAL;
若一个端点支持动态地址特性,指定SCTP_BINDX_ADD_ADDR或SCTP_BINDX_REM_ADDR标志调用sctp_bindx将导致该端点向对端发送一个合适的消息,
以修改对端的地址列表;由于增减一个己连接关联的地址只是一个可选的功能,因此不支持本功能的实现将返回EOPNOTSUPP;
【注意】:本功能正确操作要求两个端点都支持这个特性;本特性对于支持动态接口供给的系统可能有用;如:若调出一个新的以太网接口,那么应用进程可以指定SCTP_BINDX_ADD_ADDR标志在已经存在的连接上启动使用这个接口;

4、sctp_connectx函数

#include <netinet/sctp.h>int sctp_connectx(int sockfd, const struct sockaddr *addr, int addrcnt);
/**
@func: 函数用于连接到一个多宿对端主机;
@param addrs: 指定addrcnt个全部属于同一对端的地址,是一个紧凑的地址列表;SCTP栈使用其中一个或多个地址建立关联;
*/

5、sctp_getpaddrs函数

当SCTP使用getpeername时将仅仅返回主目的地址;
若需要直到对端的所有地址,则应该使用sctp_getpaddrs函数
#include <netinet/sctp.h>int sctp_getpaddrs(int sockfd, sctp_assoc_t id, struct sockaddr **addrs);
/**
@func: 获取对端的所有地址;
@param id: 是一到多式套接字的关联标识,而一到一式套接字会忽略该字段;
@param addrs: 地址指针,内容由本函数动态分配并填入的紧凑的地址列表;
【注意】:使用完后,应使用sctp_freepaddrs释放分配的资源;
*/

6、sctp_freepaddrs函数

#include <netinet/sctp.h>void sctp_freepaddrs(struct sockaddr *addrs);
/**
@func: 函数释放由sctp_getpaddrs函数分配的资源;
@param addrs: 指向sctp_getpaddrs的返回的数组的指针;
*/

7、sctp_getladdrs函数

#include <netinet/sctp.h>int sctp_getladdrs(int sockfd, sctp_addoc_t id, struct sockfaddr **addrs);
/**
@func: 用于获取属于某个关联的本地地址;
@param id: 一到多式套接字的关联标识,而一到一式套接字则会将其忽略;
@param addrs: 地址指针,内容为本函数动态分配并填入的紧凑的地址列表;
【注意】:使用完后,应使用sctp_freelpaddrs释放分配的资源;
*/

8、sctp_freelpaddrs

#include <netinet/sctp.h>void sctp_freeladdrs(struct sockaddr *addrs);
/**
@func: 释放由sctp_getlpaddrs分配的资源;
@param addr: sctp_getlpaddrs返回的地址数字的指针;
*/

9、sctp_sendmsg

#include <netinet/sctp.h>ssize_t sctp_sendmsg(int sockfd, const void *msg, size_t msggz, const struct sockaddr *to, socklen_t tolen,uint32_t ppid,uint32_t flags, uint16_t stream,uint32_t timetolive, uint32_t context);
/**
@func: 能够控制SCTP的各种特性;
@param msg: 指向一个长度为msgsz字节的缓冲区;
@param to: 内容发送的地点;
@param tolen: to中的地址长度;
@param ppid: 将随数据块传递的净荷协议标识符;
@param flags: 传递给SCTP栈,用以标识任何SCTP选项;
@param stream: 指定一个SCTP流号;
@param timetolive: 以毫秒为单位的消息的生命期,0为无限;
@param context: 指定可能有的用户上下文;用户上下文把通过消息通知机制收到的某次失败的消息发送与某个特定于应用的本地上下文关联;
*/

10、sctp_recvmsg

#include <netinet/sctp.h>ssize_t sctp_recvmsg(int sockfd, void *msg, size_t msgsz, struct sockaddr *from, socklen_t *fromlen, struct sctp_sndrcvinfo *sinfo, int *msg_flags);
/**
@func: 获取对端的地址及获取通常伴随recvmsg调用返回的msg_flags参数,可获取sctp_sndrcvinfo;
@param msg: 指向一个长度为msgsz字节的缓冲区;
@param from: 内容发送的地点;
@param fromlen: to中的地址长度;
@param msg_flags: 存放可能有的消息标志;
【注意】:若应用进程要接收sctp_sndrcbinfo,则要使用SCTP_EVENTS预订sctp_data_io_event;
*/

11、sctp_opt_info

#include <netinet/sctp.h>int sctp_opt_info(int sockfd, sctp_assoc_t assoc_id, int opt,void *arg, socklen_t *siz);
/**
@func: 允许套接字选项中使用出入变量的系统,将一个参数重新打包到合适的getsockopt调用中的库函数;
@param assoc_id: 给出可能存在的关联标识;
@param opt: SCTP的套接字选项;
@param arg: 套接字选项参数;
@param siz: 存放参数的大小;
*/

12、sctp_peeloff函数

#include <netinet/sctp.h>int sctp_peeloff(int sockfd, sctp_assoc_t id);
/**
@func: 把一到多式套接字的sockfd和待抽取的关联标识id传递给函数调用;
return: 新的套接字描述符,即一个与所请求关联对应的一到一式套接字描述符;
*/

13、shudown

SCTP不提供半关闭状态,对shutdown调用的反应不同于TCP端点;
当相互通信的两个SCTP端点中任何一个发起关联终止序列时,这两个端点都得把已排队的任何数据发送掉,然后关闭关联;
关联主动打开的发起端点改用shutdown而不是close的可能原因是:- 同一个端点可用于连接到一个新的对端端点;- 与TCP不同,新的套接字打开之前不必调用close;
SCTP允许一个端点调用shutdown,结束后,这个端点可重用原套接字连接到一个新的对端;
【注意】:如果这个端点没有等到SCTP关联终止序列结束,新的连接就会失败;shutdown中的howto参数:【SHUT_RD】:没有任何SCTP协议行为发生。【SHUT_WR】:禁止后续发送操作,激活SCTP关联终止过程,以此终止当前关联;【SHUT_RDWR】:禁止所有read、write操作,激活SCTP关联终止过程;

在这里插入图片描述

14、通知

SCTP用户可经由这些通知追踪相关关联的状态,由套接字描述符获取;
通知传递的是传输级的事件,包括网络状态变动、关联启动、远程操作错误一级消息不可递送;
用户可用recvmsg和sctp_recvmsg区分对端的数据和由事件产生的通知;
若返回的数据是一个事件通知,则两个函数返回的msg_flags将含有MSG_NOTIFICATION标志;该标志告知应用进程刚刚读入的消息不是来自对端的数据,而时来自本地SCTP栈的一个通知;【通知格式】:都是采用标签-长度-值,其中前8个字节给出通知的类型和总长度;开启sctp_data_io_event将导致每次读入用户数据都收到一个sctp_sndrcvinfo;
一般信息通过调用recvmsg作为辅助数据获取,应用程序可调用sctp_recvmsg,同样的信息将被填写到由某个指针指出的sctp_sndrcvinfo;
struct sctp_tlv{u_int16_t sn_type;u_int16_t sn_flags;u_int32_t sn_length;
};union sctp_notification{struct sctp_tlv sn_header;struct sctp_assoc_change sn_assoc_change;struct sctp_ paddr__change sn_paddr_change;struct sctp_remote_error sn_remote_error;struct 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 ;
};

**在这里插入图片描述**

15、SCTP c/s程序

以下将编写一个一到多式SCTP客户/服务器程序:
- 客户从标准输入读入一行文本,并发送给服务器;该文本行遵循[#]text格式,#是在其上发送该文本消息的SCTP流号;
- 服务器从网络接收这个文本消息,把在其上到达消息的流号增1,再在新的流号上发送回同一个文本呢消息给客户;
- 客户从网络读入这行回射文本,并显示在标准输出上,内容包括流号、流序列号和文本串;

在这里插入图片描述

16、SCTP一到多式流分回射服务器程序

int main(int argc, char **argv) {int sfd, msg_flags;char readBuf[BUFFSIZE];struct sockaddr_in servaddr, cliaddr;struct sctp_sndrcvinfo sri;struct sctp_event_subscribe evnts;int stream_increment = 1;socklen_t len;size_t rd_sz;if(argc == 2)stream_increment = atoi(argv[1]);/* 创建一个SCTP一到多式套接字 */sfd = socket(AF_INET, SOCK_SEQPACKET, IPPROTO_SCTP);/* 捆绑地址,对于多宿主机,这种捆绑意味着一个远程断点能够与这个本地主机任何一个路由* 地址建立关联并发送分组* */bzero(&servaddr, sizeof(servaddr));servaddr.sin_family = AF_INET;servaddr.sin_addr.s_addr = htonl(INADDR_ANY);servaddr.sin_port = htons(SERV_PORT);bind(sfd, (struct sockaddr*)&servaddr, sizeof(servaddr));/* 预定sctp_data_io_event,从而允许服务器查看sctp_sndrcvinfo结构,* 服务器可从结构确定消息所在的流号* */bzero(&evnts, sizeof(evnts));evnts.sctp_data_io_event = 1;setsockopt(sfd, IPPROTO_SCTP, SCTP_EVENTS, &evnts, sizeof(evnts));listen(sfd, LISTENQ);while (1) {len = sizeof(struct sockaddr_in);/* 等待消息,服务器初始化客户套接字地址结构的大小,后阻塞在等待来自任何一个远程* 对端的消息上;* */rd_sz = sctp_recvmsg(sfd, readBuf, sizeof(readBuf),(struct sockaddr*)&cliaddr, &len, &sri, &msg_flags);/* 当有消息到达时,服务器检查stream_increment来确定是否需要增长流号;* 若设置了该标志,服务器就把消息的流号增1,若流号增长最大流号时,服务器就把流号重置为0* */if(stream_increment) {sri.sinfo_stream++;if(sri.sinfo_stream >=sctp_get_no_strms(sfd, (struct sockaddr*)&cliaddr, len))sri.sinfo_stream = 0;}/* 服务器使用来自sri结构的净荷协议ID、标志一级可能改动过的流号发送回消息本身* 服务器不希望得到关联通知,故禁止了向上传递消息到套接字缓冲区的所有事件;* 本服务器依赖于sctp_sndrcvinfo结构中的消息和cliaddr返回地址定位对端的关联地址并回射消息;* */sctp_sendmsg(sfd, readBuf, rd_sz,(struct sockaddr*)&cliaddr, len,sri.sinfo_ppid,sri.sinfo_flags, sri.sinfo_stream, 0, 0);}return 0;
}

17、SCTP流分回射客户程序

int main(int argc, char **argv) {int sfd;struct sockaddr_in servaddr;struct sctp_event_subscribe evnts;int echo_to_all = 0;if(argc < 2)err_quit("Missing host argument - use '%s host [echo]'\n", argv[0]);if(argc > 2) {err_quit("Echoing messages to all streams\n");echo_to_all = 1;}/* 创建一个sctp一到多式套接字 */sfd = socket(AF_INET, SOCK_SEQPACKET, IPPROTO_SCTP);bzero(&servaddr, sizeof(servaddr));servaddr.sin_family = AF_INET;servaddr.sin_addr.s_addr = htonl(INADDR_ANY);servaddr.sin_port = htons(SERV_PORT);inet_pton(AF_INET, argv[1], &servaddr.sin_addr);    // 服务器地址从表达式转化成数值格式/* 客户显示设置其一到多式SCTP套接字的通知预订*/bzero(&evnts, sizeof(evnts));evnts.sctp_data_io_event = 1;setsockopt(sfd, IPPROTO_SCTP, SCTP_EVENTS, &evnts, sizeof(servaddr));if(echo_to_all == 0)sctpstr_cli(stdin, sfd, (struct sockaddr*)&servaddr, sizeof(servaddr));elsesctpstr_cli_echoall(stdin, sfd, (struct sockaddr*)&servaddr, sizeof(servaddr));close(sfd);return 0;
}

sctp_address_to_associd

sctp_assoc_t sctp_address_to_associd(int sock_fd, struct sockaddr *sa, socklen_t salen)
{struct sctp_paddrparams sp;socklen_t siz;siz = sizeof(struct sctp_paddrparams);bzero(&sp,siz);memcpy(&sp.spp_address,sa,salen);sctp_opt_info(sock_fd,0,SCTP_PEER_ADDR_PARAMS, &sp, &siz);return(sp.spp_assoc_id);
}

sctp_get_no_strms

int sctp_get_no_strms(int sock_fd,struct sockaddr *to, socklen_t tolen)
{socklen_t retsz;struct sctp_status status;retsz = sizeof(status);bzero(&status,sizeof(status));status.sstat_assoc_id = sctp_address_to_associd(sock_fd,to,tolen);getsockopt(sock_fd,IPPROTO_SCTP, SCTP_STATUS,&status, &retsz);return(status.sstat_outstrms);
}

18、sctpstr_cli函数

void sctpstr_cli(FILE *fp, int sockfd, struct sockaddr *to, socklen_t tolen) {struct sockaddr_in peeraddr;struct sctp_sndrcvinfo sri;char sendline[MAXLINE], recvline[MAXLINE];socklen_t len;int out_sz, rd_sz;int msg_flags;/* 将sri清0,并循环阻塞读取 */bzero(&sri, sizeof(sri));while (fgets(sendline, MAXLINE, fp) != NULL) {/* 检查输入格式 */if(sendline[0] != '[') {cout << "Error, line must be of the from '[streamnum]text'\n";continue;}/* 将请求的流号转成sri结构的sinfo_stream */sri.sinfo_stream = strtol(&sendline[1], NULL, 0);/* 初始化目的地址结构的长度以及用户数据的大小后,客户使用sctp_sendmsg函数发送消息 */out_sz = strlen(sendline);sctp_sendmsg(sockfd, sendline, out_sz, to,tolen, 0, 0, sri.sinfo_stream, 0, 0);/* 阻塞等待服务器的回射消息 */len = sizeof(peeraddr);rd_sz = sctp_recvmsg(sockfd, recvline, sizeof(recvline),(struct sockaddr*)&peeraddr, &len, &sri, &msg_flags);printf("From str:%d seq:%d (assoc:0x%x):",sri.sinfo_stream, sri.sinfo_ssn, (u_int)sri.sinfo_assoc_id);printf("%.*s", rd_sz, recvline);}
}

在这里插入图片描述

19、探究头端阻塞

SCTP中内部关联具有先后顺序的消息序列;
【避免仅使用单个TCP字节流导致的头端阻塞现象】:以流本身而不是以流所在关联为单位进行消息排序;

现象描述

头端阻塞发送在一个TCP分解丢失,导致后续分解不按序到达接受端;
当第一张图丢失时,客户将保持已不按序到达的所有数据,直到丢失的分节被重传并成功到达为止;

在这里插入图片描述
SCTP对流特性

SCTP该特性能够减少头端阻塞;
后续的图不受第一幅的影响;

在这里插入图片描述

#define SCTP_MAXLINE 800
#define SERV_MAX_SCTP_STRM 10void sctpstr_cli_echoall(FILE *fp, int sock_fd, struct sockaddr *to,socklen_t tolen) {struct sockaddr_in peeraddr;struct sctp_sndrcvinfo sri;char sendline[SCTP_MAXLINE], recvline[SCTP_MAXLINE];socklen_t len;int rd_sz, i, strsz;int msg_flags;bzero(sendline, sizeof(sendline));bzero(&sri, sizeof(sri));while (fgets(sendline, SCTP_MAXLINE - 9, fp) != NULL) {strsz = strlen(sendline);if(sendline[strsz -1] == '\n'){sendline[strsz-1] = '\0';strsz--;}for(i=0; i<SERV_MAX_SCTP_STRM; i++) {snprintf(sendline + strsz, sizeof(sendline) - strsz,".msg.%d", i);sctp_sendmsg(sock_fd, sendline, sizeof(sendline),to, tolen, 0, 0, i, 0, 0);}for(i=0; i<SERV_MAX_SCTP_STRM; ++i) {len = sizeof(peeraddr);rd_sz = sctp_recvmsg(sock_fd, recvline, sizeof(recvline),(struct sockaddr*)&peeraddr, &len, &sri, &msg_flags);printf("From str:%d seq:%d (assoc:0x%x):",sri.sinfo_stream, sri.sinfo_ssn, (u_int)sri.sinfo_assoc_id);printf("[%d]%s", rd_sz, recvline);}}
}

20、控制流的数目

如何在关联初始化阶段控制一个端点请求的流数目;
if(argc == 2) stream_increment = atoi(argv[1]);
sock_fd = socket(AF_INET, SOCK_SEQPACKET, IPPROTO_SCTP);
/* 将sinit_num_ostream设置未期望请求的流数目 */
bzero(&initm, sizeoof(initm));
initm.sinit_num_ostream = SERV_MORE_STRMS_SCTP;
setsockopt(sock_fd, IPPROTO_SCTP, SCTP_INITMSG, &initm, sizeof(initm));

21、控制终结

如果服务器希望在发送完一个应答消息后终止一个关联:
- 可在与该消息对应的sctp_sndrcvinfo结构的sinfo_flags字段中设置WSG_EOF标志;该标志使所发送消息被客户确认之后,相应关联也被终止;
- 可把MSG_ABORT标志应用于sinfo_flags字段。该标志将以ABORT块迫使立即终止关联;SCTP的ABORT块类似TCP的RST分节,能够无延迟地中止任何关联,尚未发送的任何数据都被丢弃;

服务器程序应答同时终止关联的改动部分

while(1) {len = sizeof(struct sockaddr_in);rd_sz = sctp_recvmgs(sock_fd, readbuf, sizeof(readbuf));if(stream_increment) {sri.sinfo_stream++;if(sri.sinfo_stream >= sctp_get_no_strms(sock_fd, (struct sockaddr*)&cliaddr, len))sri.sinfo_stream = 0;}sctp_sendmsg(sock_fd, readbuf, rd_sz, (struct sockaddr*)&cliaddr, len, sri.sinfo_ppid, (sri.sinfo_flags | MSG_EOF), sri.sinfo_stream, 0, 0);
}

客户程序预先终止关联的改动部分

if(echo_to_all == 0)sctpstr_cli(stdin, sock_fd, (struct sockaddr*)&servaddr, sizeof(servaddr));
elsesctpstr_cli_echoall(stdin, sock_fd, (struct sockaddr*)&servaddr, sizeof(servaddr));
/* 客户准备一个信息座位关联中止的用户错误起因,后以MSG_ABORT调用sctp_sendmsg函数;该标志导致一发送一个ABORT块,从而立即终止当前关联,该ABORT块包含用户发起错误起因代码*/
strcpy(byemsg, "goodbye");
sctp_sendmsg(sock_fd, byemsg, strlen(byemsg), (struct sockaddr*)&servaddr, sizeof(servaddr), 0, MSG_ABORT, 0, 0, 0);
/* 即使关联中止,仍得关闭套接字描述符以释放与关联的系统资源 */
close(sock_fd);

http://chatgpt.dhexx.cn/article/8RYpCA6g.shtml

相关文章

C++网络编程-tcpip协议

目录 1 tcp/ip协议族 1.1 体系结构以及主要协议 1.2 封装 1.3 分用 1.4 测试网络 1.5 arp协议工作原理 1.6 dns工作原理 1.7 socket和tcp/ip协议族的关系 2 ip协议详解 2.1 ip服务特点 2.2 ipv4头部结构 2.3 ip分片 2.4 ip路由 3 tcp协议详解 3.1 tcp服务的特点…

CSP绕过

01 比赛中常见的绕过CSP csp例子&#xff1a; <meta http-equiv"Content-Security-Policy" content"script-src self; object-src none; style-src cdn.example.org third-party.org; child-src https:">目前在比赛中常见的绕过 CSP 一般是: scri…

CS的使用

1&#xff09;首先创建服务端 命令&#xff1a;teamserver 192.168.71.130(主机IP) 123456&#xff08;随便设&#xff09; teamserver 192.168.71.130 123456 >/dev/null 2>&1 & (命令隐藏后台&#xff0c;jobs查看后台&#xff0c;客户端同理&#xff0c;在st…

C/C++Unix网络编程-IPC简介

IPC是进程间通信的简称。 进程、线程与信息共享 Unix进程间的信息共享的方式&#xff1a; (1) 左边的两个进程共享存留于文件系统中某个文件上的某些信息。为访问这些信息、每个进程都得穿越内核(例如read、write、lseek等)。当一个文件有待更新时&#xff0c;某种形式的同步…

CTP For Python

GitHub地址&#xff1a;https://github.com/shizhuolin/PyCTP 这是程序化期货交易上期ctp接口版本.将其包装为python版本. 支持python3 编译需求:vs2010/gcc 编译方法 python setup.py build PyCTP 编译方法 开发环境&#xff1a;windows 10 64bit, python 3.4.3 32bit, Visu…

CSP-S 2021

[CSP-S 2021] 括号序列 题目描述 小 w 在赛场上遇到了这样一个题&#xff1a;一个长度为 n n n 且符合规范的括号序列&#xff0c;其有些位置已经确定了&#xff0c;有些位置尚未确定&#xff0c;求这样的括号序列一共有多少个。 身经百战的小 w 当然一眼就秒了这题&#x…

CyberSploit:1

一、环境搭建 靶机下载地址&#xff1a;https://www.vulnhub.com/entry/cybersploit-1,506/ 二、漏洞复现 探测靶机ip地址&#xff0c;得到靶机IP地址 nmap扫描服务以及端口&#xff0c;发现80和22端口 访问80端口&#xff0c;看到一个页面&#xff0c;查看源码未发现东西 …

[网络安全]dSploit-Android系统下的网络分析和渗透套件的使用

一、准备工作 一台已经获得root权限的安卓手机&#xff0c;并且安卓系统版本在 2.3 以上 busyBox 安装软件 下载地址 BusyBox 是一个集成了一百多个最常用linux命令和工具的软件。&#xff3b;百度百科&#xff3d; 安装这个软件主要是为dsploit软件的运行提供 linux 中…

记一次无线渗透

用到的工具 一台root的安卓手机&#xff08;我这台手机刷了miui9&#xff09; Csploit 安卓渗透神器 下载地址&#xff1a;https://github.com/cSploit/android/releases Kali meterpreter 当然你有Kali的Nethunter设备更好 开始测试 利用万能钥匙找一波wifi&#xff0c;运气好…

为网络安全红队方向提供的资源,工具大合集(渗透测试)

这是一份必备的资源大合集&#xff0c;收录了最优秀的网络安全红队方向&#xff08;渗透测试&#xff09;的资源和工具。 &#xff08;文末领取读者福利&#xff09; 无论您是初学者还是专业人士&#xff0c;都能从中获得所需的技能和知识。 在这个信息化时代&#xff0c;网络…

如何在网站中插入视频

&#xfeff;&#xfeff; 很多新手站长在往自己网站里&#xff0c;添加土豆优酷等视频网站里的视频时&#xff0c;会遇到一些麻烦,珊珊在这里向大家介绍一种简单方法. 1.首先要找到要插入的视频&#xff0c;如下图点击分享给朋友右侧的小按钮. 2.点击按钮后弹出一个窗口点击复…

Word中轻松插入本地视频

场景 在Word文档中插入视频 实现 新建或打开Word文档 找到上面插入菜单栏&#xff0c;点击并选择对象 点击后选择PPT 点击确定 此时会打开PPT&#xff0c;然后再选择上面的插入 选择插入下的视频选项&#xff0c;然后选择PC上的视频 选择视频后点击插入 可以调整视频大小 …

如何在html里插入视频

第一步&#xff1a;首先下载video.js&#xff0c;百度一下就能找到。 这个是下载后的目录。 第二步&#xff1a;先把要用到的js\css\swf都加载到html页面上。 如&#xff1a; 第三步&#xff1a;加入下面的代码&#xff1a; <video id"my_video_1" class"…

制作往图片里插入视频,视频添加到图片上播放

在视频中还有个小视频同时播放&#xff0c;这种画中画的效果以前都学习过&#xff0c;那在图片上插入视频播放&#xff0c;可以用媒体梦工厂中的画中画功能来制作吗&#xff1f;这个肯定是可以的了。下面就来看看怎么的操作的吧。 先来看看图片加视频制作出来的画中画效果 制作…

插入视频--使用<video>标签为网页添加视频

使用方法 举例 显示结果 在网页上添加视频和添加音频的标签属性用法相同。 讲解 1.autoplay:如果出现该属性&#xff0c;则视频在就绪后马上播放。 2.controls:如果出现该属性&#xff0c;则向用户显示控件&#xff0c;比如播放按钮。 3.loop:如果出现该属性&#xff0c;…

视频剪辑工具,如何批量在图片中插入视频

怎么批量在图片中插入视频呢&#xff1f;其实这是一种很常见的效果&#xff0c;那么这种效果是怎么制作的呢&#xff1f;下面随小编一起来操作。 所需工具 多张图片、视频素材 操作步骤 运行媒体梦工厂&#xff0c;将图片导入画中画板块中的“底画”中&#xff0c;多张图片&…

教你给视频画面任意位置插入GIF图

视频怎么添加GIF图片呢&#xff1f;如何在视频任意位置添加的呢&#xff1f;其实很简单。教你这个简单的剪辑方法。一起来试试吧。 准备工具&#xff1a; 视频素材及动图 下载一个视频剪辑高手 开始操作&#xff1a; 运行软件登录上&#xff0c;在多种功能上选择“批量剪辑视…

计算机word如何提交,如何在word添加视频?

您可以从计算机或Internet添加视频以直接在Word文档中播放。 此功能使您(或与您共享文档的人)可以直接观看视频而无需离开文档。 将视频添加到Word文档 将离线视频(或计算机存储中的视频)添加到Word文档的不利之处在于&#xff0c;它们只能在您的PC上播放。 如果您将文档发送给…

如何在html网页中插入视频(以及让视频自动播放的问题)

直接进入正题&#xff1a; 关于视频的插入可使用 video标签 如下图 简单介绍下用到的几个属性 class定义了video类 在style中调整这个类的长度和高度属性&#xff1b; src处引入视频的链接&#xff1b; controls属性&#xff1a;允许用户控制视频的播放&#xff0c;包括音…

HTML插入视频和音频

一、插入视频 src表示视频来源位置 height表示视频高度 autoplay表示视频自动播放 loop表示循环播放 controls表示进度控制条 muted表示静音播放 poster表示视频封面所用的图片路径 video/mp4表示视频的格式 例如&#xff1a; <video src"images\sp1.mp4&quo…