C++笔记-调用winsocket发送ICMP
·
知识点
整个流程遵循 “初始化→解析目标→创建 ICMP 句柄→循环发送请求→处理响应→清理资源” 的逻辑,核心依赖 Windows 的 ICMP API(IcmpCreateFile、IcmpSendEcho等)和 Winsock 库,实现了与系统 ping 命令类似的功能:向目标主机发送 ICMP 请求并显示响应结果。
各个函数说明:
- WSAStartup(MAKEWORD(2, 2), &wsaData)初始化 Windows 套接字库
- IcmpCreateFile()创建 ICMP 操作句柄,用于后续发送 ICMP 请求。
- IcmpSendEcho()发送 ICMP 回显请求(即 ping 包)。
- IcmpCloseHandle(hIcmpFile)关闭 ICMP 句柄,释放资源。
- LocalFree(ReplyBuffer)释放响应缓冲区的内存。
关键的头文件:
#include <iphlpapi.h>
#include <icmpapi.h>
关键的库:
#pragma comment(lib, "iphlpapi.lib")
#pragma comment(lib, "ws2_32.lib")
过程
代码如下。
pro文件:
QT -= gui
CONFIG += c++11 console
CONFIG -= app_bundle
INCLUDEPATH += C:/Program Files (x86)/Windows Kits/8.1/Include/um
# You can make your code fail to compile if it uses deprecated APIs.
# In order to do so, uncomment the following line.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
SOURCES += \
main.cpp
# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target
main.cpp:
#include <iostream>
#include <winsock2.h>
#include <iphlpapi.h>
#include <icmpapi.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#pragma comment(lib, "iphlpapi.lib")
#pragma comment(lib, "ws2_32.lib")
// ICMP响应缓冲区大小
#define REPLY_BUFSIZE 1024
// 发送ping请求
void Ping(const char* host, int count = 4, int timeout = 1000)
{
HANDLE hIcmpFile;
unsigned long ipaddr = INADDR_NONE;
DWORD dwRetVal = 0;
char SendData[32] = "Data Buffer";
LPVOID ReplyBuffer = (VOID*)LocalAlloc(LPTR, REPLY_BUFSIZE);
DWORD ReplySize = REPLY_BUFSIZE;
// 解析主机名或IP地址
ipaddr = inet_addr(host);
// 创建ICMP句柄
hIcmpFile = IcmpCreateFile();
if (hIcmpFile == INVALID_HANDLE_VALUE)
{
std::cerr << "IcmpCreateFile 失败: " << GetLastError() << std::endl;
return;
}
std::cout << "正在 Ping " << host << " [" << inet_ntoa(*(in_addr*)&ipaddr) << "] 具有 32 字节的数据:" << std::endl;
// 发送多个ping请求
for (int i = 0; i < count; i++)
{
// 发送ICMP echo请求
dwRetVal = IcmpSendEcho(hIcmpFile, ipaddr, SendData, sizeof(SendData),
NULL, ReplyBuffer, ReplySize, timeout);
if (dwRetVal != 0)
{
PICMP_ECHO_REPLY pEchoReply = (PICMP_ECHO_REPLY)ReplyBuffer;
struct in_addr ReplyAddr;
ReplyAddr.S_un.S_addr = pEchoReply->Address;
// 显示响应信息
if (pEchoReply->Status == IP_SUCCESS)
{
std::cout << pEchoReply->DataSize << " 字节,来自 "
<< inet_ntoa(ReplyAddr) << ": "
<< "时间=" << pEchoReply->RoundTripTime << "ms" << std::endl;
}
else
{
std::cout << "请求超时。" << std::endl;
}
}
else
{
std::cerr << "IcmpSendEcho 失败: " << GetLastError() << std::endl;
break;
}
// 等待1秒再发送下一个请求
Sleep(1000);
}
// 清理资源
IcmpCloseHandle(hIcmpFile);
LocalFree(ReplyBuffer);
}
int main(int argc, char* argv[])
{
WSADATA wsaData;
int iResult;
// 初始化Winsock
iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
if (iResult != 0)
{
std::cerr << "WSAStartup 失败: " << iResult << std::endl;
return 1;
}
// 默认ping目标
const char* target = "8.8.8.8";
// 发送ping请求
Ping(target, 4, 1000);
// 清理Winsock
WSACleanup();
return 0;
}
程序运行截图如下:

更多推荐

所有评论(0)