原始套接口的ping命令编程
来源:互联网 发布:河北网络干部学院官网 编辑:程序博客网 时间:2024/05/16 10:49
原始套接口(SOCK_RAW)允许对较低层协议(如IP或ICMP)进行直接访问,常用于检验新的网络协议实现,也可用于测试新配置或安装的网络设备。创建一个原始套接口时,一般格式如下:
SOCKET sockid=socket(AF_INET,SOCK_RAW,IPPROTO_ICMP);//ICMP协议
SOCKET sockid=socket(AF_INET,SOCK_RAW,IPPROTO_IP);//IP协议
SOCKET sockid=socket(AF_INET,SOCK_RAW,IPPROTO_IP);//IP协议
以下是利用ICMP协议实现的PING命令:
#include <WINSOCK2.H> #pragma comment(lib,"ws2_32") #include <stdio.h> //--------------------①头部格式-------------- /************************************************************************/ /* IP头部 */ /************************************************************************/ typedef struct IP_Header//20B的IP固定头部 { UCHAR ipVer; //1B 4b版本号+4b头长度 UCHAR ipTOS; //1B 服务类型 USHORT ipLength; //2B 总长度(IP数据报的长度) USHORT ipID; //2B 标识(唯一标识发送的每一个数据报) USHORT ipFlags; //2B 3b标志+13b分段偏移 UCHAR ipTTL; //1B 生存时间TTL UCHAR ipProtocol; //1B 上层协议标识(TCP、UDP、ICMP) USHORT ipChecksum; //2B 头部效验和 ULONG ipSource; //4B 源IP地址 ULONG ipDestination;//4B 目的IP地址 }IPHDR,*PIPHDR; /************************************************************************/ /* ICMP头部 */ /************************************************************************/ typedef struct ICMP_Header//8B的ICMP头部 { UCHAR icmp_type; //1B 类型 UCHAR icmp_code; //1B 代码 USHORT icmp_checksum;//2B 效验和 USHORT icmp_id; //2B 标识符(通常设置为进程ID) USHORT icmp_seq; //2B 序号(0~3) }ICMPHDR,*PICMPHDR; //------------------------②函数声明----------------------- USHORT checksum(USHORT *buff,int size); int SetTimeout(SOCKET s,long nTime); //------------------------③main函数----------------------- int main() { WSADATA wsaData; if (WSAStartup(MAKEWORD(2,2),&wsaData)!=0) { printf("WSAStartup Failed,Error=【%d】\n",WSAGetLastError()); return 1; } else printf("加载成功\n"); //----------创建原始套接字---------------- SOCKET sRaw=socket(AF_INET,SOCK_RAW,IPPROTO_ICMP);//创建原始套接字 //----------设置接收超时----------------- struct timeval tv; tv.tv_sec=1; int F=SetTimeout(sRaw,tv.tv_sec); if (F) { printf("setsockopt() Failed,Error=%d\n",WSAGetLastError()); return 1; } else printf("设置接收超时为%d秒\n",tv.tv_sec); //----------绑定------------- struct sockaddr_in Sadd; Sadd.sin_family=AF_INET; Sadd.sin_port=htons(1111); Sadd.sin_addr.s_addr=inet_addr("192.168.31.1"); if (bind(sRaw,(sockaddr*)&Sadd,sizeof(Sadd))==SOCKET_ERROR) { printf("bind() Failed,Error=%d\n",WSAGetLastError()); return 1; } else printf("绑定成功,本地IP地址:【%s】,端口号:【%d】\n",inet_ntoa(Sadd.sin_addr),ntohs(Sadd.sin_port)); //---------目的IP地址(要ping的IP地址)-------------- struct sockaddr_in Dest; Dest.sin_family=AF_INET; Dest.sin_addr.s_addr=inet_addr("192.168.32.1"); //----------创建ICMP包---------------- char buff[sizeof(ICMPHDR)]; //char buff[sizeof(ICMPHDR)+32]; PICMPHDR pIcmp=(ICMPHDR*)buff; // 1)填写ICMP包(公共部分) pIcmp->icmp_type=8; pIcmp->icmp_code=0; pIcmp->icmp_id=(USHORT)GetCurrentProcessId(); //当前进程ID //memset(&buff[sizeof(ICMPHDR)],'E',32); //----------开始准备发送和接收ICMP封包-------------- char recvBuf[200]; struct sockaddr_in R_Dest; int L_R_Dest=sizeof(struct sockaddr_in); while (true) { static USHORT nSeq=0; //seq由0开始 static int nCount=0; //发送4个包 if (nCount++==4) break; //2)继续填写ICMP封包数据(可变部分) pIcmp->icmp_checksum=0; pIcmp->icmp_seq=nSeq++; pIcmp->icmp_checksum=checksum((USHORT*)buff,sizeof(ICMPHDR)); //效验 //pIcmp->icmp_checksum=checksum((USHORT*)buff,sizeof(ICMPHDR)+32); //-------------发送------------- int time_send=GetTickCount(); int nRet=sendto(sRaw,buff,sizeof(ICMPHDR),0,(SOCKADDR*)&Dest,sizeof(Dest)); //int nRet=sendto(sRaw,buff,sizeof(ICMPHDR)+32,0,(SOCKADDR*)&Dest,sizeof(Dest)); if (nRet==SOCKET_ERROR) { printf("sendto() Failed,Error=%d\n",WSAGetLastError()); return 1; } //-------------接收--------------- int RRet=recvfrom(sRaw,recvBuf,sizeof(recvBuf),0,(sockaddr*)&R_Dest,&L_R_Dest); int time_recv=GetTickCount(); if (nRet==SOCKET_ERROR) { if (WSAGetLastError()==WSAETIMEDOUT) { printf("timed out\n"); continue; } printf("recvfrom() Failed,Error=%d\n",WSAGetLastError()); return 1; } //------------解析---------------- PICMPHDR pRecvIcmp=(ICMPHDR*)(recvBuf+sizeof(IPHDR)); if (RRet<(nRet+sizeof(IPHDR))) printf("从%s收到的数据过少\n",inet_ntoa(R_Dest.sin_addr)); if (pRecvIcmp->icmp_type!=0) //不是应答 { printf("这不是我要接收的应答报文,该报文类型为%d\n",pRecvIcmp->icmp_type); return 1; } if (pRecvIcmp->icmp_id!=GetCurrentProcessId()) { printf("这是别人的包\n"); return 1; } printf("%d bytes from %s,icmp_seq=%d,time:%d ms\n",RRet,inet_ntoa(R_Dest.sin_addr),pRecvIcmp->icmp_seq,time_recv-time_send); Sleep(1000); } closesocket(sRaw); WSACleanup(); return 0; } //---------------④效验函数----------------- USHORT checksum(USHORT *buff,int size) { unsigned long cksum=0; while (size>1) { cksum+=*buff++; size-=2; } if (size==1) cksum+=*(UCHAR*)buff; cksum=(cksum>>16)+(cksum&0xffff); cksum+=(cksum>>16); USHORT ans=(USHORT)~cksum; return (ans); } //---------------⑤接收超时函数--------------- int SetTimeout(SOCKET s,long nTime) { int ret=setsockopt(s,SOL_SOCKET,SO_RCVTIMEO,(char*)&nTime,sizeof(nTime)); return ret; }运行程序效果如下:
原文链接:http://blog.csdn.net/akof1314/article/details/5663536
阅读全文
0 0
- 原始套接口的ping命令编程
- 原始套接口的ping命令编程
- 原始套接口的ping命令编程
- 原始套接口的ping命令编程
- 原始套接口编程-Ping总结
- 网络编程之原始套接口
- 原始套接口基础知识
- 深入分析原始套接口
- 原始套接口(RAW SOCKET)
- linux网络原始套接口
- UNP Chapter 25 - 原始套接口(icmp的实现)
- 用原始套接字编程实现linux中的 ping 命令 ************************
- Linux原始套接字----ping命令的实现
- UNPv1第二十五章:原始套接口
- 使用原始套接字编程实现简单的ping程序
- 基本的tcp套接口编程
- UNIX的套接口(Socket)编程
- 套接口编程基础
- MAMP 数据库文件的位置
- 解决微信授权回调页面域名只能设置一个的问题 [php]
- 图的两种存储结构及其互相转换
- tiny4412内核自带led驱动分析
- 程序是如何执行的(二)控制结构的执行
- 原始套接口的ping命令编程
- 命令模式
- 摩尔定律还有效吗?
- 每个开发人员都应该知道的 10 个 Linux 命令
- 归一化的学习心得
- 断点续传的mvp
- 一个要重新奋斗的初学码农
- openssl vs2015编译静态库
- 程序是如何执行的(三)函数调用