socket编程---SCTP

sctp_sndrcvinfo结构体

sctp_event_subscribe结构体

更多的关于SCTP的结构体http://aisxyz.iteye.com/blog/2408978

SCTP套接字编程相关函数

client.c

/*************************************************************************
    > File Name: client.c
    > Author: Chen
    > Mail: 971859774@qq.com 
    > Created Time: 2018年11月14日 星期三 17时06分56秒
 ************************************************************************/

#include <stdio.h>
#include <stdlib.h>
#include <arpa/inet.h>
#include <netinet/sctp.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <strings.h>
#include <string.h>
#include <ctype.h>
#include "my_err.h"

#define SERV_PORT 9877
#define SCTP_MAXLINE 800
#define SERV_MAX_SCTP_STRM 10

void sctp_cli(int sockfd,struct sockaddr * to,socklen_t tolen)
{
    struct sctp_sndrcvinfo sri;
    bzero(&sri,sizeof(sri));

    char rdbuf[MAXLINE],rvbuf[MAXLINE];
    struct sockaddr_in peeraddr;
    int flag;
    while(fgets(rdbuf,MAXLINE,stdin)!=NULL)
    {
        if(rdbuf[0]!='[')
        {
            fprintf(stderr,"Error,line must be of the form '[strnum]text'
");
            continue;
        }

        if(isdigit(rdbuf[1]))
        {
            sri.sinfo_stream=strtol(&rdbuf[1],NULL,10);
            int out_sz=strlen(rdbuf);
            sctp_sendmsg(sockfd,rdbuf,out_sz,to,tolen,0,0,sri.sinfo_stream,0,0);
            socklen_t len=sizeof(peeraddr);
            int rd_sz=sctp_recvmsg(sockfd,rvbuf,sizeof(rvbuf),(struct sockaddr *)&peeraddr,&len,&sri,&flag);

            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,rvbuf);
        }
    }
    return;
}

//是否有头端阻塞
void sctp_cli_all(int sockfd,struct sockaddr *to,socklen_t tolen)
{
    struct sctp_sndrcvinfo sri;
    bzero(&sri,sizeof(sri));

    char rdbuf[MAXLINE],rvbuf[MAXLINE];
    bzero(&rdbuf,sizeof(rdbuf));
    bzero(&rvbuf,sizeof(rvbuf));

    while(fgets(rdbuf,SCTP_MAXLINE-9,stdin)!=NULL)
    {
        int rd_sz=strlen(rdbuf);
        if(rdbuf[rd_sz-1]=='
')
        {
            rdbuf[rd_sz-1]='';
            --rd_sz;
        }

        int i=0;
        for(;i<SERV_MAX_SCTP_STRM;++i)
        {
            snprintf(rdbuf+rd_sz,sizeof(rdbuf)-rd_sz,".msg.%d",i);
            sctp_sendmsg(sockfd,rdbuf,sizeof(rdbuf),to,tolen,0,0,i,0,0);
        }

        struct sockaddr_in peeraddr;
        int flag;
        for(i=0;i<SERV_MAX_SCTP_STRM;++i)
        {
            socklen_t len=sizeof(peeraddr);
            rd_sz=sctp_recvmsg(sockfd,rvbuf,sizeof(rdbuf),(struct sockaddr *)&peeraddr,&len,&sri,&flag);

            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,rvbuf);
        }
    }
    return;
}

int main(int argc,char **argv)
{
    int flag=0;
    if(argc<2)
        err_quit("please input server ip");
    else if(argc>2)
        flag=1;
    //sock
    int sockfd=socket(AF_INET,SOCK_SEQPACKET,IPPROTO_SCTP);
    
    struct sockaddr_in servaddr;
    bzero(&servaddr,sizeof(servaddr));
    servaddr.sin_family=AF_INET;
    servaddr.sin_port=htons(SERV_PORT);
    inet_pton(AF_INET,argv[1],&servaddr.sin_addr);

    struct sctp_event_subscribe events;
    bzero(&events,sizeof(events));
    events.sctp_data_io_event=1;
    setsockopt(sockfd,IPPROTO_SCTP,SCTP_EVENTS,&events,sizeof(events));

    if(flag==0)
        sctp_cli(sockfd,(struct sockaddr *)&servaddr,sizeof(servaddr));
    else
        sctp_cli_all(sockfd,(struct sockaddr *)&servaddr,sizeof(servaddr));

    /*
     * ABORT类似于tcp的rst分节,无延迟的终止任何关联,尚未发送的任何数据都
     * 丢弃,也没有TCP的TIME_WAIT的不良影响,
     */
    /*
    char beymsg[20];
    strcpy(beymsg,"goodbey");
    sctp_sendmsg(sockfd,beymsg,strlen(beymsg),(struct sockaddr *)&servaddr,sizeof(servaddr),0,MSG_ABORT,0,0,0);*/
    close(sockfd);
    return 0;
}

server.c

/*************************************************************************
    > File Name: client.c
    > Author: Chen
    > Mail: 971859774@qq.com 
    > Created Time: 2018年11月14日 星期三 14时56分38秒
 ************************************************************************/

#include <stdio.h>
#include <stdlib.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <string.h>
#include <strings.h>
#include <netinet/sctp.h>
#include "my_err.h"

#define SERV_PORT 9877
#define LISTENQ 1024

sctp_assoc_t sctp_get_no_strms(int sock_fd,struct sockaddr *to,socklen_t tolen,struct sctp_sndrcvinfo sri)
{
    int retsz;
    struct sctp_status status;
    retsz=sizeof(status);
    bzero(&status,sizeof(status));

    status.sstat_assoc_id=sri.sinfo_assoc_id;
    getsockopt(sock_fd,IPPROTO_SCTP,SCTP_STATUS,&status,&retsz);
    return status.sstat_outstrms;
}

int main(int argc,char **argv)
{
    //socket
    int sockfd=socket(AF_INET,SOCK_SEQPACKET,IPPROTO_SCTP);

    struct sockaddr_in servaddr,cliaddr;
    bzero(&servaddr,sizeof(servaddr));
    servaddr.sin_family=AF_INET;
    servaddr.sin_port=htons(SERV_PORT);
    servaddr.sin_addr.s_addr=htonl(INADDR_ANY);

    //bind
    bind(sockfd,(struct sockaddr *)&servaddr,sizeof(servaddr));

    struct sctp_event_subscribe events;
    bzero(&events,sizeof(events));
    events.sctp_data_io_event=1;//预定,每次recvmsg返回sctp_sndrcvifo
    setsockopt(sockfd,IPPROTO_SCTP,SCTP_EVENTS,&events,sizeof(events));

    //listen
    listen(sockfd,LISTENQ);
    
    char rdbuf[MAXLINE];
    struct sctp_sndrcvinfo sri;
    int flag,index=1;
    while(1)
    {
        socklen_t len=sizeof(struct sockaddr_in);
        size_t rd_sz=sctp_recvmsg(sockfd,rdbuf,sizeof(rdbuf),(struct sockaddr *)&cliaddr,&len,&sri,&flag);
        
        if(index)
        {
            ++sri.sinfo_stream;
            if(sri.sinfo_stream>=
             sctp_get_no_strms(sockfd,(struct sockaddr *)&cliaddr,len,sri))//如果流号增长到大于等于最大流号,重新置为0
                sri.sinfo_stream=0;
        }
        /*
         * 服务器在发送完消息后终止关联,设置MSG_EOF标志。该标志迫使发送消
         * 被客户确认后,相应的关联终止
         */
        sctp_sendmsg(sockfd,rdbuf,rd_sz,(struct sockaddr *)&cliaddr,len,sri.sinfo_ppid,(sri.sinfo_flags),sri.sinfo_stream,0,0);
    }
    return 0;

}
原文地址:https://www.cnblogs.com/tianzeng/p/9960077.html