• 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;
    
    }
  • 相关阅读:
    Python 的编码格式
    Python import其他层级的模块
    自己写ORM框架 DBUtils_DG Java(C#的写在链接里)
    C#对象深度克隆
    SpringMVC文件上传下载
    HttpRuntime.Cache .Net自带的缓存类
    Winform跨窗体操作控件(使用委托)
    Winform调用WebKitBrowser,基于chrome内核WebKit的浏览器控件
    ORM框架 EF code first 的封装 优化一
    Go Language 开发环境搭建
  • 原文地址:https://www.cnblogs.com/tianzeng/p/9960077.html
Copyright © 2020-2023  润新知