• UDP数据接收服务器


    简介
    这是我在做一个要用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 <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <pthread.h>
    #include <sys/time.h>
    #include <unistd.h>


    #include <getopt.h>
    /* For signal response */
    #include <signal.h>
    #include <limits.h>
    #include <unistd.h>
    #include <fcntl.h>
    #include <sys/ioctl.h>
    #include <sys/time.h>
    #include <termios.h>


    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: ");
        printf("-p port : set listern port ");
        printf("-o file : set output filename ");
        printf("-h      : print help infomation ");
        printf("eg : ");
        printf("$./udp_server -p 10001 -o test.dat "); 
        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 ");
      }
      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 ", 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 ");
            bTerminalFlag = 1;
            break;
          }
          if (key == 'n')
          {
            verbose++;
            printf("verbose = %d ", verbose);


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


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


      printf("Waiting for thread to finish... ");
      res = pthread_join(tid_sock, &thread_result);
      if (res != 0)
      {
        perror("Thread join failed");
        exit(EXIT_FAILURE);
      }
      printf("Thread joined, it returned %s ", (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 ", 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 ", 
      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 ");
    }


    完整的代码可以在这里下载:
    http://download.csdn.net/detail/fireroll/6286649

     
  • 相关阅读:
    博客园 Open Live Writer 博客编辑工具&代码高亮显示插件 安装使用说明
    测试高亮代码
    Linux 查看操作系统版本信息 uname
    Linux 查看登录用户信息 who & whoami
    Linux crontab 每5秒钟执行一次 shell 脚本 的方法
    Linux 查找特定程序 whereis
    Java 语言实现 MD5 加密
    Maven 官网 查找&下载 jar包& pom引用 完美方案
    ArcGIS Engine 10.x许可代码
    IIS 无法显示网页 目前访问网站的用户过多
  • 原文地址:https://www.cnblogs.com/james1207/p/3329150.html
Copyright © 2020-2023  润新知