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: \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数据接收服务器的更多相关文章
- udp协议的数据接收与发送的代码
我想基于lwIP协议中的UDP协议,用单片机做一个服务器,接受电脑的指令然后返回数据.以下是我的代码 /************************************************ ...
- C#中UDP数据的发送、接收
Visual C# UDP数据的发送、接收包使用的主要类及其用法: 用Visual C# UDP协议的实现,最为常用,也是最为关键的类就是UdpClient,UdpClient位于命名空间System ...
- 【04】AJAX接收服务器返回的数据
AJAX接收服务器返回的数据 readyState 和 status 属性 readyState 属性保存有 XMLHttpRequest 对象的交互状态,从 0 到 4 变化: 0 :未初始化(还没 ...
- 浅谈UDP(数据包长度,收包能力,丢包及进程结构选择)
UDP数据包长度 UDP数据包的理论长度 udp数据包的理论长度是多少,合适的udp数据包应该是多少呢?从TCP-IP详解卷一第11章的udp数据包的包头可以看出,udp的最大包长度是2^16-1的个 ...
- UDP信息接收与发送
转载:http://www.cnblogs.com/sunev/archive/2012/08/08/2627247.html 一.摘要 总结基于C#的UDP协议的同步通信. 二.实验平台 Visua ...
- 详解TCP和UDP数据段的首部格式
TCP数据段的首部格式: 源端口号(16) 目的端口号(16) 序列号(32) 确认应答号(32) 数据偏移(4) 保留(6) 代码位(6) 窗口(16) 校验和(16) 紧急指针 选项(长度可变) ...
- C#UDP(接收和发送源码)源码完整
C#UDP(接收和发送源码)源码完整 最近做了一个UDP的服务接收和发送的东西.希望能对初学的朋友一点帮助. 源码如下: 一.逻辑--UdpServer.cs using System;using S ...
- 实现UDP高效接收/响应
环境Linux g++6.3.0 问题一:一个ip地址如何接收高并发请求 问题二:如何高并发响应消息 发送请求端只能通过ip地址+端口号向服务器发送请求码,所以服务器只能用一个UDP去绑定此ip以及端 ...
- UDP和多线程服务器
UDP: UDP是数据报文传输协议,这个传输协议比较野蛮,发送端不需要理会接收端是否存在,直接就发送数据,不会像TCP协议一样建立连接.如果接收端不存在的话,发送的数据就会丢失,UDP协议不会去理会数 ...
随机推荐
- BZOJ2754: [SCOI2012]喵星球上的点名
2754: [SCOI2012]喵星球上的点名 Time Limit: 20 Sec Memory Limit: 128 MBSubmit: 680 Solved: 314[Submit][Sta ...
- 转:Android模拟器连接电脑网络
原文地址:http://www.it165.net/pro/html/201212/4444.html 第一步: 在命令行(就是开始——运行——输入cmd)模式下输入adb shell命令一般会报两种 ...
- javaweb 登录注册
1:用户登录界面 login.jsp <%@ page language="java" import="java.util.*" pageEncoding ...
- Android 开机启动通知
效果图: 学习: 1.静态注册实现开机启动 <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLET ...
- SelectSort 选择排序
//SelectSort (( O(n²))) public class TestSelectSort { public int[] selectSortArray(int[] arr){ int m ...
- poj 2392 Space Elevator(多重背包+先排序)
Description The cows are going to space! They plan to achieve orbit by building a sort of space elev ...
- pyqt小例子 音乐盒
源代码1: # -*- coding: utf-8 -*- import sys,time,os import ctypes from PyQt4 import QtCore, QtGui,Qt fr ...
- html a标签打开邮件
<a href="mailto:frotech@foxmail.com" target="_blank">frotech@foxmail.com&l ...
- [Redux] Extracting Presentational Components -- TodoApp
Finally, I just noticed that the to-do app component doesn't actually have to be a class. I can turn ...
- C++刷称号——2707: 素数与要素
Description 从键盘输入的随机整数n,如果n不是质数,然后计算n所有的因素(不含1).例如,对于16,出口2,4,8:否则输出"It is a prime number." ...