Windows下使用C语言创建定时器并周期和网络调试助手通信

在Windows C下采用timeSetEvent函数来设置定时器

关于timeSetEvent的函数原型及注释如下所示:

MMRESULT timeSetEvent(
  UINT           uDelay,       // 定时事件的触发周期,单位为毫秒
  UINT           uResolution,  // 定时事件的精度,单位为毫秒;值越小精度越高,
  LPTIMECALLBACK lpTimeProc,   // 定时事件的回调函数,每周期就调用该回调函数
  DWORD_PTR      dwUser,       // 用户提供的回调数据,可以默认置为0
  UINT           fuEvent       // 定时器的类型
);

**lpTimeProc:**触发事件的回调函数,回调函数的声明如下:

void WINAPI CallBackFunc(UINT uTimerID, UINT uMsg, DWORD_PTR dwUser, DWORD_PTR dw1, DWORD_PTR dw2)// uTimerID 为定时器的ID,

**fuEvent:**定时器的类型,分为以下两种类型:

​ TIME_ONESHOT:当经过 uDelay 时间之后,只调用一次

​ TIME_PERIODC:周期执行,每经过 uDelay 时间,就调用一次

**返回值:**当函数执行成功,就返回该定时器的ID,如果失败则返回NULL

下面为 timeSetEvent 函数的应用示例:

#include <Windows.h>                //需要包含该头文件
#include <iostream>
using namespace std;
 
#pragma comment(lib,"Winmm.lib")	//For timeSetEvent
 
//定时器的回调函数
void WINAPI TimerCallback(UINT uTimerID, UINT uMsg, DWORD_PTR dwUser, DWORD_PTR dw1, DWORD_PTR dw2)
{
	cout << ">>> 定时器回调函数" << endl;
}
 
int main()
{
	DWORD_PTR dwUser = NULL;
 
    // 设置定时器
	int timerID = timeSetEvent(1000, 1, (LPTIMECALLBACK)TimerCallback, dwUser, TIME_PERIODIC);    
	if(timerID != NULL)
		cout << ">>> 定时器创建成功" << endl;
 
	char ch = '0';
	while(ch != 'q')
	{
		ch = getchar();
	}
	timeKillEvent(timerID);    //关闭定时器
	return 0;
}

不过,在MSDN上看到, timeSetEvent 函数已经过时了,现在都在用 CreateTimerQueueTimer 函数。

周期和网络调试助手通信

前面一篇文章:Windows下C语言程序和网络调试助手通信

已经讲解了C语言程序和网络调试助手之间的通信,现在我们更进一步,创建周期性的C语言程序来和网络调试助手进行通信。

创建周期性的函数任务,我们需要使用定时器,利用Windows提供的timeSetEvent,我们可以方便地创建出周期性的函数任务。

代码如下:

#include <Windows.h>                //需要包含该头文件
#include <stdio.h>
 
#pragma comment(lib,"Winmm.lib")	//For timeSetEvent

#include <WinSock2.h>
#pragma comment(lib, "ws2_32.lib")  //加载 ws2_32.dll
 
//定时器1的回调函数
void WINAPI TimerCallback1(UINT uTimerID, UINT uMsg, DWORD_PTR dwUser, DWORD_PTR dw1, DWORD_PTR dw2)
{
	WSADATA wsaData;
    WSAStartup(MAKEWORD(2, 2), &wsaData);
    //创建套接字
    SOCKET sock = socket(PF_INET, SOCK_DGRAM, 0);
    //服务器地址信息
    struct sockaddr_in servAddr;
    memset(&servAddr, 0, sizeof(servAddr));  //每个字节都用0填充
    servAddr.sin_family = PF_INET;
    servAddr.sin_addr.s_addr = inet_addr("127.0.0.1");
    servAddr.sin_port = htons(1234);
	printf("我是第一个周期函数,周期为1s\n");
	char buffer[100] = "wiliyuan";
    sendto(sock, buffer, strlen(buffer), 0, (struct sockaddr*)&servAddr, sizeof(servAddr));
	
}

//定时器2的回调函数
void WINAPI TimerCallback2(UINT uTimerID, UINT uMsg, DWORD_PTR dwUser, DWORD_PTR dw1, DWORD_PTR dw2)
{
	WSADATA wsaData;
    WSAStartup(MAKEWORD(2, 2), &wsaData);
    //创建套接字
    SOCKET sock = socket(PF_INET, SOCK_DGRAM, 0);
    //服务器地址信息
    struct sockaddr_in servAddr;
    memset(&servAddr, 0, sizeof(servAddr));  //每个字节都用0填充
    servAddr.sin_family = PF_INET;
    servAddr.sin_addr.s_addr = inet_addr("127.0.0.1");
    servAddr.sin_port = htons(2345);
	printf("我是第二个周期函数,周期为2s\n");
	char buffer[100] = "xky";
    sendto(sock, buffer, strlen(buffer), 0, (struct sockaddr*)&servAddr, sizeof(servAddr));
	
}
 
int main()
{
	DWORD_PTR dwUser = NULL;
 
    // 设置定时器
	int timerID1 = timeSetEvent(1000, 1, (LPTIMECALLBACK)TimerCallback1, dwUser, TIME_PERIODIC);    
	if(timerID1 != NULL)
		printf("定时器1创建成功\n");
	
	int timerID2 = timeSetEvent(2000, 1, (LPTIMECALLBACK)TimerCallback2, dwUser, TIME_PERIODIC);    
	if(timerID2 != NULL)
		printf("定时器2创建成功\n");	
	
	while(1)
	{
		;
	}
	timeKillEvent(timerID1);    //关闭定时器1
	timeKillEvent(timerID2);    //关闭定时器2
	return 0;
}

该代码创建了两个周期函数,一个周期为1000ms,一个为2000ms。两个周期函数都通过UDP通信向外发送数据。发送目标ip都为127.0.0.0,一个端口号为1234,一个为2345。

我们打开两个网络调试助手,设置成上面的参数,运行代码,结果如下图所示:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-D6j7S4lE-1670767587306)(C:\Users\10521\AppData\Roaming\Typora\typora-user-images\image-20221211220109807.png)]

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小熊coder

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值