博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
libuv实现ping包发送和接收
阅读量:2135 次
发布时间:2019-04-30

本文共 6055 字,大约阅读时间需要 20 分钟。

目录

简介

使用socket函数创建套接字,并与uv_udp_t关联,可以实现对icmp包的发送和接收,实现类似ping命令的功能。

uv_loop_t* loop = uv_default_loop();	uv_udp_t* pUdp = new uv_udp_t;	int sock = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);    uv_udp_init(loop, pUdp);    uv_udp_open(pUdp, sock);

源码

学习icmp协议和libuv关于udp,定时器的使用。

创建了ICMP的套接字,并与uv_udp_t关联

创建一个定时器,并与uv_udp_t关联,用于处理响应超时
构造并发送一个icmp包req
收到icmp包rsp,打印响应内容,关闭定时器,关闭uv_udp_t句柄
超时未收到rsp,打印超时,关闭uv_udp_t句柄,关闭定时器

需要注意的是:由于套接字协议是IPPROTO_ICMP,收到的包是包含IP头的。

///*在入口函数中包含 _CrtDumpMemoryLeaks();  即可检测到内存泄露*/#define CRTDBG_MAP_ALLOC  #include 
#include
////#include
//for kbhit()#include "stdafx.h"#include "uv.h"#pragma pack(1)#define ICMP_ECHOREPLY 0#define ICMP_ECHOREQ 8#define REQ_DATASIZE 32 // Echo 请求数据的大小// IP Header -- RFC 791typedef struct tagIPHDR{
u_char VIHL; // Version and IHL u_char TOS; // Type Of Service short TotLen; // Total Length short ID; // Identification short FlagOff; // Flags and Fragment Offset u_char TTL; // Time To Live u_char Protocol; // Protocol u_short Checksum; // Checksum struct in_addr iaSrc; // Internet Address - Source struct in_addr iaDst; // Internet Address - Destination}IPHDR, *PIPHDR;// ICMP Header - RFC 792typedef struct tagICMPHDR{
u_char Type; // Type u_char Code; // Code u_short Checksum; // Checksum u_short ID; // Identification u_short Seq; // Sequence char Data; // Data}ICMPHDR, *PICMPHDR;// ICMP Echo Requesttypedef struct tagECHOREQUEST{
ICMPHDR icmpHdr; uint64_t dwTime; char cData[REQ_DATASIZE];}ECHOREQUEST, *PECHOREQUEST;// ICMP Echo Replytypedef struct tagECHOREPLY{
IPHDR ipHdr; ECHOREQUEST echoRequest; char cFiller[256];}ECHOREPLY, *PECHOREPLY;#pragma pack()//目的ipstruct sockaddr_in g_saDest;//icmp校验u_short in_cksum(u_short *addr, int len){
register int nleft = len; register u_short *w = addr; register u_short answer; register int sum = 0; while( nleft > 1 ) {
sum += *w++; nleft -= 2; } if( nleft == 1 ) {
u_short u = 0; *(u_char *)(&u) = *(u_char *)w ; sum += u; } sum = (sum >> 16) + (sum & 0xffff); sum += (sum >> 16); answer = ~sum; return (answer);}void CreateIcmp(char* buff, ULONG* size){
ECHOREQUEST echoReq; static int nId = 1; static int nSeq = 1; int nRet; //构造请求 echoReq.icmpHdr.Type = ICMP_ECHOREQ; echoReq.icmpHdr.Code = 0; echoReq.icmpHdr.Checksum = 0; echoReq.icmpHdr.ID = nId++; echoReq.icmpHdr.Seq = nSeq++; for (nRet = 0; nRet < REQ_DATASIZE; nRet++) echoReq.cData[nRet] = ' '+nRet; //保存发送时间 echoReq.dwTime = uv_hrtime(); echoReq.icmpHdr.Checksum = in_cksum((u_short *)&echoReq, sizeof(ECHOREQUEST)); memcpy(buff, &echoReq, sizeof(ECHOREQUEST)); *size = sizeof(ECHOREQUEST);}static void slab_alloc(uv_handle_t* handle, size_t suggested_size, uv_buf_t* buf) {
/* up to 16 datagrams at once */ static char slab[16 * 64 * 1024]; buf->base = slab; buf->len = sizeof(slab);}static void on_recv(uv_udp_t* handle, ssize_t nread, const uv_buf_t* rcvbuf, const struct sockaddr* addr, unsigned flags) {
ECHOREPLY* r = (ECHOREPLY*)rcvbuf->base; struct sockaddr_in* ad = (struct sockaddr_in*)addr; uv_timer_t* pTimer = (uv_timer_t*)handle->data; char ip[64] = {
0}; uv_ip4_name(ad, ip, sizeof(ip)); if (nread == 0) {
/* Everything OK, but nothing read. */ return; } if (memcmp(&g_saDest.sin_addr, &ad->sin_addr, sizeof(ad->sin_addr)) != 0) {
return; } uint64_t now = uv_hrtime(); uint64_t time = now - (r->echoRequest.dwTime); double dtime = time / 1000000.0 ; printf("%d bytes form %s: icmp_seq=%d ttl=%d time=%.3f ms\n", sizeof(ECHOREQUEST) - sizeof(ICMPHDR), ip, (r->echoRequest.icmpHdr.Seq), r->ipHdr.TTL, dtime); //停止定时器,关闭定时器句柄 if(pTimer) {
uv_timer_stop(pTimer); uv_close((uv_handle_t*)pTimer, NULL); } //停止udp的接收,关闭udp句柄 uv_udp_recv_stop(handle); uv_close((uv_handle_t*)handle, NULL);}static void on_send(uv_udp_send_t* req, int status) {
uv_buf_t *buf = (uv_buf_t *)req->data; //发送完毕释放内存 delete [] buf->base; delete buf; delete req;}void timercb(uv_timer_t* req){
uv_udp_t* handle = (uv_udp_t*)req->data; //停止udp的接收,关闭udp句柄 uv_udp_recv_stop(handle); uv_close((uv_handle_t*)handle, NULL); printf("timeout\n"); //停止定时器,关闭定时器句柄 uv_timer_stop(req); uv_close((uv_handle_t*)req, NULL);}int _tmain(int argc, _TCHAR* argv[]){
//libuv环境初始化,内存分配 uv_loop_t* loop = uv_default_loop(); uv_udp_t* pUdp = new uv_udp_t; uv_timer_t* pTimer = new uv_timer_t; uv_udp_send_t *reqSend = new uv_udp_send_t; //设置ping的目的地址 const char* strDstIp = "192.168.10.1"; uv_ip4_addr(strDstIp, 0, &g_saDest); //创建发送数据的buf uv_buf_t *buf = new uv_buf_t; buf->base = new char[sizeof(ECHOREQUEST)] ; buf->len = sizeof(ECHOREQUEST); //创建套接字,设置关联 int sock = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP); uv_udp_init(loop, pUdp); uv_udp_open(pUdp, sock); //初始化定时器,做简单的数据关联,以便后续管理 uv_timer_init(loop, pTimer); pTimer->data = pUdp; pUdp->data = pTimer; reqSend->data = buf; //构造icmp请求报文 CreateIcmp(buf->base, &buf->len); printf("ping %s:\n", strDstIp); //发送icmp报文,启动udp接收,启动1s超时的定时器 uv_udp_send(reqSend, pUdp, buf, 1, (const sockaddr*)&g_saDest, on_send); uv_udp_recv_start(pUdp, slab_alloc, on_recv); uv_timer_start(pTimer, timercb, 1000, 0); uv_run(loop, UV_RUN_DEFAULT); //超时或收到响应后退出释放内存 delete pUdp; delete pTimer; //关闭loop printf("uv_loop_close ...\n"); uv_loop_close(loop); _CrtDumpMemoryLeaks(); getchar(); return 0;}

转载地址:http://mmkgf.baihongyu.com/

你可能感兴趣的文章
RNN与机器翻译
查看>>
用 Recursive Neural Networks 得到分析树
查看>>
RNN的高级应用
查看>>
TensorFlow-7-TensorBoard Embedding可视化
查看>>
一个隐马尔科夫模型的应用实例:中文分词
查看>>
轻松看懂机器学习十大常用算法
查看>>
一个框架解决几乎所有机器学习问题
查看>>
特征工程怎么做
查看>>
机器学习算法应用中常用技巧-1
查看>>
机器学习算法应用中常用技巧-2
查看>>
通过一个kaggle实例学习解决机器学习问题
查看>>
决策树的python实现
查看>>
Sklearn 快速入门
查看>>
了解 Sklearn 的数据集
查看>>
用ARIMA模型做需求预测
查看>>
推荐系统
查看>>
详解 TensorBoard-如何调参
查看>>
TensorFlow-11-策略网络
查看>>
浅谈 GBDT
查看>>
如何选择优化器 optimizer
查看>>