SCTP应用测试代码

这是一个SCTP测试工具的源代码实现,用于进行性能测试和连接管理。代码中包含了连接、监听、数据发送、性能测试等功能,并使用epoll进行事件驱动。通过命令行输入,可以设置各种参数并执行不同操作。
摘要由CSDN通过智能技术生成


/*****************************************************************************/
/******sctp test tool standard v1.0
scutzxb@sina.com 2016.11.18***************/
/*****************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#include <unistd.h>
#include <time.h>
#include <sys/socket.h>
#include <netdb.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <netinet/sctp.h>
#include <errno.h>
#include <stddef.h>
#include <sys/epoll.h>
#include <sched.h>
#include <arpa/inet.h>

#define TOOL_VERSION "1.0"
#define MAX_BUFF_SIZE 65525
#define DEF_BUFF_SIZE 150
#define EPOLLEVENTS 65536
#define MAX_CMD_LEN 100
#define MAX_CMD_DISC_LEN 100
#define SCTP_GET_PARA   1
#define SCTP_SET_PARA   2

#define PERFORMANCE_TEST_START "performance test start"
#define PERFORMANCE_TEST_END "performance test end"
#define DATA_PERFORMANCE_TEST_START "data sending performance test start"
#define DATA_PERFORMANCE_TEST_END "data sending performance test end"

#define O_NONBLOCK 00004000
#define F_GETFL  3 /* get file->f_flags */
#define F_SETFL  4 /* set file->f_flags */

#define DEBUG_PRINT(fd, fmt,args...) {if(!g_performance_test && !g_data_performance_test && !get_fd_pt(fd)) printf(fmt, ##args);}

unsigned char g_local_ip_1[50] = {0};
unsigned char g_local_ip_2[50] = {0};
unsigned short g_local_port = 0;
unsigned char g_remote_ip_1[50] = {0};
unsigned char g_remote_ip_2[50] = {0};
unsigned short g_remote_port = 0;
unsigned char g_test_v4 = 0;
unsigned char g_test_v6 = 0;
unsigned char g_multi_homing = 0;
unsigned char g_client_server = 0;
unsigned char g_performance_test =0;
unsigned char g_data_performance_test =0;
unsigned char g_connect_mod = 0; /* 0: connect; 1: setsockopt */
unsigned char g_pmtu = 1; /* 0: disable pmtu; 1: enable pmtu */
int g_max_conn_num = 65535;
int g_message_len = 150;
int g_data_pt_time = 10; /* 10 seconds */
unsigned long g_message_num = 65536;
unsigned long g_message_received = 0;
unsigned long g_message_total_size = 0;
int g_failure_cnt = 0;
int g_success_cnt = 0;
int g_hbinterval = 1000;
int g_sackdelay = 110; /* 0: disable sackdelay */
int g_rto_init = 200;
int g_rto_min = 150;
int g_rto_max = 200;
int g_first_fd = 0;
time_t g_first;
time_t g_last;
int g_fd_count = 0;
int g_epfd;

static bool inline add_to_epoll(int fd)
{
 struct epoll_event ev;
 int ret;

 memset(&ev, 0, sizeof(ev));
 ev.events = EPOLLIN | EPOLLET;
 ev.data.fd = fd;
 ret = epoll_ctl(g_epfd, EPOLL_CTL_ADD, fd, &ev);
 if (ret < 0) {
  printf("[EPOLL_CTL_ADD error] %d:%s\n", errno, strerror(errno));
  return false;
 }
 return true;
}

static bool inline del_from_epoll(int fd)
{
 struct epoll_event ev;
 int ret;

 memset(&ev, 0, sizeof(ev));
 ev.data.fd = fd;
 ret = epoll_ctl(g_epfd, EPOLL_CTL_DEL, fd, &ev);
 if (ret < 0) {
  printf("[EPOLL_CTL_DEL error] fd = %d, %d:%s\n", fd, errno, strerror(errno));
  return false;
 }
 return true;
}

#define MAX_FD 65536
#define MASK_FD 65535
#define MAX_CONFLICT 3
#define UNUSED_SK_TYPE 0
#define LISTEN_SK_TYPE 1
#define CONN_SK_TYPE  2
#define REMOVE_SK_TYPE 3

struct fd_list {
 int fd;
 unsigned char type;
 unsigned char state;
 unsigned char performance_test;
} g_fd_list[MAX_FD][MAX_CONFLICT];

pthread_mutex_t fd_list_lock;

enum sk_state {
 SK_STATE_CLOSED = 0,
 SK_STATE_LISTENING,
 SK_STATE_ACCEPTED,
 SK_STATE_CONNECTING,
 SK_STATE_COMM_UP,
 SK_STATE_MAX
};

struct sk_state_description {
 char state;
 char description[MAX_CMD_LEN];
} g_sk_state_list[SK_STATE_MAX] = {
 {SK_STATE_CLOSED, "closed"},
 {SK_STATE_LISTENING, "listening"},
 {SK_STATE_ACCEPTED, "accepted"},
 {SK_STATE_CONNECTING, "connecting"},
 {SK_STATE_COMM_UP, "established"}
};

static void inline add_to_fd_list_unlock(int fd, unsigned char type, unsigned char state)
{
 int i, key;
 
 key = MASK_FD&fd;
 for (i = 0; i < MAX_CONFLICT && g_fd_list[key][i].fd != 0 && g_fd_list[key][i].fd != fd; i++) {
 }
 if (i < MAX_CONFLICT && g_fd_list[key][i].type == REMOVE_SK_TYPE) {
  g_fd_list[key][i].type = UNUSED_SK_TYPE;
  return;
 }
 if (i < MAX_CONFLICT && g_fd_list[key][i].fd == 0) {
  g_fd_list[key][i].fd = fd;
  g_fd_list[key][i].type = type;
  g_fd_list[key][i].state = state;
  g_fd_list[key][i].performance_test = g_performance_test;
  g_fd_count++;
 } else if (g_fd_list[key][i].fd == fd) {
  /* update_fd_list() may be called before add_to_fd_list() */
  g_fd_list[key][i].type = type;
 } else {
  printf("[add_to_fd_list] too many conflict fds, key = %d\n", key);
 }
}

static void inline add_to_fd_list(int fd, unsigned char type, unsigned char state)
{
 pthread_mutex_lock(&fd_list_lock);
 add_to_fd_list_unlock(fd, type, state);
 pthread_mutex_unlock(&fd_list_lock);
}

static void inline update_fd_state(int fd, unsigned char state)
{
 int i, key;

 key = MASK_FD&fd;
 pthread_mutex_lock(&fd_list_lock);
 for (i = 0; i < MAX_CONFLICT && g_fd_list[key][i].fd != fd; i++) {
 }
 if (i < MAX_CONFLICT && g_fd_list[key][i].fd == fd) {
  g_fd_list[key][i].state = state;
 } else {
  /* update_fd_list() may be called before add_to_fd_list() */
  add_to_fd_list_unlock(fd, 0, state);
 }
 pthread_mutex_unlock(&fd_list_lock);
}

static void inline remove_from_fd_list(int fd)
{
 int i, key;
 
 key = MASK_FD&fd;
 pthread_mutex_lock(&fd_list_lock);
 for (i = 0; i < MAX_CONFLICT && g_fd_list[key][i].fd != fd; i++) {
 }
 if (i < MAX_CONFLICT && g_fd_list[key][i].fd == fd) {
  g_fd_list[key][i].fd = 0;
  g_fd_list[key][i].type = UNUSED_SK_TYPE;
  g_fd_list[key][i].state = 0;
  g_fd_count--;
 } else {
  for (i = 0; i < MAX_CONFLICT && g_fd_list[key][i].fd != 0; i++) {
  }
  if (i < MAX_CONFLICT && g_fd_list[key][i].fd == 0) {
   g_fd_list[key][i].type = REMOVE_SK_TYPE;
  }
 }
 pthread_mutex_unlock(&fd_list_lock);
}

unsigned char inline get_fd_type(int fd)
{
 int i, key;

 key = MASK_FD&fd;
 pthread_mutex_lock(&fd_list_lock);
 for (i = 0; i < MAX_CONFLICT && g_fd_list[key][i].fd != fd; i++) {
 }
 if (i < MAX_CONFLICT && g_fd_list[key][i].fd == fd) {
  pthread_mutex_unlock(&fd_list_lock);
  return g_fd_list[key][i].type;
 }
 pthread_mutex_unlock(&fd_list_lock);
 return UNUSED_SK_TYPE;
}

unsigned char inline get_fd_pt(int fd)
{
 int i, key;

 key = MASK_FD&fd;
 pthread_mutex_lock(&fd_list_lock);
 for (i = 0; i < MAX_CONFLICT && g_fd_list[key][i].fd != fd; i++) {
 }
 if (i < MAX_CONFLICT && g_fd_list[key][i].fd == fd) {
  pthread_mutex_unlock(&fd_list_lock);
  return g_fd_list[key][i].performance_test;
 }
 pthread_mutex_unlock(&fd_list_lock);
 return 0;
}

static void inline clean_fd(int fd)
{
 if (get_fd_type(fd) == CONN_SK_TYPE)
  del_from_epoll(fd);
 remove_from_fd_list(fd);
 close(fd);
}

static void inline clean_all_cnn_fds()
{
 int i, j;

 pthread_mutex_lock(&fd_list_lock);
 for (i = 0; i < MAX_FD; i++) {
  for (j = 0; j < MAX_CONFLICT; j++) {
   if (g_fd_list[i][j].type != UNUSED_SK_TYPE) {
    if (g_fd_list[i][j].type == CONN_SK_TYPE) {
     del_from_epoll(g_fd_list[i][j].fd);
     close(g_fd_list[i][j].fd);
     memset(&g_fd_list[i][j], 0, sizeof(struct fd_list));
     g_fd_count--;
    }
   }
  }
 }
 pthread_mutex_unlock(&fd_list_lock);
}

static void inline update_all_cnn_fds()
{
 int i, j;

 pthread_mutex_lock(&fd_list_lock);
 for (i = 0; i < MAX_FD; i++) {
  for (j = 0; j < MAX_CONFLICT; j++) {
   if (g_fd_list[i][j].type != UNUSED_SK_TYPE) {
    if (g_fd_list[i][j].type == CONN_SK_TYPE) {
     g_fd_list[i][j].performance_test = 1;
    }
   }
  }
 }
 pthread_mutex_unlock(&fd_list_lock);
}

static void inline print_fd_list()
{
 int i, j;

 pthread_mutex_lock(&fd_list_lock);
 for (i = 0; i < MAX_FD; i++) {
  for (j = 0; j < MAX_CONFLICT; j++) {
   if (g_fd_list[i][j].fd != 0) {
    printf("[fd list] fd = %d, style = %s, state = %s\n",
     g_fd_list[i][j].fd,
     (g_fd_list[i][j].type == LISTEN_SK_TYPE)?"listen":"connect",
     g_sk_state_list[g_fd_list[i][j].state].description);
   }
  }
 }
 pthread_mutex_unlock(&fd_list_lock);
 printf("[fd list] total = %d\n", g_fd_count);
}

bool ch_to_i(unsigned char *d, char *s)
{
 bool ret = true;

 if (s[0] >= 'A' && s[0] <= 'Z')
  *d = (s[0] - 'A' + 10) << 4;
 else if (s[0] >= 'a' && s[0] <= 'z')
  *d = (s[0] - 'a' + 10) << 4;
 else if (s[0] >= '0' && s[0] &l

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值