C++定时器函数

qin_pp 2012-11-01 09:06:15
我现在写一个有关定时器的函数,使用过程首先想到的是用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;

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

Sleep(500);

Ret = RecvData(sHost);

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

return -1;

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

sID--;

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

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

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

printf("超时");

return -1;
}
}

closesocket(sHost);

WSACleanup();

system("pause");

时间历程调用如下:


static int xintiao = 0;
//该函数实现向服务器发送心跳,时间间隔是 2 s
void CALLBACK TimeProc(HWND hwnd,

UINT message,

UINT idTimer,

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

DATATOSEND tempdatatosend;

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

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

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

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

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

//发送心跳数据包
int Ret;

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

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

LastTime = GetTickCount();



}

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

//该函数实现通过套接字 s 将数据发送过去
int SendData(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开始

int Ret;

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);
}
return 1;
}

想问有没有不阻塞的实现方式,定时发送闹钟报文,而在这期间则发送报文?
...全文
1539 10 打赏 收藏 转发到动态 举报
写回复
用AI写文章
10 条回复
切换为时间正序
请发表友善的回复…
发表回复
ertuy123 2013-10-30
  • 打赏
  • 举报
回复
SetTimer(NULL,timer1,5000,TimerProc);这样的是不会调用TimerProc的,程序会继续跑,但是也不是说自己根据消息调用TimerProc。真正的处理过程是,进程从系统消息队列中取出消息,进程接着派送消息,让系统去调用我们的回调函数。
Java路漫漫 2012-11-02
  • 打赏
  • 举报
回复
我看了一下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程序,其中,保证相互发送程序包有时间间隔,并且有设定状态。
我的建议是:采用线程异步操作。

baichi4141 2012-11-02
  • 打赏
  • 举报
回复
迄今为止只用过最后一个参数是NULL的SetTimer
  • 打赏
  • 举报
回复
没有必要2个线程,一个线程就够了。
JiMoKuangXiangQu 2012-11-02
  • 打赏
  • 举报
回复
SetTimer()函数会导致产生一个WM_TIMER消息,然后这个消息由你的WinProc()或者DefWindowProc()来处理,再由它们间接的调用用SetTimer()注册的timer回调.也就是说,SetTimer()应该用在基于消息循环结构的程序下.

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

将程序改成基于消息驱动的方式应该能解决问题.
qin_pp 2012-11-02
  • 打赏
  • 举报
回复
谢谢你,我昨天晚上也想了一下,觉得客户端有必要采用双线程才能实现想要的功能,但是这样做,就与要求不相符合。主要就是想看看有没有一种时间处理函数,能够在处理自己的时间历程后的时间间隔,处理其他的事情,当时间到达后,再异步中断通知时间历程。

当然,也非常感谢楼上的几个兄弟的建议。
qin_pp 2012-11-01
  • 打赏
  • 举报
回复
UINT timerid = SetTimer(NULL, 1, 3000, TimeProc);例句中,定时器仅仅执行TimeProc历程,执行完就等待下一个时刻的到来!不会继续执行后续的语句
qin_pp 2012-11-01
  • 打赏
  • 举报
回复
并且只是执行自己的历程TimeProc,而不会继续往下执行。
qin_pp 2012-11-01
  • 打赏
  • 举报
回复
就是阻塞的,如果在哪里调用了,就会一直处于等待下一个时刻的到来
JiMoKuangXiangQu 2012-11-01
  • 打赏
  • 举报
回复
SetTimer()不是阻塞的吧?

64,649

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧