简介

这是我在做一个要用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: \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");


}

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


http://download.csdn.net/detail/fireroll/6286649

 

UDP数据接收服务器的更多相关文章

  1. udp协议的数据接收与发送的代码

    我想基于lwIP协议中的UDP协议,用单片机做一个服务器,接受电脑的指令然后返回数据.以下是我的代码 /************************************************ ...

  2. C#中UDP数据的发送、接收

    Visual C# UDP数据的发送、接收包使用的主要类及其用法: 用Visual C# UDP协议的实现,最为常用,也是最为关键的类就是UdpClient,UdpClient位于命名空间System ...

  3. 【04】AJAX接收服务器返回的数据

    AJAX接收服务器返回的数据 readyState 和 status 属性 readyState 属性保存有 XMLHttpRequest 对象的交互状态,从 0 到 4 变化: 0 :未初始化(还没 ...

  4. 浅谈UDP(数据包长度,收包能力,丢包及进程结构选择)

    UDP数据包长度 UDP数据包的理论长度 udp数据包的理论长度是多少,合适的udp数据包应该是多少呢?从TCP-IP详解卷一第11章的udp数据包的包头可以看出,udp的最大包长度是2^16-1的个 ...

  5. UDP信息接收与发送

    转载:http://www.cnblogs.com/sunev/archive/2012/08/08/2627247.html 一.摘要 总结基于C#的UDP协议的同步通信. 二.实验平台 Visua ...

  6. 详解TCP和UDP数据段的首部格式

    TCP数据段的首部格式: 源端口号(16) 目的端口号(16) 序列号(32) 确认应答号(32) 数据偏移(4) 保留(6) 代码位(6) 窗口(16) 校验和(16) 紧急指针 选项(长度可变) ...

  7. C#UDP(接收和发送源码)源码完整

    C#UDP(接收和发送源码)源码完整 最近做了一个UDP的服务接收和发送的东西.希望能对初学的朋友一点帮助. 源码如下: 一.逻辑--UdpServer.cs using System;using S ...

  8. 实现UDP高效接收/响应

    环境Linux g++6.3.0 问题一:一个ip地址如何接收高并发请求 问题二:如何高并发响应消息 发送请求端只能通过ip地址+端口号向服务器发送请求码,所以服务器只能用一个UDP去绑定此ip以及端 ...

  9. UDP和多线程服务器

    UDP: UDP是数据报文传输协议,这个传输协议比较野蛮,发送端不需要理会接收端是否存在,直接就发送数据,不会像TCP协议一样建立连接.如果接收端不存在的话,发送的数据就会丢失,UDP协议不会去理会数 ...

随机推荐

  1. leetcode_question_119 Pascal's Triangle II

    Given an index k, return the kth row of the Pascal's triangle. For example, given k = 3, Return [1,3 ...

  2. GSM Channel Mode Modify和Channel Mode Modify Acknowledge信令

    最近研究了下如何通过GSM Channel Mode Modify和Channel Mode Modify Acknowledge信令,获知GSM终端支持的data Rate   思路与原理: • I ...

  3. AS3读取加密XML

    首先要确定xml使用了哪些加密方式,这样在As3中就反过来解密. 我加密xml的方式是先将xml文件打包为一个压缩文件,然后将压缩文件进行RC4加密,最后用base64将加密过的压缩包转为base64 ...

  4. jquery点击按钮显示和隐藏DIv

    function changeDisplay() { if ($("#btnShow").attr("value")== "添加附件") { ...

  5. wordpress提速插件

    auto-remove-googles-url插件,替换前后台国外字体!访问速度有较大提高!可百度搜索auto-remove-googles-url下载,如在wp后台进行插件安装即可

  6. bzoj1626[Usaco2007 Dec]Building Roads 修建道路

    Description Farmer John最近得到了一些新的农场,他想新修一些道路使得他的所有农场可以经过原有的或是新修的道路互达(也就是说,从任一个农场都可以经过一些首尾相连道路到达剩下的所有农 ...

  7. JS控制菜单样式切换

    $('#subtabs a').each(function (i, ele) { var href = $(ele).attr("href"); if (location.href ...

  8. Java集合的实现细节—Set集合和Map集合

    Set:代表无序.不可重复的集合 Map:代表key-value对集合,也称为关联数组 从表面上看,Set和Map相似性很少,但实际上可以说Map集合时Set集合的扩展. 1.Set集合和Map集合的 ...

  9. Linux磁盘及文件系统管理 2---- 使用fdisk进行磁盘管理

    1 FDISK分区工具 1 fsidk是来自IBM的分区工具,支持绝大多数的操作系统,几乎所有的Linux都装有fdisk 2 fdisk是一个支持MBR的分区工具,如果要使用GPT的话我们无法使用f ...

  10. (转)iOS7界面设计规范(4) - UI基础 - 布局

    好吧,第四篇的样子,节奏还好:我怎么又是刚吃过小龙虾的状况呢. 今天的话题是布局,篇幅很短:我自己好喜欢这样,在还有些剩余时间和精力的情况下,一个话题一个话题的推进,做做译文,并热切的希望这些内容在自 ...