使用套接字实现ICMP协议
来源:互联网 发布:js给json对象添加属性 编辑:程序博客网 时间:2024/05/29 10:55
//ip协议 结构头部定义
#pragma once#include "stdafx.h"#ifdef USING_IP_HEADERtypedef struct _ipheader{ #if LITTLE_ENDIAN unsigned char ihl:4; //首部长度 unsigned char version:4; //版本 #else unsigned char version:4 ;//版本 unsigned char ihl:4 ; //首部长度 #endif unsigned char tos; //服务类型 unsigned short tot_len; //总长度 unsigned short id; //标志 unsigned short frag_off; //分片偏移 unsigned char ttl; //生存时间 unsigned char protocol; //协议 unsigned short chk_sum; //检验和 //struct in_addr src_addr; //源IP地址 /*unsigned int srcaddr;/*减少导入库,需要在引用的地方 转换为in_addr*/ //struct in_addr dest_addr; //目的IP地址 /*unsigned int destaddr;/*减少导入库,需要在引用的地方 转换为in_addr*/ unsigned long src_addr; unsigned long dest_addr;}IP_HEADER,*PIP_HEADER;#endif //USING_IP_HEADER#ifdef USING_IP_ICMP_HEADER//ICMP 结构头typedef struct _icmp_header{/*类型*/unsigned char icmp_type;/*代码*/unsigned char icmp_code;/*校检和*/unsigned short icmp_checksum;/*标识符,一般以进程号作为标识*/unsigned short icmp_id;/*序列号*/unsigned short icmp_seq; /*时间戳*/unsigned long icmp_timestamp;}ICMP_HEADER,*PICMP_HEADER;
//ICMP 协议函数定义 头文件
//解析ICMP协议包数据 BOOL __stdcall Nw_ParseIcmp4PacketData( /*ICMP协议数据包*/ __in void* pIcmpData, /*pIcmpData的长度,长度必须匹配pIcmpData,否则导致内存访问越界*/ __in size_t IcmpDataLen, /*ip结构*/ /*#ifdef USING_IP_HEADER __out_opt IP_HEADER* pIpHdr,#else*/ __out_opt void** ppIpHdr,//#endif /*icmp结构*//*#ifdef USING_IP_ICMP_HEADER __out_opt ICMP_HEADER* pIcmpHdr,#else*/ __out_opt void** ppIcmphdr,//#endif /*包含的数据*/ __out_opt void** ppData, /*pData的数据长度*/ __out_opt size_t* pDataReturnLen );//目标地址是否可使用ICMP协议到达并返回,是ping程序的简易版 //一个调用作为一个调用例程,可结合多线程使用 作为网络扫描,基于主机地址而非端口 //也可用用于使用ICMP发送数据 //可用这个函数获取本机 宽带通信的IP(用于外网通信的,不是局域网),在网络不好的情况下无法得到正确的数据,根据返回值判断,最好是多调用几次,直到返回值为0表示调用正确 /*成功返回0*/ int __stdcall Nw_Icmp4InvokeRoutine( /*目标地址*/ __in char* phostname, /*指示icmp请求允许的等待时间,为-1表示无限时间等待,函数不返回,除非目标回显请求*/ __in int itimeout, /*指定发送到icmp类型,如为0 表示以请求回显的方式 同ping一样*/ __in unsigned short icmptype, /*为TRUE,用户必须在psendbuffer构造ICMP结构头,为FALSE,则由函数自己构造,标识符为线程ID*/ __in BOOL bBuildIcmpPacket, /*通过icmp携带的数据,可为NULL;是否构造ICMP结构头,根据bBuildIcmpPacket参数指定。携带数据的长度加上ip协议结构头的和不能超过0xFFFF,超出部分被截断*/ __in void* psendbuffer, /*psendbuffer的字节长度*/ __in size_t bufferlen , /*接受的数据缓存区,可为NULL;数据结构: ip协议结构头+icmp结构+数据,用户亲自处理*/ __out_opt void* precvbuffer, /*指定precvbuffer的字节长度*/ __in size_t recvbufferlen, /*precvbuffer实际接受的字节长度*/ __out_opt size_t* preturnrecvbufferlen );
//源文件,代码实现
//解析ICMP协议包数据BOOL __stdcall Nw_ParseIcmp4PacketData(/*ICMP协议数据包*/__in void* pIcmpData, /*pIcmpData的长度,长度必须匹配pIcmpData,否则导致内存访问越界*/ __in size_t IcmpDataLen, /*ip结构*/ __out_opt void** ppIpHdr, /*icmp结构*/ __out_opt void** ppIcmpHdr, /*包含的数据*/ __out_opt void** ppData, /*pData的数据长度*/ __out_opt size_t* pDataReturnLen ){if(! pIcmpData || !IcmpDataLen) return FALSE;DWORD dwroffset=sizeof(IP_HEADER);if(dwroffset>IcmpDataLen) return FALSE;if(ppIpHdr) *ppIpHdr=(PIP_HEADER)pIcmpData;dwroffset+=sizeof(ICMP_HEADER);if(dwroffset>IcmpDataLen) return FALSE;if(ppIcmpHdr)*ppIcmpHdr=(PICMP_HEADER)((DWORD)pIcmpData+sizeof(IP_HEADER));if(ppData) *ppData=(void*)((DWORD)pIcmpData+sizeof(IP_HEADER)+sizeof(ICMP_HEADER));if(pDataReturnLen) *pDataReturnLen=IcmpDataLen-dwroffset;return TRUE;}int __stdcall Nw_Icmp4InvokeRoutine( /*目标地址*/ __in char* phostname, /*指示icmp请求允许的等待时间,为-1表示无限时间等待,函数不返回,除非目标回显请求*/ __in int itimeout, /*指定发送到icmp类型,如为0 表示以请求回显的方式 同ping一样*/ __in unsigned short icmptype, /*为TRUE,用户必须在psendbuffer构造ICMP结构头,为FALSE,则由函数自己构造,标识符为线程ID*/ __in BOOL bBuildIcmpPacket, /*通过icmp携带的数据,可为NULL;是否构造ICMP结构头,根据bBuildIcmpPacket参数指定。携带数据的长度加上ip协议结构头的和不能超过0xFFFF,超出部分被截断*/ __in void* psendbuffer, /*psendbuffer的字节长度*/ __in size_t bufferlen , /*接受的数据缓存区,可为NULL;数据结构: ip协议结构头+icmp结构+数据,用户亲自处理*/ __out_opt void* precvbuffer, /*指定precvbuffer的字节长度*/ __in size_t recvbufferlen, /*precvbuffer实际接受的字节长度*/ __out_opt size_t* preturnrecvbufferlen ) { int ierr=0; struct hostent* phost=gethostbyname(phostname); struct sockaddr_in dest_addr,src_addr; SOCKET sk_Icmp; PICMP_HEADER picmppacket=NULL;//to delete if it could int src_addr_len=sizeof(src_addr); if(!phost) { unsigned long _laddr =inet_addr(phostname); if(_laddr==INADDR_NONE) return WSAGetLastError(); dest_addr.sin_addr.s_addr=_laddr; dest_addr.sin_family=AF_INET; }else{ CopyMemory(&dest_addr.sin_addr.s_addr,phost->h_addr,phost->h_length); dest_addr.sin_family=phost->h_addrtype; } /*创建套接字*/ sk_Icmp=WSASocket(AF_INET,SOCK_RAW,IPPROTO_ICMP,NULL,0,WSA_FLAG_OVERLAPPED); if(sk_Icmp==INVALID_SOCKET) return INVALID_SOCKET; //设置超时 int ito= setsockopt(sk_Icmp,SOL_SOCKET,SO_RCVTIMEO,(char*)&itimeout,sizeof(int)); if(ito==SOCKET_ERROR) { closesocket(sk_Icmp); return SOCKET_ERROR; } ito= setsockopt(sk_Icmp,SOL_SOCKET,SO_SNDTIMEO,(char*)&itimeout,sizeof(int)); if(ito==SOCKET_ERROR) { closesocket(sk_Icmp); return SOCKET_ERROR; } //发送 if(psendbuffer==NULL/*用户指定发送包为NULL*/){ picmppacket = (PICMP_HEADER)HeapAlloc(GetProcessHeap(),8, sizeof(ICMP_HEADER)); if(picmppacket==NULL){ closesocket(sk_Icmp); return -2;//内存原因 } picmppacket->icmp_checksum=0; picmppacket->icmp_code=0; picmppacket->icmp_id=GetCurrentThreadId(); picmppacket->icmp_seq=1; picmppacket->icmp_timestamp=GetTickCount(); picmppacket->icmp_type=8; picmppacket->icmp_checksum=Icmp_CheckSum((USHORT*)picmppacket,sizeof(ICMP_HEADER)); ierr=sendto(sk_Icmp,(char*)picmppacket,sizeof(ICMP_HEADER),0,(struct sockaddr*)&dest_addr,sizeof(dest_addr)); if(ierr==SOCKET_ERROR){ ierr=WSAGetLastError(); closesocket(sk_Icmp); HeapFree(GetProcessHeap(),0,picmppacket); return ierr; } }/*NULL*/ else{ if(bBuildIcmpPacket/*用户亲自处理ICMP包*/){ ierr=sendto(sk_Icmp,(char*)psendbuffer,bufferlen/*大于65535会产生 IP碎片,这里不处理*/,0,(struct sockaddr*)&dest_addr,sizeof(dest_addr)); if(ierr==SOCKET_ERROR){ ierr=WSAGetLastError(); closesocket(sk_Icmp); return ierr; } }else/*函数构造ICMP结构*/{ size_t l=bufferlen+sizeof(ICMP_HEADER); picmppacket = (PICMP_HEADER) HeapAlloc(GetProcessHeap(),8,l); if(!picmppacket) { closesocket(sk_Icmp); return -2; } picmppacket->icmp_checksum=0; picmppacket->icmp_code=0; picmppacket->icmp_id=GetCurrentThreadId(); picmppacket->icmp_seq=1; picmppacket->icmp_timestamp=GetTickCount(); picmppacket->icmp_type=8; CopyMemory((LPVOID)((DWORD)picmppacket+sizeof(ICMP_HEADER)),psendbuffer,bufferlen); picmppacket->icmp_checksum=Icmp_CheckSum((USHORT*)picmppacket,l); ierr=sendto(sk_Icmp,(char*)picmppacket,l,0,(struct sockaddr*)&dest_addr,sizeof(dest_addr)); if(ierr==SOCKET_ERROR){ ierr=WSAGetLastError(); closesocket(sk_Icmp); HeapFree(GetProcessHeap(),0,picmppacket); return ierr; } } } //接收数据,注意,如果要做类似于ping的程序需要接收数据以判断目标是否可到达 if(precvbuffer){ ierr=recvfrom(sk_Icmp,(char*)precvbuffer,recvbufferlen,0,(struct sockaddr*)&src_addr,&src_addr_len); if(ierr==SOCKET_ERROR){ closesocket(sk_Icmp); if(picmppacket) HeapFree(GetProcessHeap(),0,picmppacket); return ierr; } if(preturnrecvbufferlen) *preturnrecvbufferlen=ierr; } closesocket(sk_Icmp); if(picmppacket) HeapFree(GetProcessHeap(),0,picmppacket); return 0; }
- 使用套接字实现ICMP协议
- ICMP,原始套接字,ping实现
- ICMP协议之ping实现
- ICMP协议之tracert实现
- ICMP协议之ping实现
- ICMP协议之ping实现
- ICMP协议之ping实现
- ICMP协议之ping实现
- ICMP协议之ping实现
- 理解和使用ICMP协议
- linux原始套接字-发送ICMP报文
- 使用socket套接字通过http协议实现文档下载功能
- 利用Visual C#实现ICMP网络协议
- 利用Visual C#实现ICMP网络协议
- ICMP协议之time/mask实现
- ICMP协议的分析与实现
- C语言实现ICMP协议Ping命令
- 利用Visual C#实现ICMP网络协议
- 字节和数字,字符串转换
- 关于handler的部分注意点
- android分辨率单位等比值
- POI3.8读取word文档的表格数据!
- linux环境下android常用工具和技巧
- 使用套接字实现ICMP协议
- 【Android】 在Andorid中解析Json数据示例
- Java高新技术学习日记
- 多表关联的update语句
- MFC 程序入口和执行流程
- 使用Plproxy设计PostgreSQL分布式数据库01
- 使用Plproxy设计PostgreSQL分布式数据库02
- 对.NET的认识
- linux启动流程导读(arm为例)<二>