sctp test
来源:互联网 发布:为什么java比php工资高 编辑:程序博客网 时间:2024/05/24 06:44
sctp简绍
1.SCTP全称
sctp(StreamControl Transmission Protocol)即流控制传送协议。
2. sctp是增强型的tcp协议
SCTP可以看做是TCP的增强协议,因为其可靠传输和拥塞控制机制基本都来自于TCP,但是它又对TCP进行了增强和完善,使得信令传输具有更高的可靠性。与TCP相比,SCTP最大的改变是增加了对多宿主(Multi-homing)、多流(Multi-streaming)以及部分有序(partialordering)的支持
3. sctp的多宿主特性(Mti-homing)
多宿主是指一个SCTP端点可以通过多个IP地址到达,这样两个SCTP端点在建立了关联后,数据可以通过不同的物理通路进行传送。也就是说,当一条通路坏掉后,可以通过另一条通路到达对端
4. sctp的多流特性(Muti-homing)
多流是指SCTP数据包会携带流标识和流序号,因此每个连接里有多个流的存在。由于采用多个流进行传输而且各个流相互独立,这样当一个流中的数据包需要重传,其他流中的数据可以继续传输, 解决了在TCP单流中容易出现的队头阻塞现象(head-of-line-blocking)
5. sctp的面向消息特性
sctp提供按序投递服务。和 UDP 一样,由发送端写入每条记录的长度,并随数据一同传递给接收端。SCTP是基于消息流,而TCP则是基于字节流。
6. source code
#include <stdio.h>#include <stdlib.h>#include <string.h>#include <unistd.h>#include <sys/types.h>#include <sys/socket.h>#include <netinet/in.h>#include <netinet/sctp.h>#include <arpa/inet.h>#include <time.h>#include <errno.h>#include <fcntl.h>#include <assert.h>#include <signal.h>#include <sys/time.h> #include <sys/utsname.h>#include <signal.h>#include <unistd.h> #include <getopt.h> static int streamno[] = {0, 1, 2, 3, 4};static int gSleepTime = 20; /* us */static long gTimer = 0; /* ms */static long gSendByte = 0;static long gRecByte = 0;static int gExit = 0;#define MAXRANGE 1600#define recBufSize (40*1024)#define MAX_BUFFER 256#define GMT_STREAM 256#define SYS_IT_INTERVAL_SEC 0#define URBAN_IT_INTERVAL_USEC (2*1000) /* 2ms */typedef enum _OS_VERSION{ OS_ES4, OS_CENTOS,}OS_VERSION;static int Linux_OS_Release=OS_ES4; /* 0=ES4, 1=CentOS */static void SetFSMTimer(){ struct itimerval *ptv, tv; struct utsname u_name; uname(&u_name); if(strstr(u_name.release,"2.6.9") == NULL) Linux_OS_Release = OS_CENTOS; ptv = (struct itimerval *) &tv; ptv->it_interval.tv_sec = SYS_IT_INTERVAL_SEC; ptv->it_value. tv_sec = SYS_IT_INTERVAL_SEC; /* if(Linux_OS_Release == OS_ES4) { ptv->it_interval.tv_usec = ES4_IT_INTERVAL_USEC; ptv->it_value.tv_usec = ES4_IT_INTERVAL_USEC; } else { ptv->it_interval.tv_usec = CENTOS_IT_INTERVAL_USEC; ptv->it_value.tv_usec = CENTOS_IT_INTERVAL_USEC; }*/ ptv->it_interval.tv_usec = URBAN_IT_INTERVAL_USEC; ptv->it_value.tv_usec = URBAN_IT_INTERVAL_USEC; setitimer(ITIMER_REAL, ptv, NULL);}static void sysTimer_IRQ(){ gTimer += 2;}static void SigactionSystem(){struct sigaction action;action.sa_handler = sysTimer_IRQ;sigemptyset(&action.sa_mask);action.sa_flags = SA_RESTART;if(sigaction(SIGALRM, &action, NULL)<0){printf("sigactin sigalarm failed\n");}}inline char *get_human_byte(long int byte){ static char human[256]; memset(human, 0, 256); if((byte >> 30) > 0) sprintf(human, "%ldG%ldM%ldK%ldB", byte >> 30, (byte >> 20) % 1024, (byte >> 10) % 1024, byte % 1024); else if((byte >> 20) > 0) sprintf(human, "%ldM%ldK%ldB", (byte >> 20) % 1024, (byte>>10) % 1024, byte % 1024); else if((byte >> 10) > 0) sprintf(human, "%ldK%ldB", (byte >> 10) % 1024, byte % 1024); else sprintf(human, "%ldB", byte % 1024); return human;}inline char *get_human_byte_v(long int byte){ static char human[256]; memset(human, 0, 256); if((byte >> 30) > 0) sprintf(human, "%ldG%ldM%ldK%ldB", byte >> 30, (byte >> 20) % 1024, (byte >> 10) % 1024, byte % 1024); else if((byte >> 20) > 0) sprintf(human, "%ldM%ldK%ldB", (byte >> 20) % 1024, (byte>>10) % 1024, byte % 1024); else if((byte >> 10) > 0) sprintf(human, "%ldK%ldB", (byte >> 10) % 1024, byte % 1024); else sprintf(human, "%ldB", byte % 1024); return human;}int client_init_socket(){ int connSock, on = 1; long rec_sock_buf_size = 40*1024; int send_sock_buf_size = 512*1024; /* Create SCTP TCP-Style Socket */ connSock = socket(AF_INET, SOCK_STREAM, IPPROTO_SCTP); /* set send buffer size */ if(setsockopt(connSock, SOL_SOCKET, SO_SNDBUF, &send_sock_buf_size, sizeof(send_sock_buf_size)) !=0) { fprintf(stderr, "%s set socket send buffer failed\n", __FUNCTION__); return -1; } /* set receive buffer size */ if(setsockopt(connSock, SOL_SOCKET, SO_RCVBUF, &rec_sock_buf_size, sizeof(rec_sock_buf_size)) != 0) { fprintf(stderr, "%s set socket rec buffer failed\n", __FUNCTION__); return -1; } /* set reuse addr */ if(setsockopt(connSock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) != 0) { fprintf(stderr, "%s set addr reusable failed\n", __FUNCTION__); return -1; } /* set no delay */ if(setsockopt(connSock, IPPROTO_SCTP, SCTP_NODELAY, &on, sizeof(on)) != 0) { fprintf(stderr, "%s set tcp no dealy failed\n", __FUNCTION__); return -1; } return connSock;}int client_connect(int connSock, unsigned short int serverPort, const char *pServerIP){ int in = 0; struct sockaddr_in servaddr; struct sctp_status status; struct sctp_event_subscribe events; struct sctp_initmsg initmsg; /* Specify that a maximum of 5 streams will be available per socket */ memset( &initmsg, 0, sizeof(initmsg) ); initmsg.sinit_num_ostreams = 5; initmsg.sinit_max_instreams = 5; initmsg.sinit_max_attempts = 4; /* Specify the peer endpoint to which we'll connect to*/ bzero( (void *)&servaddr, sizeof(servaddr) ); servaddr.sin_family = AF_INET; servaddr.sin_port = htons(serverPort); servaddr.sin_addr.s_addr = inet_addr( pServerIP ); /* Connect to the server */ if(connect( connSock, (struct sockaddr *)&servaddr, sizeof(servaddr)) < 0) { fprintf(stderr, "%s connect err. errno:%d errmsg:%s\n", __FUNCTION__, errno, strerror(errno)); return -1; } /* set nonblock */ if(fcntl(connSock, F_SETFL, O_NONBLOCK) < 0) { fprintf(stderr, "%s set nonblock failed\n", __FUNCTION__); return -1; } /* Enable receipt of SCTP Snd/Rcv Data via sctp_recvmsg */ memset( (void *)&events, 0, sizeof(events) ); events.sctp_data_io_event = 1; if( setsockopt( connSock, SOL_SCTP, SCTP_EVENTS, (const void *)&events, sizeof(events) ) < 0) { printf("setsockopt err. errno:%d errmsg:%s\n", errno, strerror(errno)); return -1; } /* Read and emit the status of the Socket (optional step) */ in = sizeof(status); if(getsockopt( connSock, SOL_SCTP, SCTP_STATUS, (void *)&status, (socklen_t *)&in ) < 0) { fprintf(stderr, "%s getsockopt err. errno:%d errmsg:%s\n", __FUNCTION__, errno, strerror(errno)); return -1; } printf("assoc id = %d\n", status.sstat_assoc_id ); printf("state = %d\n", status.sstat_state ); printf("instrms = %d\n", status.sstat_instrms ); printf("outstrms = %d\n", status.sstat_outstrms ); return 0;}inline int client_get_msg_len(const unsigned char *pMsg){ return ( (unsigned short int)(pMsg[0] - 0) << 8) + pMsg[1] - 0;}static int client(unsigned short int serverPort, const char *pServerIP){ static long int sTimer = 0; int connSock, in, flags, totalRecPackNum = 0; struct sctp_sndrcvinfo sndrcvinfo; unsigned char buffer[recBufSize+1]; connSock = client_init_socket(); if(client_connect(connSock, serverPort, pServerIP) < 0) { fprintf(stderr, "%s client_connet err.\n", __FUNCTION__); close(connSock); return -1; } for (; ;) { in = sctp_recvmsg(connSock, (void *)buffer, recBufSize, (struct sockaddr *)NULL, 0, &sndrcvinfo, &flags); if (in > 0) { buffer[in] = 0; gRecByte += in; totalRecPackNum++; if(0 == (gTimer % 1000) && 0 != gTimer && sTimer != gTimer) { printf("receiveByteV:%s/s recPackV:%ld recBytes:%s recTime:%ld.%ld(m)\n", get_human_byte_v(gRecByte/(gTimer/1000)), totalRecPackNum/(gTimer/1000), get_human_byte(gRecByte), gTimer/1000, gTimer%1000); sTimer = gTimer; } if(0 != sndrcvinfo.sinfo_ppid) printf("ppid:%x\n", sndrcvinfo.sinfo_ppid); // printf("TotalRecPackNum:%d streamno:%d recLen:%d lenInMsg:%d\n", ++totalRecPackNum, sndrcvinfo.sinfo_stream, in, client_get_msg_len(buffer)/*, buffer + 2*/); /* check msg len rec len */ if(in != (2 + client_get_msg_len(buffer)) ) { fprintf(stderr, "err\n"); close(connSock); assert(in == (2 + client_get_msg_len(buffer))); } } // usleep(gSleepTime); if(1 == gExit) { close(connSock); return 0; } } /* Close our socket and exit */ fprintf(stderr, "%s err\n", __FUNCTION__); close(connSock); return 0;}inline static const unsigned char *get_rand_str(int maxRange, int *realRange){ /* a-z A-Z */ // const int maxCharNum = 51; static unsigned char str[MAXRANGE]; // int i = 0, readRandRange; // char ch; if(maxRange >= MAXRANGE) return NULL;/* srand( (unsigned)time(NULL) ); readRandRange = rand()%maxRange; // printf("RAND_MAX:%ld readRandRange:%d\n", RAND_MAX, readRandRange); for(i = 0; i < readRandRange; ++i) { ch = rand() % maxCharNum; // printf("ch:%d\n", ch); if(ch > (maxCharNum>>1)) ch = 'A' + ch - 25; else ch = 'a' + ch; str[i+2] = ch; } str[0] = ((readRandRange & 0xff00) >> 8); str[1] = (readRandRange & 0xff); *realRange = readRandRange + 2;*/ str[0] = ((maxRange & 0xff00) >> 8); str[1] = (maxRange & 0xff); *realRange = maxRange + 2; // str[*realRange] = '0'; // printf("len:%d strLen:%d str:%s\n", *realRange, client_get_msg_len(str), str); return str;}int server_init_socket(){ int listenSock, on = 1; long rec_sock_buf_size = 40*1024; int send_sock_buf_size = 512*1024; /* Create SCTP TCP-Style Socket */ listenSock = socket(AF_INET, SOCK_STREAM, IPPROTO_SCTP); /* set send buffer size */ if(setsockopt(listenSock, SOL_SOCKET, SO_SNDBUF, &send_sock_buf_size, sizeof(send_sock_buf_size)) !=0) { fprintf(stderr, "%s set socket send buffer failed\n", __FUNCTION__); return -1; } /* set receive buffer size */ if(setsockopt(listenSock, SOL_SOCKET, SO_RCVBUF, &rec_sock_buf_size, sizeof(rec_sock_buf_size)) != 0) { fprintf(stderr, "%s set socket rec buffer failed\n", __FUNCTION__); return -1; } if(setsockopt(listenSock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) != 0) { fprintf(stderr, "%s set addr reusable failed\n", __FUNCTION__); return -1; } /* set no delay */ if(setsockopt(listenSock, IPPROTO_SCTP, SCTP_NODELAY, &on, sizeof(on)) != 0) { fprintf(stderr, "%s set tcp no dealy failed\n", __FUNCTION__); return -1; } return listenSock;}int server_bindandlisten(int listenSock, unsigned short int localServerPort, const char *pServerIP){ struct sockaddr_in servaddr; struct sctp_initmsg initmsg; /* Accept connections from any interface */ bzero( (void *)&servaddr, sizeof(servaddr) ); servaddr.sin_family = AF_INET; servaddr.sin_addr.s_addr = inet_addr( pServerIP ); // htonl( INADDR_ANY); servaddr.sin_port = htons(localServerPort); if(bind(listenSock, (struct sockaddr *)&servaddr, sizeof(servaddr)) < 0) { fprintf(stderr, "%s bind err. errno:%d errmsg:%s\n", __FUNCTION__, errno, strerror(errno)); return -1; } /* set nonblock */ if(fcntl(listenSock, F_SETFL, O_NONBLOCK) < 0) { fprintf(stderr, "%s set nonblock failed\n", __FUNCTION__); return -1; } /* Specify that a maximum of 5 streams will be available per socket */ memset( &initmsg, 0, sizeof(initmsg) ); initmsg.sinit_num_ostreams = 5; initmsg.sinit_max_instreams = 5; initmsg.sinit_max_attempts = 4; if(setsockopt( listenSock, IPPROTO_SCTP, SCTP_INITMSG, &initmsg, sizeof(initmsg) ) < 0) { fprintf(stderr, "%s setsockopt err. errno:%d errmsg:%s\n", __FUNCTION__, errno, strerror(errno)); return -1; } /* Place the server socket into the listening state */ listen(listenSock, 5); return 0;}static int server(unsigned short int localServerPort, const char *pServerIP){ long int sTimer = 0; int listenSock, connSock; const unsigned char *pSendMsg = NULL; int sendLen = 0, totalSendPackNum = 0; long int protID = 55; listenSock = server_init_socket(); server_bindandlisten(listenSock, localServerPort, pServerIP); /* Server loop... */ while(1) { /* Await a new client connection */ printf("Awaiting a new connection\n"); while(1) { connSock = accept( listenSock, (struct sockaddr *)NULL, (socklen_t *)NULL ); if(connSock < 0) { fprintf(stderr, "%s accept err. connSock:%d errno:%d errmsg:%s\n", __FUNCTION__, connSock, errno, strerror(errno)); continue; } break; } printf("accept suc and ready to sleep 10 seconds\n"); sleep(30); printf("after sleep 30 seconds\n"); /* New client socket has connected then send msg to the client socket*/ while(1) { if((pSendMsg = get_rand_str(200, &sendLen)) == NULL) { fprintf(stderr, "%s get_rand_str err\n", __FUNCTION__); return -1; } if(sendLen <= 0) { fprintf(stderr, "%s sendLen:%d\n", __FUNCTION__, sendLen); continue; } if(sctp_sendmsg( connSock, (void *)pSendMsg, sendLen, NULL, 0, protID, 0, streamno[2], 0, 0 ) < 0) { fprintf(stderr, "%s sctp_sendmsg errno:%d errmsg:%s\n", __FUNCTION__, errno, strerror(errno)); return -1; } protID = ((protID + 1) % 0x100000000); // printf("totalPackNum:%d v:%d streamno:%d sendLen:%d lenInmsg:%d\n", ++totalSendPackNum, streamno[0], sendLen, client_get_msg_len(pSendMsg)/*, pSendMsg + 2*/); gSendByte += sendLen; totalSendPackNum++; if(0 == (gTimer % 1000) && 0 != gTimer && sTimer != gTimer) { printf("sendByteV:%s/s sendPackV:%ld sendByte:%s timeNow:%ld.%ld(s)\n", get_human_byte_v(gSendByte/(gTimer/1000)), totalSendPackNum/(gTimer/1000), get_human_byte(gSendByte), gTimer/1000, gTimer%1000); sTimer = gTimer; } // usleep(gSleepTime); if(1 == gExit) { close(connSock); return 0; } } /* Close the client connection */ close( connSock ); } return 0;} void sig_handler(int sig){ if(sig == SIGINT) { printf("ctrl+c has been keydowned\n"); gExit = 1; }}int main(int argc, char **argv){ int retval, isServer = -1; char clientIP[256] = {0}; char serverIP[256] = {0}; unsigned short int clientPort; unsigned short int serverPort;SigactionSystem();SetFSMTimer(); signal(SIGINT, sig_handler); while((retval = getopt(argc, argv, "cst")) != -1) { switch(retval) { case 'c': // optind: next command index optarg: command string strcpy(clientIP, argv[optind]); clientPort = atoi(argv[optind + 1]); isServer = 0; break; case 's': strcpy(serverIP, argv[optind]); serverPort = atoi(argv[optind + 1]); isServer = 1; break; case 't': gSleepTime = atoi(argv[optind]); break; default: break; } } if(1 == isServer) return server(serverPort, serverIP); else if(0 == isServer) return client(clientPort, clientIP); printf("usage: xx -c serverIP serverPort/-s serverPort/-t\n"); return 0;}
7. compile
gcc -Wall -g -o xx sctp.c -lsctp
8. host a client run: ./sctp -s b 2222 -t 1
host b server run: ./sctp -c b 2222 -t 1
0 0
- sctp test
- linux kernel sctp test
- SCTP
- SCTP
- SCTP
- SCTP浅谈
- sctp编程
- SCTP编程
- SCTP编程
- SCTP编程
- sctp介绍
- SCTP详解
- sctp介绍
- SCTP编程
- sctp AIX
- SCTP简介
- 【转载·SCTP协议】浅析 - SCTP协议
- 使用 SCTP 优化网络
- 利用OpenCV实现图像纹理特征提取
- 服务器相关技术调研
- 基于内容的推荐系统概述
- Mongodb MapReduce
- Davinci DM6446开发攻略——linux-2.6.18移植
- sctp test
- 0011 认识理解Java中native方法【基础】
- CentOS Linux安装RPMForge源
- j2ee期末复习概要
- [综合面试] 牛人整理分享的面试知识:操作系统、计算机网络、设计模式、Linux编程,数据结构总结
- ssh框架
- malloc()与calloc区别
- PHP框架 百万级时 要注意的事项
- JavaSE_jdk新特性