Chinaunix首页 | 论坛 | 博客
  • 博客访问: 7743889
  • 博文数量: 701
  • 博客积分: 2150
  • 博客等级: 上尉
  • 技术积分: 13233
  • 用 户 组: 普通用户
  • 注册时间: 2011-06-29 16:28
个人简介

天行健,君子以自强不息!

文章分类

全部博文(701)

文章存档

2019年(2)

2018年(12)

2017年(76)

2016年(120)

2015年(178)

2014年(129)

2013年(123)

2012年(61)

分类: 网络与安全

2013-09-18 15:04:52

简介
这是我在做一个要用UDP方式进行数据传输时,自己写的一个多线程的UDP数据接收服务器,
它能将接收到的UDP数据包存成文件,并提供数据包接收时间监测;
还支持键盘命令响应,以将数据写到新的文件,和退出程序;
闲言少述,直接上代码;


代码:
/*
 ******************************************************************************
 * \File
 *   udp_server.c
 * \Descript
 *   Receive udp datas and write into file, implement by multi-threads
 * \Author
 *   Anderson Yan
 * \Create
 *   2013-9-18
 ******************************************************************************
 */


#include
#include
#include
#include
#include
#include
#include
#include


#include
/* For signal response */
#include
#include
#include
#include
#include
#include
#include


static struct termios oldtty;
static int q_pressed = 0;
static int verbose = 0;
static int using_stdin = 0;
static int run_as_daemon = 0;




static volatile int received_sigterm = 0;


static void term_init(void);
static void term_exit(void);
static void sigterm_handler(int sig);
static int read_key(void);
/* end */


/* For parsing command-line parameters */
extern char* optarg;
extern int   opterr;
struct option opts[] = 
{
  {"port", required_argument, NULL, 'p'},
  {"out",  required_argument, NULL, 'o'},
  {"help", required_argument, NULL, 'h'},
  {0,0,0,0}
};


int parse_params(int agrc, char** argv, int* port, char* f);
/* end */


#define SERVPORT 10000
#define MAXDATASIZE 2048
FILE* fp_udp = NULL;
void *sock_recv_udp(void *arg);


static int bTerminalFlag = 0;


int main(int argc, char** argv)
{
  int file_number = 0;
  int  udp_port = SERVPORT;
  char filename[128] = "test.dat";
  char filename_new[256] = {0};


  int res;
  pthread_t tid_sock;
  void *thread_result;


  /* 命令行输入参数解析 */
  if (argc < 2)
  {
    printf("Usage: \n");
    printf("-p port : set listern port\n");
    printf("-o file : set output filename\n");
    printf("-h      : print help infomation\n");
    printf("eg :\n");
    printf("$./udp_server -p 10001 -o test.dat\n"); 
    exit(1);
  }
  parse_params(argc, argv, &udp_port, filename); 


  /* SIGNAL,键盘命令响应的初始化 */
  int key;
  if (!using_stdin)
  {
    if (verbose >=0)
      printf("Press [q] to stop, [?] for help, [n] for creating new file\n");
  }
  term_init();
  /* end */


  fp_udp = fopen(filename, "wb");
  if (fp_udp == NULL)
  {
    perror("Open file failed");
    exit(EXIT_FAILURE);
  }


  res = pthread_create(&tid_sock, NULL, sock_recv_udp, (void*)&udp_port);
  if (res != 0)
  {
    perror("Thread creation failed");
    exit(EXIT_FAILURE);
  }


  /* Response for keyboard */
  for(; received_sigterm == 0;)
  {
    if (verbose != file_number)
    {
      file_number = verbose;
      bTerminalFlag = 0;
      snprintf(filename_new, sizeof(filename_new),"%s.%d",filename, file_number);
      printf("Create new file : %s\n", filename_new);


      fp_udp = fopen(filename_new, "wb");
      if (fp_udp == NULL)
      {
        perror("Open file failed");
        exit(EXIT_FAILURE);
      }


      res = pthread_create(&tid_sock, NULL, sock_recv_udp, (void*)&udp_port);
      if (res != 0)
      {
        perror("Thread creation failed");
        exit(EXIT_FAILURE);
      }
    }
    /* if 'q' pressed, exits */
    if (!using_stdin)
    {
      if (q_pressed)
        break;


      /* read_key() returns 0 on EOF */
      key = read_key();
      if (key == 'q')
      {
        printf("quit\n");
        bTerminalFlag = 1;
        break;
      }
      if (key == 'n')
      {
        verbose++;
        printf("verbose = %d\n", verbose);


        bTerminalFlag = 1;
        printf("Waiting for thread to finish...\n");
        res = pthread_join(tid_sock, &thread_result);
        if (res != 0)
        {
          perror("Thread join failed");
          exit(EXIT_FAILURE);
        }
        printf("Thread joined, it returned %s\n", (char*)thread_result);


        memset(filename_new, 0, sizeof(filename_new));
        fflush(fp_udp);
        fclose(fp_udp);
      }
      if (key == '?')
      {
        printf("key function\n"
               "? show this help\n"
               "n create new file\n"
               "q quit\n");
      }
    }
  }
  /* end */


  printf("Waiting for thread to finish...\n");
  res = pthread_join(tid_sock, &thread_result);
  if (res != 0)
  {
    perror("Thread join failed");
    exit(EXIT_FAILURE);
  }
  printf("Thread joined, it returned %s\n", (char*)thread_result);


  fflush(fp_udp);
  fclose(fp_udp);


  return 0;
}




void *sock_recv_udp(void *arg)
{
  int port = *(int*)arg;


  int sockfd, recvbytes;
  char rcv_buf[MAXDATASIZE], snd_buf[MAXDATASIZE];
  struct sockaddr_in server_addr;
  socklen_t addr_size=sizeof(server_addr);
  int pkt_cnt = 0;


  struct timeval start_time, end_time;
  double time_used;


  int optval;
  printf("PORT : %d\n", port);


  if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
  {
    perror("socket:");
    exit(1);
  }


  server_addr.sin_family = AF_INET;
  server_addr.sin_port = htons(port);
  server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
  memset(&(server_addr.sin_zero), 0, 8);


  if (bind(sockfd, (struct sockaddr *)&server_addr, sizeof(struct sockaddr))==-1)
  {
    perror("bind:");
    exit(1);
  }


  optval = 1;
  int ret = setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval));


  while(!bTerminalFlag)
  {
    addr_size = sizeof(struct sockaddr);
    gettimeofday(&start_time, 0);


    /* receive the data from "server_addr" by "sockfd" and store into "rcv_buf" */
    if ((recvbytes = recvfrom(sockfd, rcv_buf, MAXDATASIZE, 0,
(struct sockaddr*)&server_addr, &addr_size)) == -1)
    {
      perror("recv:");
      exit(1);
    }


    fwrite(rcv_buf, 1, recvbytes, fp_udp);
    fflush(fp_udp);


    gettimeofday(&end_time, 0);
    time_used = 1000000 * (end_time.tv_sec - start_time.tv_sec)
                + end_time.tv_usec - start_time.tv_usec;
    time_used /= 1000;
    printf("recv:%s:%d : pkt_cnt = %6d :  %4d bytes : time(ms) = %f\n", 
  inet_ntoa(server_addr.sin_addr), ntohs(server_addr.sin_port), 
  pkt_cnt, recvbytes, time_used);


    pkt_cnt++;
  }
  close(sockfd);


  pthread_exit("thread sock_recv_udp over\n");
}


完整的代码可以在这里下载:


阅读(3341) | 评论(0) | 转发(0) |
0

上一篇:智力杠杆

下一篇:perl 邮件发送示例详解

给主人留下些什么吧!~~