SCTP并发服务器
2018-03-14 20:07
218 查看
注:一定要通过setsockopt函数开启sctp_io_data_event事件,否则得到的关联号可能为0,从而调用getpeeloff失败
服务器端代码:
服务器端代码:
#include <stdio.h> #include <sys/socket.h> #include <stdlib.h> #include <string.h> #include <errno.h> #include <netdb.h> #include <netinet/sctp.h> #include <unistd.h> #include <arpa/inet.h> #include <sys/wait.h> #define BUFSIZE 4096 #define LISTENQ 100 const char* Inet_ntop(void* ptr) { static char str[INET_ADDRSTRLEN]; return inet_ntop(AF_INET,ptr,str,INET_ADDRSTRLEN); } static void sig_child(int signo) { int pid; while ((pid = waitpid(-1,NULL,WNOHANG)) > 0) { printf("child process %d terminated\n",pid); } } void server_echo(int sockfd) { struct sctp_sndrcvinfo sri; struct sockaddr_in clientaddr; socklen_t len = sizeof(struct sockaddr_in); int pid; char buf[BUFSIZE]; ssize_t n; int connfd; sctp_assoc_t id; bzero(&sri,sizeof(struct sctp_sndrcvinfo)); struct sctp_event_subscribe events; bzero(&events,sizeof(struct sctp_event_subscribe)); events.sctp_data_io_event = 1; if (setsockopt(sockfd,IPPROTO_SCTP,SCTP_EVENTS,&events,sizeof(struct sctp_event_subscribe)) < 0) { printf("setsockopt error: %s\n",strerror(errno)); exit(1); } while ((n = sctp_recvmsg(sockfd,buf,BUFSIZE,(struct sockaddr*)&clientaddr,&len,&sri,&len)) > 0) { if (sctp_sendmsg(sockfd,buf,n,(struct sockaddr*)&clientaddr,len,0,0,2,0,0) != n) { printf("sctp_sendmsg error: %s\n",strerror(errno)); break; } if ((connfd = sctp_peeloff(sockfd,sri.sinfo_assoc_id)) < 0) { printf("sctp_peeloff error: %s\n",strerror(errno)); exit(1); } if ((pid = fork()) < 0) { printf("fork error: %s\n",strerror(errno)); exit(1); }else if (pid == 0) { char childbuf[BUFSIZE]; ssize_t n; struct sockaddr_in peer; socklen_t peerlen = sizeof(struct sockaddr_in); struct sctp_sndrcvinfo csri; int cflags; while ((n = sctp_recvmsg(connfd,childbuf,BUFSIZE,(struct sockaddr*)&peer,&peerlen,&csri,&cflags)) > 0) { printf("child process pid = %d from IP: %s\n",getpid(),Inet_ntop(&peer.sin_addr)); if (sctp_sendmsg(connfd,childbuf,n,(struct sockaddr*)&peer,peerlen,0,0,3,0,0) != n) { printf("sctp_sendmsg error: %s\n",strerror(errno)); exit(1); } } exit(0); } } } int main(int argc,char** argv) { if (argc != 2) { printf("please add or check <service-name or port>\n"); exit(1); } struct addrinfo hints; bzero(&hints,sizeof(struct addrinfo)); hints.ai_flags = AI_PASSIVE; hints.ai_family = AF_INET; hints.ai_socktype = SOCK_SEQPACKET; hints.ai_protocol = IPPROTO_SCTP; struct addrinfo* results; int err; if ((err = getaddrinfo(NULL,argv[1],&hints,&results)) != 0) { printf("getaddrinfo error: %s\n",strerror(err)); exit(1); } struct addrinfo* dummy = results; int sockfd; for (; dummy != NULL; dummy = dummy->ai_next) { if ((sockfd = socket(dummy->ai_family,dummy->ai_socktype,dummy->ai_protocol)) < 0) { continue; } if (bind(sockfd,dummy->ai_addr,dummy->ai_addrlen) == 0) { break; } close(sockfd); } if (dummy == NULL) { printf("all socket failed\n"); freeaddrinfo(results); exit(1); } if (listen(sockfd,LISTENQ) < 0) { printf("listen error: %s\n",strerror(errno)); exit(1); } freeaddrinfo(results); if (signal(SIGCHLD,sig_child) == SIG_ERR) { printf("signal error: %s\n",strerror(errno)); exit(1); } server_echo(sockfd); return 0; }
相关文章推荐
- 35-并发服务器(多进程)
- 3高并发服务器:多路IO之epoll
- 在Go中构建并发TCP服务器
- 4、搭建一个后台服务器--服务端代码(异步,大并发)
- 高性能、高并发TCP服务器(多线程调用libevent)
- 支持高并发的IIS Web服务器常用设置
- 高性能、高并发、高扩展性和可读性的网络服务器架构:StateThreads
- 单服务器架构下的多线程下数据库并发更新的处理方案
- Linux并发服务器编程之多线程并发服务器
- 优化Linux的内核参数来提高服务器并发处理能力
- 常见多线程与并发服务器设计方案举例
- linux服务器每秒并发处理数的计算方法
- 高负载高并发服务器开发参考
- 服务器高并发优化
- Java 并发TCP 服务器[CODE]
- Linux + C + Epoll实现高并发服务器(线程池 + 数据库连接池)
- Java Socket编程(四)重复和并发服务器
- 并发服务器(五):Redis 案例研究
- linux网络编程之并发服务器的三种实现模型 (超级经典)
- Linux下突破限制实现高并发量服务器