如何用winsock实现ping(源代码)

原创 2002年04月16日 09:14:00

/*This is a sample routine of ping.It's implemented with winsock1.1
* under windows 2000 professional and has been not tested under other
* platform.Our target is to illustrator the principles,so many details
* may be ignored.(author email:zhangwu2003@163.com)
*/
#include<stdio.h>
#include<windows.h>
#include<process.h>

#define SEND_SIZE 32 
#define PACKET_SIZE 4096
#define ICMP_ECHO 8
#define ICMP_ECHOREPLY 0

struct icmp
{
 unsigned char icmp_type;
 unsigned char icmp_code;
 unsigned short icmp_cksum;
 unsigned short icmp_id;
 unsigned short icmp_seq;
 unsigned long icmp_data; 
};

struct ip
{
    unsigned char ip_hl:4;      
 unsigned char ip_v:4;       
    unsigned char ip_tos;          
    unsigned short ip_len;        
    unsigned short ip_id;         
    unsigned short ip_off;        
    unsigned char ip_ttl;          
    unsigned char ip_p;         
    unsigned short ip_sum;        
    unsigned long ip_src;
    unsigned long ip_dst; 
};

unsigned char sendpacket[PACKET_SIZE];
unsigned char recvpacket[PACKET_SIZE];
struct sockaddr_in dest_addr;
struct sockaddr_in from_addr;
int sockfd;
int pid;

unsigned short cal_chksum(unsigned short *addr,int len);
int pack(int pack_no);
int unpack(unsigned char *buf,int len);
void send_packet(void);
void recv_packet(void);

void main(int argc,char *argv[])
{      
 struct hostent *host;
    struct protoent *protocol;
 WSADATA wsaData;
 int timeout=1000;
 int SEND_COUNT=4;
 int i;
 char *par_host;

 par_host=argv[argc-1];
 switch(argc)
 {
 case 2: break;
 case 3: if(strcmp(argv[1],"-t")==0)
   {
    SEND_COUNT=10000;
    break;
   }
   //fall through
 default:
  printf("usage: %s [-t] Host name or IP address/n",argv[0]);
  exit(1);       
 }

 if(WSAStartup(0x1010,&wsaData)!=0)
 {
  printf("wsastartup error/n");
  exit(1);
 }
    if( (protocol=getprotobyname("icmp") )==NULL)
 {
  printf("getprotobyname error/n");
        exit(1);
    }
    if( (sockfd=socket(AF_INET,SOCK_RAW,protocol->p_proto) )<0)
    {  
  printf("socket error/n");
        exit(1);
    }
   if(setsockopt(sockfd,SOL_SOCKET,SO_RCVTIMEO,(char*)&timeout,sizeof(timeout))<0) 
    fprintf(stderr,"failed to set recv timeout: %d/n",WSAGetLastError());
   if(setsockopt(sockfd,SOL_SOCKET,SO_SNDTIMEO,(char*)&timeout,sizeof(timeout))<0)
    fprintf(stderr,"failed to set send timeout: %d/n",WSAGetLastError());       

    memset(&dest_addr,0,sizeof(dest_addr));
    dest_addr.sin_family=AF_INET;
    if(host=gethostbyname(par_host) )
    {
  memcpy( (char *)&dest_addr.sin_addr,host->h_addr,host->h_length);
  //resolve address to hostname
  if(host=gethostbyaddr(host->h_addr,4,PF_INET))
   par_host=host->h_name;
 }
    else if( dest_addr.sin_addr.s_addr=inet_addr(par_host)==INADDR_NONE)
 {
  printf("Unkown host %s/n",par_host);
  exit(1);
 }

      
    pid=getpid();
    printf("Pinging %s [%s]: with %d bytes of data:/n/n",par_host,inet_ntoa(dest_addr.sin_addr),SEND_SIZE);                   
 for(i=0;i<SEND_COUNT;i++)                       
    {
     send_packet();
        recv_packet();
  Sleep(1000);
    }
}

//this algorithm is referenced from other's
unsigned short cal_chksum(unsigned short *addr,int len)
{      
 int nleft=len;
    int sum=0;
    unsigned short *w=addr;
    unsigned short answer=0;
 
    while(nleft>1)
    {       sum+=*w++;
            nleft-=2;
    }
    if( nleft==1)
    {       *(unsigned char *)(&answer)=*(unsigned char *)w;
            sum+=answer;
    }
    sum=(sum>>16)+(sum&0xffff);
    sum+=(sum>>16);
    answer=~sum;
    return answer;
}

//打包
int pack(int pack_no)
{      
 int packsize;
    struct icmp *icmp;

    packsize=8+SEND_SIZE;
    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;
 icmp->icmp_data=GetTickCount();
    icmp->icmp_cksum=cal_chksum( (unsigned short *)icmp,packsize); /*校验算法*/
    return packsize;
}

//解包
int unpack(unsigned char *buf,int len)
{     
    struct ip *ip;
    struct icmp *icmp;
    double rtt;
 int iphdrlen;

    ip=(struct ip *)buf;
    iphdrlen=ip->ip_hl*4;   
    icmp=(struct icmp *)(buf+iphdrlen);          
    if( (icmp->icmp_type==ICMP_ECHOREPLY) && (icmp->icmp_id==pid) )
    {
  len=len-iphdrlen-8;  
  rtt=GetTickCount()-icmp->icmp_data; 
     printf("Reply from %s: bytes=%d time=%.0fms TTL=%d icmp_seq=%u/n",            
             inet_ntoa(from_addr.sin_addr),
    len,
    rtt,
    ip->ip_ttl,
             icmp->icmp_seq);
  return 1;
    }
 return 0;
}

//发送
void send_packet()
{  
    int packetsize;
    static int pack_no=0;
   
    packetsize=pack(pack_no++);
    if( sendto(sockfd,sendpacket,packetsize,0,(struct sockaddr *)&dest_addr,sizeof(dest_addr) )<0  )
     printf("Destination host unreachable./n");
// printf("send NO %d/n",pack_no-1);
}

//接收
void recv_packet()
{   
 int n,fromlen;
 int success;

    fromlen=sizeof(from_addr);
 do
 {
  if( (n=recvfrom(sockfd,recvpacket,sizeof(recvpacket),0,(struct sockaddr *)&from_addr,&fromlen)) >=0)
   success=unpack(recvpacket,n);
  else if (WSAGetLastError() == WSAETIMEDOUT)
  {
   printf("Request timed out./n");
   return;
  }
 }while(!success);

}

 

 

ping的实现和代码分析

ping命令是用来查看网络上另一个主机系统的网络连接是否正常的一个工具。ping命令的工作原理是:向网络上的另一个主机系统发送ICMP报文,如果指定系统得到了报文,它将把报文一模一样地传回给发送者,这...
  • u010893129
  • u010893129
  • 2014年11月23日 08:39
  • 5210

微软ping程序源代码完整版

微软ping程序源代码完整版 编写自己的一个ping程序,可以说是许多人迈出网络编程的第一步吧!!这个ping程序的源代码经过我的修改和调试,基本上可以取代windows中自带的ping程序. 各个...
  • WuOu
  • WuOu
  • 2016年01月01日 17:47
  • 2344

Windows下基于Qt用c++实现ping

Windows下基于Qt用c++实现ping1、代码来源此份ping的源码来自于vc6对应msdn中。自己稍做修改,然后成了现在这个版本。2、winsock与winsock2windows下socke...
  • junbujianwpl
  • junbujianwpl
  • 2017年07月30日 15:23
  • 705

ping程序的实现

关于网络编程,知之甚少,linux环境下编程的经验也比较缺乏,于是乎,在百度文库上下载了一个关于ping的程序设计,照着将代码敲打一遍,顺便熟悉某些东东。 敲完代码,运行时,发现错误极多,正好也试着学...
  • petershina
  • petershina
  • 2013年02月05日 14:05
  • 9121

Windows下使用C语言实现Ping的源码

// Ping.c // Ping [host] [packet-size] // // host String name of host to ping ...
  • u012935646
  • u012935646
  • 2014年11月23日 11:55
  • 782

Windows下PING程序实现

跟着网上的代码试着敲了一遍,熟悉Ping的过程。 Ping.h //Ping.h //Define the header of IP and ICMP #pragma pack(1) #define ...
  • Hearthougan
  • Hearthougan
  • 2016年06月12日 14:33
  • 1427

socket实现Ping命令

实现的原理还是很简单的,主要还是要对ICMP协议有所了解。ICMP协议是在IP协议的数据部分实现的,普通的socket只能建立TCP或者UDP连接,实在传输层上做东西,只能控制要传输的数据,不能控制I...
  • sunny1996
  • sunny1996
  • 2017年03月11日 23:07
  • 678

用C语言实现Ping命令

【引言】 前几天脑子里忽然蹦出来一个想法,想试着用C语言写一个自己的Ping命令出来。开始还有些茫然无措,因为此前没有接触过网络编程方面的知识。幸运的是对Ping的实现原理还是比较清楚的,难度和挑战...
  • qq_33724710
  • qq_33724710
  • 2016年06月03日 11:21
  • 9411

C++实现一个ping命令

今天利用C++实现一个自己的ping命令,首先我们在Linux下运行下ping命令,看它完成了那些功能: 1.向目标IP发送一个64字节的ICMP请求包,然后收到目标IP的一个ICM...
  • zhaorenjie93
  • zhaorenjie93
  • 2017年06月04日 16:30
  • 880

java实现ping功能的几种方法

java实现ping功能 一、纯Java实现ICMP的ping命令 import java.io.*; import java.net.*; import java.nio.channel...
  • qq_29663071
  • qq_29663071
  • 2016年01月22日 17:20
  • 2505
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:如何用winsock实现ping(源代码)
举报原因:
原因补充:

(最多只允许输入30个字)