Ping命令源代码

合集下载

ping命令的实现过程 -回复

ping命令的实现过程 -回复

ping命令的实现过程-回复"ping命令的实现过程"引言:在计算机网络中,ping命令是一种常见的网络诊断工具,用于测试主机之间的连接性以及网络延迟。

它通过发送ICMP(Internet Control Message Protocol)请求报文,并等待目标主机返回相应。

本文将一步一步地解析ping命令的实现过程,帮助读者深入了解这个常用工具背后的原理。

一、环境准备要实现ping命令,我们首先需要了解网络协议栈和操作系统网络接口的基本知识。

同时,为了简化实现过程,我们将使用一些常见的网络库、工具和编程语言,例如Python或C语言的套接字编程接口。

二、发送ICMP请求报文在实现ping命令时,我们要首先构造ICMP请求报文,并通过网络发送给目标主机。

这个过程可以分为以下几个步骤:1. 创建套接字:使用socket库创建一个原始套接字,以便可以直接访问网络层。

通常,这个套接字的协议类型应为ICMP。

2. 构造IP报文头:创建IP报文头以封装ICMP请求报文。

这需要设置源IP地址、目标IP地址以及其他相关网络参数。

3. 构造ICMP请求报文:创建ICMP请求报文,其中包括报文类型(通常为Echo Request)、标识符(用于匹配请求和响应报文)、序列号(用于区分不同的ping请求)等字段。

还要计算校验和,确保报文的完整性。

4. 发送报文:通过上述套接字将构造的IP报文头和ICMP请求报文发送给目标主机。

三、接收ICMP响应报文发送ICMP请求报文后,我们需要等待目标主机的响应,并分析返回的ICMP响应报文。

下面是实现这一步的具体过程:1. 准备套接字:在接收ICMP响应报文之前,我们首先需要准备接收这些报文的套接字。

同样,我们使用一个原始套接字,并设置其协议类型为ICMP。

2. 接收报文:使用套接字的接收函数,等待目标主机的ICMP响应报文,并将其存储在缓冲区中。

3. 解析报文:解析接收到的ICMP响应报文,提取其中的关键信息,如标识符、序列号以及时间戳等。

网络检测常用命令

网络检测常用命令

一、ping命令详解在日常网络维护工作中,我们使用最多的工具可能就是ping命令了,下面就ping命令的原理与应用进行介绍。

(一)Ping命令原理?????了解ping命令的原理能够更好的利用这个测试工具。

?????1.pingPing的网络在网络传输过程中,可能会发生许多突发事件并导致数据传输失败。

网络层的IP协议是一个无连接的协议,它不会处理网络层传输中的故障,而位于网络层的ICMP协议却恰好弥补了IP的缺限,ICMP消息被封装为IP数据包后传输,收到ICMP消息的主机向数据包中的源主机提供发生在网络层的通信结果或者错误信息反馈。

如果中间节点出现通信中断,中间节点的ICMP协议能够响应ICMP测试消息,在源主机通过观察ICMP 响应消息的源地址,能够快速定位通信在哪一个节点被中断了,也可以通过响应消息判断大致的故障原因。

4、ICMP协议ICMP注意类型和代码为(8,0)的为ping请求包,也称echorequest类型和代码为(0,0)的为ping应答包,也称echoreply其它类型和代码为扩展功能和报错消息。

6、结束语通过本文的介绍,我们可以了解到ping命令使用ICMP协议工作,ICMP的ip协议号为1,通过ICMP 报文类型和代码的介绍,可以了解到更多的ping命令功能和报错消息,并且以后如果需要使用ACL控制各种ping 操作,可以参考这些类型和代码进行准确的控制。

一、ping命令--详细帮助校验与远程计算机或本地计算机的连接。

只有在安装TCP/IP协议之后才能使用该命令。

ping[-t][-a][-ncount][-llength][-f][-ittl][-vtos][-rcount][-scount][[-jcomputer-list]|[-kcomputer参数-t-a-ncount发送由-f-ittl将“-vtos将“-rcount在“。

-scount指定由count指定的转发次数的时间邮票。

ping源代码

ping源代码

1)PING的关键源代码:<基于VC++编译的。

应用于ARM >< xmlnamespace prefix ="o" ns ="urn:schemas-microsoft-com:office:office" /> void CEPing(CString cIPAddr,CListBox * pListBox,CWnd * pWnd){WSAData wsaData;//初始化Socket动态链接库if (WSAStartup(MAKEWORD(1, 1), &wsaData) != 0){return ;}/*将IP地址转换成单字节*/char szDestIPAddr[255];ZeroMemory(szDestIPAddr,255);WideCharToMultiByte(CP_ACP,WC_COMPOSITECHECK,cIPAddr.GetBuffer(cIPAddr.GetLength()),cIPAddr.GetLength(),szDestIPAddr,cIPAddr.GetLength(),NULL,NULL);IPAddr ipAddr;//将目标字符串IP地址转换成IPAddr结构ipAddr = inet_addr(szDestIPAddr);if (ipAddr == INADDR_NONE){AfxMessageBox(TEXT("地址无效"));return ;}// 打开ping服务HANDLE hIP = IcmpCreateFile();if (hIP == INVALID_HANDLE_VALUE){AfxMessageBox(TEXT("不能打开Ping服务"));return ;}// 构造ping数据包char acPingBuffer[64];memset(acPingBuffer, '*', sizeof(acPingBuffer));PICMP_ECHO_REPLY pIpe =(PICMP_ECHO_REPLY)GlobalAlloc( GMEM_FIXED | GMEM_ZEROINIT, sizeof(ICMP_ECHO_REPLY) + sizeof(acPingBuffer));if (pIpe == 0){AfxMessageBox(TEXT("分配ping包缓冲区失败"));return ;}CString m_recv;// 发送ping数据包m_recv = "ping "+cIPAddr+" with 64 Bytes";pListBox->AddString(m_recv);for (int i=0;i<4;i++){//发送ping服务包,等待接收时间为1秒DWORD dwStatus = IcmpSendEcho(hIP,ipAddr,acPingBuffer, sizeof(acPingBuffer), NULL, pIpe,sizeof(ICMP_ECHO_REPLY) + sizeof(acPingBuffer), 1000);//当dwStatus不等于0,代表接收到回应if (dwStatus != 0){m_recv.Format(TEXT("Reply From %d.%d.%d.%d :bytes=%d time=%d TTL"),int(LOBYTE(LOWORD(pIpe->Address))),int(HIBYTE(LOWORD(pIpe->Address))),int(LOBYTE(HIWORD(pIpe->Address))),int(HIBYTE(HIWORD(pIpe->Address))),int(pIpe->DataSize),int(pIpe->RoundTripTime),int(pIpe->Options.Ttl));pListBox->AddString(m_recv);Sleep(500);}else{pListBox->AddString(TEXT("Error obtaining info from ping packet."));}pWnd->UpdateWindow();}//释放已分配的内存GlobalFree(pIpe);//关闭Ping服务IcmpCloseHandle(hIP);//释放Socket资源WSACleanup();}void CPingDlg::OnBtnClear(){// TODO: Add your control notification handler code hereint nCount = m_lstRecv.GetCount();for (int i=0;i < nCount;i++){m_lstRecv.DeleteString(0);}}void CPingDlg::OnBtnPing(){// TODO: Add your control notification handler code hereUpdateData(TRUE);CEPing(m_ipAddr,&m_lstRecv,this);UpdateWindow();}。

ping源码分析

ping源码分析

ping 源码分析10.4.1 ping简介Ping是网络中应用非常广泛的一个软件,它是基于ICMP协议的。

下面首先对ICMP协议做一简单介绍。

ICMP是IP层的一个协议,它是用来探测主机、路由维护、路由选择和流量控制的。

ICMP 报文的最终报宿不是报宿计算机上的一个用户进程,而是那个计算机上的IP层软件。

也就是说,当一个带有错误信息的ICMP报文到达时,IP软件模块就处理本身问题,而不把这个ICMP报文传送给应用程序。

ICMP报文类型有:回送(ECHO)回答(0);报宿不可到达(3);报源断开(4);重定向(改变路由)(5);回送(ECHO)请求(8);数据报超时(11);数据报参数问题(12);时间印迹请求(13);时间印迹回答(14);信息请求(15);信息回答(16);地址掩码请求(17);地址掩码回答(18)。

虽然每种报文都有不同的格式,但它们开始都有下面三段:∙ 一个8位整数报文TYPE(类型)段;∙ 一个8位CODE(代码码)段,提供更多的报文类型信息;∙ 一个16 位CHECKSUM(校验和)段;此外,报告差错的ICMP 报文还包含产生问题数据报的网际报头及前64 位数据。

一个ICMP回送请求与回送回答报文的格式如表10.17 所示。

表10.17 ICMP回送请求与回送回答报文格式类型CODE 校验和[CHECKSUM]标识符序列号《嵌入式Linux应用程序开发详解》——第10章、嵌入式Linux网络编程数据10.4.2 ping源码分析下面的ping.c 源码是在busybox 里实现的源码。

在这个完整的ping.c 代码中有较多选项的部分代码,因此,这里先分析除去选项部分代码的函数实现部分流程,接下来再给出完整的ping代码分析。

这样,读者就可以看到一个完整协议实现应该考虑到的各个部分。

1.Ping 代码主体流程Ping.c主体流程图如下图10.8 所示。

另外,由于ping是IP层的协议,因此在建立socket时需要使用SOCK_RAW 选项。

计算机网络ping源代码

计算机网络ping源代码
unsigned short checksum;
unsigned int sourceip;
unsigned int destip;
}IP_HEADER,*PIP_HEADER;
typedef struct tagIP_OPT_HEADER
{
unsigned char code;
unsigned char len;
{
printf("Pingtool,by blode(blode@\n");
printf("usage:ping[-r]<host ip> [-d][data size]\n");
printf("\t-r:\ttrecord router\n");
printf("\thost ip:\thost ip to ping\n");
if(argc==1)
{
usageinfo(argv[0]);
return -1;
}
BOOL bRecordRout =FALSE;
SOCKET hSocket =INVALID_SOCKET;
SOCKADDR_IN dstSin;
SOCKADDR_IN fromSin;
IP_OPT_HEADER ipOptHeader;
//头文件
#define WIN32_LEAN_AND_MEAN
#include<windows.h>
#include<winsock2.h>
#include<ws2tcpip.h>
#include<stdlib.h>
#include<stdio.h>

python实现ping命令小程序

python实现ping命令小程序

python实现ping命令⼩程序ping的原理是发送⼀个ICMP请求包,然后根据⽬的地址的应答包来判断是否能够和这个主机进⾏通信。

我们使⽤python实现,借助于scapy来进⾏编写程序。

from scapy.all import *import time,struct,random# 编写ping⼀个包的函数。

def ping_one(dst = '36.152.44.95',ttl_no = 64,id_no = 345,seq_no = 5):start_time = time.time()# 将时间转换为⼆进制序列。

time_to_bytes = struct.pack('>d',start_time)# 进⾏发送ICMP包,发送出去⼀个,收回来⼀个。

ping_one_result = sr1(IP(dst = dst,ttl = ttl_no)/ICMP(seq = seq_no,id = id_no)/time_to_bytes, timeout = 1, verbose=False)# print(ping_one_result.show())# 判断收回来的包是不是ICMP的应答包,和序列号是否相同。

try:if ping_one_result.getlayer('ICMP').type == 0 and ping_one_result.getlayer('ICMP').seq == seq_no:# print('进⾏解析包')# 提取IP头部中的源IP地址,也就是我们ping的IP地址。

reply_src_IP = ping_one_result.getlayer('IP').src# 提取序列号。

reply_icmp_seq = ping_one_result.getlayer('ICMP').seq# 提取ttlreply_icmp_ttl = ping_one_result.getlayer('IP').ttl# 数据长度等于数据长度(Raw) + 垫⽚长度(Padding) + 8字节(ICMP头部长度)if ping_one_result.getlayer(Raw) != None:Raw_length = len(ping_one_result.getlayer(Raw).load)else:Raw_length = 0if ping_one_result.getlayer(Padding) != None:Padding_length = len(ping_one_result.getlayer(Padding).load)else:Padding_length = 0# 计算数据长度。

编程模拟ping程序

编程模拟ping程序

一、实验题目编程模拟ping程序,实现Ping程序的基本功能,即接收到一个ping程序数据包后给出回应。

二、原理概述ping命令是用来查看网络上另一个主机系统的网络连接是否正常的一个工具。

ping命令的工作原理是:向网络上的另一个主机系统发送ICMP报文,如果指定系统得到了报文,它将把报文一模一样地传回给发送者,这有点象潜水艇声纳系统中使用的发声装置。

想要了解ping命令的原理必须了解ICMP协议、ICMP报文格式和IP报文格式。

(1)ICMP报文结构ICMP 报文结构: ICMP 报文前四个字节为报文头部分,第一个字节为报文类型,第二个字节未用, 第三四个字节为报文的校验和。

从第四个字节开始为长度可变的数据段,该段的内容取决于ICMP 的类型,本文所要使用的请求报文和请求应答报文的数据段中前四个字节是报文的标识符和顺序号。

对于整个ICMP 报文来说其长度最长不能超过64K字节。

ICMP 报文结构如图1 所示。

0 7 8 15 16 31 32 47 48 63 64(2)IP报文结构ICMP 报文和其它位于IP 层的报文一样是作为IP 报文的数据段加上IP 报文头组成IP 数据报发出,其中IP 报文头长度一般为20 个字节。

如图2所示。

三、设计方案根据实验题目查找相关资料,熟悉及理解ping的工作原理,从而进一步设计ping程序的功能图和系统流程图。

准备工作做好后就可上机调试,验证其可行性并查找漏洞,完善ping程序。

(1) ping程序的设计包含了4部分:IP、ICMP的头结构,主函数模块,CMP数据包校验和的计算和使用说明模块。

(2)系统流程图首先在主函数里定义变量同时进行初始化,然后检查参数的正确性,如果参数不正确或者没有输入参数,则显示用户帮助信息(Usage ),并结束程序;如果参数正确,则对指定目的地执行Ping命令,如果Ping通,则显示Ping结果并释放占用资源,如果没有Ping通,则报告错误信息,并释放占用资源。

ping命令C语言

ping命令C语言
//返回应答时间
return(echoReply.echoRequest.dwTime);
}
// 等待回应答复,使用select机制
int WaitForEchoReply(SOCKET s)
{
struct timeval timeout;
fd_set readfds;
nRet = sendto(s, // 建立起的套接字
(LPSTR)&echoReq, // 发送的缓冲区内容
sizeof(ECHOREQUEST),
0, // 标志位
(struct sockaddr*)lpstToAddr, // 发送的目标地址
#include <stdio.h>
#include <stdlib.h>
#include <winsock.h>
#pragma comment (lib, "ws2_32.lib")
#define ICMP_ECHOREPLY 0 // ICMP回复应答
#define ICMP_ECHOREQ 8 // ICMP回应请求
{
printf("closesocket() error:%d\n",WSAGetLastError());
}
}
void main(int argc, char **argv)
{
WSADATA wsd;
int nRet;
// 检测输入的参数
if (argc != 2)
char cData[REQ_DATASIZE];
}ECHOREQUEST, *PECHOREQUEST;
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

ping的原理就是首先建立通道,然后发送包,对方接受后返回信息,这个包至少包括以下内容,发送的时候,包的内容包括对方的ip地址和自己的地址,还有序列数,回送的时候包括双方地址,还有时间等,主要是接受方在都是在操作系统内核里做好的,时刻在监听,提供一段c程序的代码,希望对大家有用。

#include#include#include#include#include#include#include#include#include#include#include#include#define PACKET_SIZE 4096#define MAX_WAIT_TIME 5#define MAX_NO_PACKETS 3char sendpacket[PACKET_SIZE];char recvpacket[PACKET_SIZE];int sockfd,datalen=56;int nsend=0,nreceived=0;struct sockaddr_in dest_addr;pid_t pid;struct sockaddr_in from;struct timeval tvrecv;void statistics(int signo);unsigned short cal_chksum(unsigned short *addr,int len);int pack(int pack_no);void send_packet(void);void recv_packet(void);int unpack(char *buf,int len);void tv_sub(struct timeval *out,struct timeval *in);void statistics(int signo){ printf("\n--------------------PING statistics-------------------\n");printf("%d packets transmitted, %d received , %%%d lost\n",nsend,nreceived, (nsend-nreceived)/nsend*100);close(sockfd);exit(1);}/*校验和算法*/unsigned short cal_chksum(unsigned short *addr,int len){ int nleft=len;int sum=0;unsigned short *w=addr;unsigned short answer=0;/*把ICMP报头二进制数据以2字节为单位累加起来*/while(nleft>1){ sum+=*w++;nleft-=2;}/*若ICMP报头为奇数个字节,会剩下最后一字节。

把最后一个字节视为一个2字节数据的高字节,这个2字节数据的低字节为0,继续累加*/if( nleft==1){ *(unsigned char *)(&answer)=*(unsigned char *)w;sum+=answer;}sum=(sum>>16)+(sum&0xffff);sum+=(sum>>16);answer=~sum;return answer;}/*设置ICMP报头*/int pack(int pack_no){ int i,packsize;struct icmp *icmp;struct timeval *tval;icmp=(struct icmp*)sendpacket;icmp->icmp_type=ICMP_ECHO;icmp->icmp_code=0;icmp->icmp_cksum=0;icmp->icmp_seq=pack_no;icmp->icmp_id=pid;packsize=8+datalen;tval= (struct timeval *)icmp->icmp_data;gettimeofday(tval,NULL); /*记录发送时间*/icmp->icmp_cksum=cal_chksum( (unsigned short *)icmp,packsize); /*校验算法*/ return packsize;}/*发送三个ICMP报文*/void send_packet(){ int packetsize;while( nsend{ nsend++;packetsize=pack(nsend); /*设置ICMP报头*/if( sendto(sockfd,sendpacket,packetsize,0,(struct sockaddr *)&dest_addr,sizeof(dest_addr) )<0 ){ perror("sendto error");continue;}sleep(1); /*每隔一秒发送一个ICMP报文*/}}/*接收所有ICMP报文*/void recv_packet(){ int n,fromlen;extern int errno;signal(SIGALRM,statistics);fromlen=sizeof(from);while( nreceived{ alarm(MAX_WAIT_TIME);if( (n=recvfrom(sockfd,recvpacket,sizeof(recvpacket),0,(struct sockaddr *)&from,&fromlen)) <0){ if(errno==EINTR)continue;perror("recvfrom error");continue;}gettimeofday(&tvrecv,NULL); /*记录接收时间*/if(unpack(recvpacket,n)==-1)continue;nreceived++;}}/*剥去ICMP报头*/int unpack(char *buf,int len){ int i,iphdrlen;struct ip *ip;struct icmp *icmp;struct timeval *tvsend;double rtt;ip=(struct ip *)buf;iphdrlen=ip->ip_hl<<2; /*求ip报头长度,即ip报头的长度标志乘4*/ icmp=(struct icmp *)(buf+iphdrlen); /*越过ip报头,指向ICMP报头*/ len-=iphdrlen; /*ICMP报头及ICMP数据报的总长度*/if( len<8) /*小于ICMP报头长度则不合理*/{ printf("ICMP packets\'s length is less than 8\n");return -1;}/*确保所接收的是我所发的的ICMP的回应*/if( (icmp->icmp_type==ICMP_ECHOREPLY) && (icmp->icmp_id==pid) ) { tvsend=(struct timeval *)icmp->icmp_data;tv_sub(&tvrecv,tvsend); /*接收和发送的时间差*/rtt=_sec*1000+_usec/1000; /*以毫秒为单位计算rtt*//*显示相关信息*/printf("%d byte from %s: icmp_seq=%u ttl=%d rtt=%.3f ms\n",len,inet_ntoa(from.sin_addr),icmp->icmp_seq,ip->ip_ttl,rtt);}else return -1;}main(int argc,char *argv[]){ struct hostent *host;struct protoent *protocol;unsigned long inaddr=0l;int waittime=MAX_WAIT_TIME;int size=50*1024;if(argc<2){ printf("usage:%s hostname/IP address\n",argv[0]);exit(1);}if( (protocol=getprotobyname("icmp") )==NULL){ perror("getprotobyname");exit(1);}/*生成使用ICMP的原始套接字,这种套接字只有root才能生成*/if( (sockfd=socket(AF_INET,SOCK_RAW,protocol->p_proto) )<0){ perror("socket error");exit(1);}/* 回收root权限,设置当前用户权限*/setuid(getuid());/*扩大套接字接收缓冲区到50K这样做主要为了减小接收缓冲区溢出的的可能性,若无意中ping一个广播地址或多播地址,将会引来大量应答*/ setsockopt(sockfd,SOL_SOCKET,SO_RCVBUF,&size,sizeof(size) ); bzero(&dest_addr,sizeof(dest_addr));dest_addr.sin_family=AF_INET;/*判断是主机名还是ip地址*/if( inaddr=inet_addr(argv[1])==INADDR_NONE){ if((host=gethostbyname(argv[1]) )==NULL) /*是主机名*/{ perror("gethostbyname error");exit(1);}memcpy( (char *)&dest_addr.sin_addr,host->h_addr,host->h_length); }else /*是ip地址*/memcpy( (char *)&dest_addr,(char *)&inaddr,host->h_length);/*获取main的进程id,用于设置ICMP的标志符*/pid=getpid();printf("PING %s(%s): %d bytes data in ICMP packets.\n",argv[1], inet_ntoa(dest_addr.sin_addr),datalen);send_packet(); /*发送所有ICMP报文*/recv_packet(); /*接收所有ICMP报文*/statistics(SIGALRM); /*进行统计*/return 0;}/*两个timeval结构相减*/void tv_sub(struct timeval *out,struct timeval *in){ if( (out->tv_usec-=in->tv_usec)<0){ --out->tv_sec;out->tv_usec+=1000000;}out->tv_sec-=in->tv_sec;}。

相关文档
最新文档