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'\n"); 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]=='\n') { rdbuf[rd_sz-1]='\0'; --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\n",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; }