读书人

SCTP 一对多方式 (UDP模式)的服务器

发布时间: 2013-09-05 16:02:07 作者: rapoo

SCTP 一对多模式 (UDP模式)的服务器端代码

以下源码是基于linux操作系统的。实现了基于SCTP协议的一对多模式的服务器端代码,该段不但处理的用户数据,而且处理了的通知类的消息,即notification消息。


#include <sys/types.h>#include <sys/socket.h>#include <netinet/in.h>#include <netinet/sctp.h>#include <arpa/inet.h>#include <string.h>#include <stdio.h>#include <stdlib.h>#include <unistd.h>static void handle_event(void *buf){struct sctp_assoc_change   *sac;struct sctp_send_failed    *ssf;struct sctp_paddr_change   *spc;struct sctp_remote_error   *sre;struct sctp_shutdown_event *sse;union sctp_notification  *snp;snp = (sctp_notification*)buf;switch (snp->sn_header.sn_type){case SCTP_ASSOC_CHANGE:{sac = &snp->sn_assoc_change;printf("assoc_change: state=%hu, error=%hu, instr=%hu outstr=%hu associd=%d\n", sac->sac_state, sac->sac_error,sac->sac_inbound_streams, sac->sac_outbound_streams,sac->sac_assoc_id);break;}case SCTP_SEND_FAILED:{ssf = &snp->sn_send_failed;printf("sendfailed: len=%hu err=%d assoc_i=%d ssf_data=%d\n", ssf->ssf_length, ssf->ssf_error, ssf->ssf_assoc_id, ssf->ssf_data[0]);break;}case SCTP_PEER_ADDR_CHANGE:{spc = &snp->sn_paddr_change;struct sockaddr_in  *sin = (struct sockaddr_in *)&spc->spc_aaddr;char  addrbuf[INET6_ADDRSTRLEN];inet_ntop(AF_INET, &sin->sin_addr, addrbuf, INET6_ADDRSTRLEN);printf("peeraddrchange: %s state=%d, error=%d\n", addrbuf, spc->spc_state, spc->spc_error);break;}case SCTP_REMOTE_ERROR:{sre = &snp->sn_remote_error;printf("remote_error: err=%hu len=%hu\n", ntohs(sre->sre_error), ntohs(sre->sre_length));break;}case SCTP_SHUTDOWN_EVENT:{sse = &snp->sn_shutdown_event;printf("shutdown event: assoc_id=%d\n", sse->sse_assoc_id);break;}default:{printf("unknown type: %hu\n", snp->sn_header.sn_type);break;}}}int main(int agrc, char* agrv[]){/* Create a 1-to-many style SCTP socket. */int fd = -1;if ((fd = socket(AF_INET, SOCK_SEQPACKET, IPPROTO_SCTP)) < 0){perror("socket");exit(1);}     /* Enable all notifications and events */struct sctp_event_subscribe event;     event.sctp_data_io_event = 1;     event.sctp_association_event = 1;     event.sctp_address_event = 1;     event.sctp_send_failure_event = 1;     event.sctp_peer_error_event = 1;     event.sctp_shutdown_event = 1;     event.sctp_partial_delivery_event = 1;     event.sctp_adaption_layer_event = 1;     if (setsockopt(fd, IPPROTO_SCTP, SCTP_EVENTS, &event, sizeof(event)) != 0){          perror("setevent failed");exit(1);}/* Configure auto-close timer. */int timeout = 5;if (setsockopt(fd, IPPROTO_SCTP, SCTP_AUTOCLOSE, &timeout, 4) < 0) {perror("setsockopt SCTP_AUTOCLOSE");exit(1);}/* Bind the socket to all local addresses. */struct sockaddr_in sin;bzero((char*)&sin, sizeof(sin));sin.sin_family = AF_INET;sin.sin_port = htons(19000);sin.sin_addr.s_addr = inet_addr("192.168.10.120");if (bind(fd, (struct sockaddr *)&sin, sizeof(sin)) == -1){perror("bind");exit(1);}/* Enable accepting associations. */if (listen(fd, 1) < 0) {perror("listen");exit(1);}char buffer[256];int bufferlen = 256;bzero(buffer, bufferlen);struct sockaddr_in clientaddr;int fromlen = sizeof(clientaddr);struct sctp_sndrcvinfo sndrcvinfo;int msg_flag;while(true) { int length = sctp_recvmsg(fd, buffer, bufferlen, (struct sockaddr*)&clientaddr, (socklen_t*)&fromlen, &sndrcvinfo, &msg_flag);if (msg_flag &  MSG_NOTIFICATION){printf("****************************************************\n");printf("Event: notificaiton length=%d\n", length);handle_event((void*)buffer);}else{printf("****************************************************\n");printf("Event: data event length=%d\n", length);char addrbuf[100];inet_ntop(AF_INET, &clientaddr.sin_addr, addrbuf, INET6_ADDRSTRLEN);int port = ntohs(clientaddr.sin_port);printf("data from=%s:%d\n", addrbuf, port);printf("data=%s\n", buffer);}}if (close(fd) < 0) {perror("close");exit(1);}return (0);}


读书人网 >其他相关

热点推荐