69,371
社区成员
发帖
与我相关
我的任务
分享
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <process.h>
#include <conio.h>
#pragma comment(lib,"Ws2_32.lib")
#define ALLOWERRORMAX 100 //允许的最大错误编号,大于此值的错误将导致程序终止
#define MAINSLEEPTIME 1000 //主线程错误检测间隔,毫秒
#define UDPPACKSIZE 1024 //UDP数据包大小
#define SOCKETWAITTIME 200 //网速速度过快时挂起等待时间,毫秒,测试用
#define DATABUFFSIZE 8192 //数据缓冲区大小,单位-UDPPACKSIZE
#define NETPORT 8000 //端口
int ERR_FLAG = 0; //错误标记
HANDLE TUWhEvent; //用于防止写入速度超过网络接受的事件
char (*DataBuff)[UDPPACKSIZE]; //数据缓冲区指针
//线程状态
struct ThreadAttr
{
unsigned long int Count;//计数器
int TEndFlag; //结束控制标记
int ErrFlag; //错误标记
};
volatile struct ThreadAttr TAUdpRec;
volatile struct ThreadAttr TAWriteDist;
FILE *TWriteDist_fdest; //数据写入位置
SOCKET TUdpRec_sUDP; //数据来源网络
void PrtErrorMessage(int err); //打印错误详情
int TcloseUdprec(void); //关闭udp线程
int TcloseWriteDist(void); //关闭写数据线程
void TUdpRec(void *Attr); //从UDP接受数据
void TWriteDist(void *Attr); //写入数据到内存
//主线程,控制线程
int main(void)
{
if((DataBuff = (char (*)[UDPPACKSIZE])malloc(DATABUFFSIZE*UDPPACKSIZE)) == NULL)//创建缓冲区
{
ERR_FLAG = 1;
PrtErrorMessage(ERR_FLAG);
return 0;
}
TUWhEvent = CreateEvent(NULL, TRUE, FALSE, NULL);//创建事件
//创建线程
_beginthread(TWriteDist, 0, NULL);
_beginthread(TUdpRec, 0, NULL);
//主线程
while(!_kbhit())
{
//一般错误
if(TAUdpRec.ErrFlag>ALLOWERRORMAX)
{
ERR_FLAG = TAUdpRec.ErrFlag;
PrtErrorMessage(ERR_FLAG);
}
if(TAWriteDist.ErrFlag>ALLOWERRORMAX)
{
ERR_FLAG = TAWriteDist.ErrFlag;
PrtErrorMessage(ERR_FLAG);
}
//致命错误
if(TAWriteDist.ErrFlag && TAUdpRec.ErrFlag<ALLOWERRORMAX)
{
ERR_FLAG = TAUdpRec.ErrFlag;
PrtErrorMessage(ERR_FLAG);
break;
}
if(TAWriteDist.ErrFlag && TAWriteDist.ErrFlag<ALLOWERRORMAX)
{
ERR_FLAG = TAWriteDist.ErrFlag;
PrtErrorMessage(ERR_FLAG);
break;
}
//PrtErrorMessage(ERR_FLAG);
Sleep(MAINSLEEPTIME);
}
//结束子线程
TcloseUdprec();
TcloseWriteDist();
printf("Client@> \n rec:%lu\n write:%lu\n\n", TAUdpRec.Count, TAWriteDist.Count);
free(DataBuff);
printf("Client@> Main Thread End.\n");
getchar();
getchar();
return 0;
}
//关闭udp线程
int TcloseUdprec(void)
{
TAUdpRec.TEndFlag = 1;
closesocket(TUdpRec_sUDP);
while(TAUdpRec.TEndFlag);
return TAUdpRec.ErrFlag;
}
//关闭写数据线程
int TcloseWriteDist(void)
{
TAWriteDist.TEndFlag = 1;
SetEvent(TUWhEvent);//使写入线程运行,以便进行必要的清理
while(TAWriteDist.TEndFlag);
return TAWriteDist.ErrFlag;
}
//从UDP接受数据
void TUdpRec(void *Attr)
{
WSADATA wsa;
struct sockaddr_in addr, from;
int SAddrLen = sizeof(struct sockaddr);
unsigned int RecvLen;//接收包长度
WSAStartup(0x101, &wsa);//载入合适的Winsock动态链接库
//初始化本地网络
TUdpRec_sUDP = socket(AF_INET, SOCK_DGRAM, 0);
addr.sin_family = AF_INET;
addr.sin_port = htons(NETPORT);
addr.sin_addr.s_addr = htonl(INADDR_ANY);
bind(TUdpRec_sUDP, (struct sockaddr*)&addr, sizeof(addr));//绑定到所有可用地址
TAUdpRec.Count = 0;
TAUdpRec.TEndFlag = 0;
TAUdpRec.ErrFlag = 0;
while(!TAUdpRec.TEndFlag)
{
if(TAUdpRec.Count-TAWriteDist.Count >= DATABUFFSIZE)
{
Sleep(SOCKETWAITTIME);
continue;
}
if((RecvLen = recvfrom(TUdpRec_sUDP, DataBuff[TAUdpRec.Count % DATABUFFSIZE], UDPPACKSIZE, 0, (struct sockaddr *)&from, &SAddrLen)) == SOCKET_ERROR)
{
if(!TAUdpRec.TEndFlag)
TAUdpRec.ErrFlag = 201;
else
break;//关闭socket时执行
}
TAUdpRec.Count++;
SetEvent(TUWhEvent);//当收到数据后置位事件,使写入线程运行
}
closesocket(TUdpRec_sUDP);
WSACleanup();//释放占用资源
printf("Client@> TUdpRec Thread End.\n");
TAUdpRec.TEndFlag = 0;
_endthread();
}
//写入数据到内存
void TWriteDist(void *Attr)
{
TAWriteDist.Count = 0;
TAWriteDist.TEndFlag = 0;//默认执行
TAWriteDist.ErrFlag = 0;
if((TWriteDist_fdest=fopen("UDP.DAT", "wb")) == NULL)
{
TAWriteDist.ErrFlag = 2;
_endthread();
}
fseek(TWriteDist_fdest, 0L, SEEK_SET);
while(1)
{
if(TAUdpRec.Count <= TAWriteDist.Count)
{
ResetEvent(TUWhEvent);//复位事件,使自己阻塞
}
WaitForSingleObject(TUWhEvent, INFINITE);//挂起,直到事件被置位
if(TAWriteDist.TEndFlag)
break;
fwrite(DataBuff[TAWriteDist.Count % DATABUFFSIZE], UDPPACKSIZE, 1, TWriteDist_fdest);
TAWriteDist.Count++;
}
//执行善后操作,存储当前已接收数据
// while(TAUdpRec.Count > TAWriteDist.Count)
// {
// fwrite(DataBuff[TAWriteDist.Count % DATABUFFSIZE], UDPPACKSIZE, 1, TWriteDist_fdest);
// TAWriteDist.Count++;
// }
fflush(TWriteDist_fdest);
fclose(TWriteDist_fdest);
printf("Client@> TWriteDist Thread End.\n");
TAWriteDist.TEndFlag = 0;
_endthread();
}
//打印错误详情,大于ALLOWERRORMAX的错误将导致程序终止
void PrtErrorMessage(int err)
{
switch(err)
{
case 0:
printf("Client@> run normal.\n");
break;
case 1:
printf("Client/Error@> malloc DataBuff unsuccessful.\n");
break;
case 2:
printf("Client/Error@> open udp.dat file unsuccessful.\n");
break;
case 201:
printf("Client/Warning@> recvfrom udp data exception.\n");
break;
default:
printf("Client/Warning@> undefine type.\n");
}
}
#include <stdio.h>#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <process.h>
#include <conio.h>
#pragma comment(lib,"Ws2_32.lib")
#define ALLOWERRORMAX 100 //允许的最大错误编号,大于此值的错误将导致程序终止
#define MAINSLEEPTIME 1000 //主线程错误检测间隔,毫秒
#define UDPPACKSIZE 1024 //UDP数据包大小
#define SOCKETWAITTIME 10 //网速速度过快时挂起等待时间,毫秒,测试用
#define DATABUFFSIZE 8192 //数据缓冲区大小,单位-UDPPACKSIZE
#define BUFFWRITESIZE 2048 //缓冲写(延时写入)大小,单位-UDPPACKSIZE
#define NETPORT 8000 //端口
int ERR_FLAG = 0; //错误标记
char (*DataBuff)[UDPPACKSIZE]; //数据缓冲区指针
//线程状态
struct ThreadAttr
{
unsigned long int Count;//计数器
int TEndFlag; //结束控制标记
int ErrFlag; //错误标记
};
volatile struct ThreadAttr TAUdpRec;
volatile struct ThreadAttr TAWriteDist;
FILE *TWriteDist_fdest; //数据写入位置
SOCKET TUdpRec_sUDP; //数据来源网络
void PrtErrorMessage(int err); //打印错误详情
int TcloseUdprec(void); //关闭udp线程
int TcloseWriteDist(void); //关闭写数据线程
void TUdpRec(void *Attr); //从UDP接受数据
void TWriteDist(void *Attr); //写入数据到内存
//主线程,控制线程
int main(void)
{
if((DataBuff = (char (*)[UDPPACKSIZE])malloc(DATABUFFSIZE*UDPPACKSIZE)) == NULL)//创建缓冲区
{
ERR_FLAG = 1;
PrtErrorMessage(ERR_FLAG);
return 0;
}
//创建线程
_beginthread(TWriteDist, 0, NULL);
_beginthread(TUdpRec, 0, NULL);
//主线程
while(!_kbhit())
{
//一般错误
if(TAUdpRec.ErrFlag>ALLOWERRORMAX)
{
ERR_FLAG = TAUdpRec.ErrFlag;
PrtErrorMessage(ERR_FLAG);
}
if(TAWriteDist.ErrFlag>ALLOWERRORMAX)
{
ERR_FLAG = TAWriteDist.ErrFlag;
PrtErrorMessage(ERR_FLAG);
}
//致命错误
if(TAWriteDist.ErrFlag && TAUdpRec.ErrFlag<ALLOWERRORMAX)
{
ERR_FLAG = TAUdpRec.ErrFlag;
PrtErrorMessage(ERR_FLAG);
break;
}
if(TAWriteDist.ErrFlag && TAWriteDist.ErrFlag<ALLOWERRORMAX)
{
ERR_FLAG = TAWriteDist.ErrFlag;
PrtErrorMessage(ERR_FLAG);
break;
}
//PrtErrorMessage(ERR_FLAG);
Sleep(MAINSLEEPTIME);
}
//结束子线程
TcloseUdprec();
TcloseWriteDist();
printf("Client@> \n rec:%lu\n write:%lu\n\n", TAUdpRec.Count, TAWriteDist.Count);
//free(DataBuff);
printf("Client@> Main Thread End.\n");
getchar();
getchar();
return 0;
}
//关闭udp线程
int TcloseUdprec(void)
{
TAUdpRec.TEndFlag = 1;
closesocket(TUdpRec_sUDP);
while(TAUdpRec.TEndFlag);
return TAUdpRec.ErrFlag;
}
//关闭写数据线程
int TcloseWriteDist(void)
{
TAWriteDist.TEndFlag = 1;
while(TAWriteDist.TEndFlag);//等待清理
return TAWriteDist.ErrFlag;
}
//从UDP接受数据
void TUdpRec(void *Attr)
{
WSADATA wsa;
struct sockaddr_in addr, from;
int SAddrLen = sizeof(struct sockaddr);
unsigned int RecvLen;//接收包长度
WSAStartup(0x101, &wsa);//载入合适的Winsock动态链接库
//初始化本地网络
TUdpRec_sUDP = socket(AF_INET, SOCK_DGRAM, 0);
addr.sin_family = AF_INET;
addr.sin_port = htons(NETPORT);
addr.sin_addr.s_addr = htonl(INADDR_ANY);
bind(TUdpRec_sUDP, (struct sockaddr*)&addr, sizeof(addr));//绑定到所有可用地址
TAUdpRec.Count = 0;
TAUdpRec.TEndFlag = 0;
TAUdpRec.ErrFlag = 0;
while(!TAUdpRec.TEndFlag)
{
if(TAUdpRec.Count-TAWriteDist.Count >= DATABUFFSIZE)//防止接受超越写入一圈
{
Sleep(SOCKETWAITTIME);
continue;
}
if((RecvLen = recvfrom(TUdpRec_sUDP, DataBuff[TAUdpRec.Count % DATABUFFSIZE], UDPPACKSIZE, 0, (struct sockaddr *)&from, &SAddrLen)) == SOCKET_ERROR)
{
if(!TAUdpRec.TEndFlag)
TAUdpRec.ErrFlag = 201;
else
break;//关闭socket时执行
}
TAUdpRec.Count++;
}
closesocket(TUdpRec_sUDP);
WSACleanup();//释放占用资源
printf("Client@> TUdpRec Thread End.\n");
TAUdpRec.TEndFlag = 0;
}
//写入数据到硬盘
void TWriteDist(void *Attr)
{
TAWriteDist.Count = 0;
TAWriteDist.TEndFlag = 0;//默认执行
TAWriteDist.ErrFlag = 0;
if((TWriteDist_fdest=fopen("UDP.DAT", "wb")) == NULL)
{
TAWriteDist.ErrFlag = 2;
_endthread();
}
fseek(TWriteDist_fdest, 0L, SEEK_SET);
while(1)
{
if(TAWriteDist.TEndFlag)
break;
if(TAUdpRec.Count <= TAWriteDist.Count)
{
continue;//不写,没有新数据
}
fwrite(DataBuff[TAWriteDist.Count % DATABUFFSIZE], UDPPACKSIZE, 1, TWriteDist_fdest);
TAWriteDist.Count++;
}
//执行善后操作,存储当前已接收数据
while(TAUdpRec.Count > TAWriteDist.Count)
{
fwrite(DataBuff[TAWriteDist.Count % DATABUFFSIZE], UDPPACKSIZE, 1, TWriteDist_fdest);
TAWriteDist.Count++;
}
fflush(TWriteDist_fdest);
fclose(TWriteDist_fdest);
printf("Client@> TWriteDist Thread End.\n");
TAWriteDist.TEndFlag = 0;
}
//打印错误详情,大于ALLOWERRORMAX的错误将导致程序终止
void PrtErrorMessage(int err)
{
switch(err)
{
case 0:
printf("Client@> run normal.\n");
break;
case 1:
printf("Client/Error@> malloc DataBuff unsuccessful.\n");
break;
case 2:
printf("Client/Error@> open udp.dat file unsuccessful.\n");
break;
case 201:
printf("Client/Warning@> recvfrom udp data exception.\n");
break;
default:
printf("Client/Warning@> undefine type.\n");
}
}