首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > C++ >

C++定时器函数解决思路

2013-10-30 
C++定时器函数我现在写一个有关定时器的函数,使用过程首先想到的是用SetTimer函数,但是这个函数是阻塞模式

C++定时器函数
我现在写一个有关定时器的函数,使用过程首先想到的是用SetTimer函数,但是这个函数是阻塞模式,即就是说,如果调用这个函数,程序就会一直阻塞在这个函数上,一直等待时间,调用自己的历程。

现在想实现一种功能,定时器到达一定时间间隔比如说 2 s,就向服务器发送一种报文,而这期间的其他时间,则发送另外一种数据报文。

各位大神,我将自己的一部分代码贴如下:

其中主程序部分:

printf("\n*******************客户端心跳程序****************************\n");

UINT timerid = SetTimer(NULL, 1, 3000, TimeProc);

MSG   msg;   

while(GetMessage(&msg,NULL,0,0))   
{   
if(msg.message==WM_TIMER)   
{   
DispatchMessage(&msg);   
}   
}

while (TRUE)
{

Ret = SendData(sHost);

if (Ret == -1)//函数返回-1,发送出错为且非阻塞,程序中断执行,直接返回

return-1;

elseif (Ret == 0)//发送失败,阻塞造成

Sleep(500);

Ret = RecvData(sHost);

if (Ret == -1)//接受失败

return -1;

elseif (Ret ==  0)//服务其要求重发

sID--;

//下面进行超时判断,当超时标记 FLAG  = 3;判断超时,自动断开连接
DWORDnowtime = GetTickCount();

if ((nowtime-LastTime)<TimeEnd)
{
if ((nowtime - LastTime) > TimeSpace){//超时一次,FLAG++操作一次

FLAG++;
}
elsecontinue;
}
elseif (FLAG>=2){//超时三次,退出程序

printf("超时");

return -1;
}
}

closesocket(sHost);

WSACleanup();

system("pause");

时间历程调用如下:


staticintxintiao = 0;
//该函数实现向服务器发送心跳,时间间隔是 2 s
voidCALLBACKTimeProc(HWND hwnd, 

UINT message,

UINT idTimer,

DWORD dwTimer){
//设置发送数据包的格式

DATATOSENDtempdatatosend;

memset(tempdatatosend.Buffer,0,DATA_BUFSIZE);//没有任何数据

tempdatatosend.Buflen = 0;//纯数据长度是0

tempdatatosend.DataType = 'T';//报文格式是‘T’心跳测试

tempdatatosend.dwTime = GetTickCount();//报文中含有当前时间,供系统刷新用

tempdatatosend.Sequence = xintiao++;//该字段没有意义

//发送心跳数据包
intRet;

printf("发送心跳!\n");

Ret = send(sHost,(LPSTR)&tempdatatosend,sizeof(DATATOSEND),0);

LastTime = GetTickCount();



}

现在想让时间历程和发送正常数据报文(如下)分别按照定时实现:

//该函数实现通过套接字 s 将数据发送过去
intSendData(SOCKET s){

//system("cls");


char temp[DATA_BUFSIZE] = "hello!!!" ;

Sleep(2000);
/*
memset(temp,0,DATA_BUFSIZE);

//接受输入用户数据

printf("\n\t\t输入向服务器发送数据:\n");


gets(temp);
*/


PDATATOSEND pdatatosend;

pdatatosend = &dataToSend;

//将数据复制到发送缓冲中
ZeroMemory(pdatatosend->Buffer,DATA_BUFSIZE);

strcpy_s(pdatatosend->Buffer,temp);

//填充发送结构体中的其他数据
pdatatosend->Buflen = strlen(temp);//数据长度存储起来

pdatatosend->DataType = 'D';//发送的类型是‘D’即就是数据

pdatatosend->dwTime = GetTickCount();//保存当前时间

pdatatosend->Sequence = sID++;//包的序号,从0开始

intRet;

Ret = send(sHost,(LPSTR)pdatatosend,sizeof(DATATOSEND)+4,0);


if (Ret == SOCKET_ERROR)
{
Ret = WSAGetLastError();

if (Ret == WSAEWOULDBLOCK)//无法完成非阻塞套接字上的操作
{
return 0;
}
else{
printf("发送失败\n%d",WSAGetLastError());
return-1;
}
}
else{//成功发送,表示与服务器交互成功

LastTime = GetTickCount();

FLAG = 0;

printf("序号 %d 包已经正常发送!\n\n",sID - 1);

printf("客户端发送的时间:%d\n\n",pdatatosend->dwTime);
}
return1;
}

想问有没有不阻塞的实现方式,定时发送闹钟报文,而在这期间则发送报文?
[解决办法]
我看了一下MSDN:
UINT_PTR SetTimer(
  __in  HWND hWnd,
  __in  UINT_PTR nIDEvent,
  __in  UINT uElapse,
  __in  TIMERPROC lpTimerFunc
);

有这么一句:
hWnd [in] 
HWND
Handle to the window to be associated with the timer. 【This window must be owned by the calling thread】. If a NULL value for hWnd is passed in along with an 【nIDEvent】 of an existing timer, that timer will be replaced in the same way that an existing non-NULL hWnd timer will be. 



是什么意思呢?我琢磨了一下,大概是要你创建一个线程,并且通过【事件】去管理操作。
-------------------------
抛开这些不说,我看的出来你的代码的意思:
创建一个C/S程序,其中,保证相互发送程序包有时间间隔,并且有设定状态。
我的建议是:采用线程异步操作。


[解决办法]
SetTimer()函数会导致产生一个WM_TIMER消息,然后这个消息由你的WinProc()或者DefWindowProc()来处理,再由它们间接的调用用SetTimer()注册的timer回调.也就是说,SetTimer()应该用在基于消息循环结构的程序下.

lz之所以会堵塞并不使因为SetTimer()是阻塞的,应该是lz的程序不是基于消息循环结构,进而系统无法传递给存在的消息处理过程,从而WM_TIMER消息始终得不到处理,导致程序阻塞.

将程序改成基于消息驱动的方式应该能解决问题.
[解决办法]
没有必要2个线程,一个线程就够了。
[解决办法]
迄今为止只用过最后一个参数是NULL的SetTimer

热点排行