一、服务器程序

#include    <stdlib.h>
#include    <string.h>
#include    <strings.h>
#include    <sys/types.h>
#include    <sys/socket.h>
#include    <netinet/sctp.h>    

#define     LISTENQ              1024
#define     BUFFSIZE             4096
#define     SERV_PORT            9877

#define     SA   struct sockaddr

int sctp_get_no_strms(int, struct sockaddr *, socklen_t);
sctp_assoc_t sctp_address_to_associd(int, struct sockaddr *, socklen_t);

int main(int argc, char **argv)
{
    int sock_fd,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]);
        }
        sock_fd = 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(sock_fd, (SA *) &servaddr, sizeof(servaddr));
    
    bzero(&evnts, sizeof(evnts));
    evnts.sctp_data_io_event = 1;
    setsockopt(sock_fd, IPPROTO_SCTP, SCTP_EVENTS,
            &evnts, sizeof(evnts));

    listen(sock_fd, LISTENQ);

    for ( ; ; ) {
        len = sizeof(struct sockaddr_in);
        rd_sz = sctp_recvmsg(sock_fd, readbuf, sizeof(readbuf),
                 (SA *)&cliaddr, &len,
                 &sri,&msg_flags);

        if(stream_increment) {
            sri.sinfo_stream++;
            if(sri.sinfo_stream >= sctp_get_no_strms(sock_fd,(SA *)&cliaddr, 
                len)) {
                sri.sinfo_stream = 0;
            }
        }
        sctp_sendmsg(sock_fd, readbuf, rd_sz, 
            (SA *)&cliaddr, len,
            sri.sinfo_ppid,
            sri.sinfo_flags,
            sri.sinfo_stream,
            0, 0
        );
    }
}

int sctp_get_no_strms(int sock_fd,struct sockaddr *to, socklen_t tolen)
{
    int 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);
}

sctp_assoc_t sctp_address_to_associd(int sock_fd, 
    struct sockaddr *sa, socklen_t salen)
{
    struct sctp_paddrparams sp;
    int 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);
}

二、客户端程序

SRE实战 互联网时代守护先锋,助力企业售后服务体系运筹帷幄!一键直达领取阿里云限量特价优惠。
#include    <stdio.h>
#include    <stdlib.h>
#include    <unistd.h>
#include    <string.h>
#include    <strings.h>
#include    <arpa/inet.h>
#include    <sys/socket.h>
#include    <netinet/sctp.h>

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

#define     SA  struct sockaddr

void err_quit(const char *, ...); 
void sctpstr_cli(FILE *, int, struct sockaddr *, socklen_t);
void sctpstr_cli_echoall(FILE *, int, struct sockaddr *, socklen_t);

int main(int argc, char **argv)
{
    int sock_fd;
        char *byemsg;
    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) {
        printf("Echoing messages to all streams\n");
        echo_to_all = 1;
    }
        sock_fd = socket(AF_INET, SOCK_SEQPACKET, IPPROTO_SCTP);
    bzero(&servaddr, sizeof(servaddr));
    servaddr.sin_family = AF_INET;
    servaddr.sin_port = htons(SERV_PORT);
    inet_pton(AF_INET, argv[1], &servaddr.sin_addr);

    bzero(&evnts, sizeof(evnts));
    evnts.sctp_data_io_event = 1;
    setsockopt(sock_fd, IPPROTO_SCTP, SCTP_EVENTS,&evnts, sizeof(evnts));

    if(echo_to_all == 0) {
        sctpstr_cli(stdin, sock_fd, (SA *)&servaddr, sizeof(servaddr));
    } else {
        sctpstr_cli_echoall(stdin, sock_fd, (SA *)&servaddr, sizeof(servaddr));
    }

    close(sock_fd);

    return(0);
}

void sctpstr_cli(FILE *fp, int sock_fd, 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;

    bzero(&sri,sizeof(sri));
    while (fgets(sendline, MAXLINE, fp) != NULL) {
        if(sendline[0] != '[' && sendline[2] != ']') {
            printf("Error, line must be of the form '[streamnum]text'\n");
            continue;
        }
        sri.sinfo_stream = strtol(&sendline[1],NULL,0);
        out_sz = strlen(sendline);
        int d = sctp_sendmsg(sock_fd, sendline, out_sz, 
                 to, tolen, 
                 0, 0,
                 sri.sinfo_stream,
                 0, 0);

        printf("d = %d\n", d);

        len = sizeof(peeraddr);
        rd_sz = sctp_recvmsg(sock_fd, recvline, sizeof(recvline),
                 (SA *)&peeraddr, &len,
                 &sri,&msg_flags);

        printf("rd_sz = %d\n", rd_sz);

        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);
    }
}

void 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),
                     (SA *)&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\n",rd_sz,recvline);
        }
    }
}
#include    <stdio.h>
#include    <errno.h>
#include    <stdlib.h>
#include    <string.h>
#include    <stdarg.h>        /* ANSI C header file */
#include    <syslog.h>        /* for syslog() */

#define     MAXLINE     4096

int        daemon_proc;       /* set nonzero by daemon_init() */

static void    err_doit(int, int, const char *, va_list);

/* Nonfatal error related to system call
 * Print message and return */

void err_ret(const char *fmt, ...) {

    va_list        ap;    

    va_start(ap, fmt);    
    err_doit(1, LOG_INFO, fmt, ap);
    va_end(ap);
    return;
}

/* Fatal error related to system call
 * Print message and terminate */

void err_sys(const char *fmt, ...) {

    va_list        ap;

    va_start(ap, fmt);
    err_doit(1, LOG_ERR, fmt, ap);
    va_end(ap);
    exit(1);
}

/* Fatal error related to system call
 * Print message, dump core, and terminate */

void err_dump(const char *fmt, ...) {
    va_list        ap;

    va_start(ap, fmt);
    err_doit(1, LOG_ERR, fmt, ap);
    va_end(ap);
    abort();        /* dump core and terminate */
    exit(1);        /* shouldn't get here */
}

/* Nonfatal error unrelated to system call
 * Print message and return */

void err_msg(const char *fmt, ...) {

    va_list        ap;

    va_start(ap, fmt);
    err_doit(0, LOG_INFO, fmt, ap);
    va_end(ap);
    return;
}

/* Fatal error unrelated to system call
 * Print message and terminate */

void err_quit(const char *fmt, ...) {

    va_list        ap;

    va_start(ap, fmt);
    err_doit(0, LOG_ERR, fmt, ap);
    va_end(ap);
    exit(1);
}

/* Print message and return to caller
 * Caller specifies "errnoflag" and "level" */

static void err_doit(int errnoflag, int level, const char *fmt, va_list ap) {

    int        errno_save, n;
    char    buf[MAXLINE + 1];

    errno_save = errno;                /* value caller might want printed */
#ifdef    HAVE_VSNPRINTF
    vsnprintf(buf, MAXLINE, fmt, ap);  /* safe */
#else
    vsprintf(buf, fmt, ap);            /* not safe */
#endif
    n = strlen(buf);
    if (errnoflag)
        snprintf(buf + n, MAXLINE - n, ": %s", strerror(errno_save));
    strcat(buf, "\n");

    if (daemon_proc) {
        syslog(level, buf);
    } else {
        fflush(stdout);                /* in case stdout and stderr are the same */
        fputs(buf, stderr);
        fflush(stderr);
    }
    return;
}

 

扫码关注我们
微信号:SRE实战
拒绝背锅 运筹帷幄