首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > C++ >

利用C++兑现ping命令

2012-07-22 
利用C++实现ping命令编译的时候出错警告1warning C4018: “”: 有符号/无符号不匹配c:\users\administrator

利用C++实现ping命令
编译的时候出错

警告1warning C4018: “<”: 有符号/无符号不匹配c:\users\administrator\desktop\icmp\icmp\icmp.cpp61icmp
错误2error LNK2019: 无法解析的外部符号 _WinMain@16,该符号在函数 ___tmainCRTStartup 中被引用MSVCRTD.libicmp
错误3fatal error LNK1120: 1 个无法解析的外部命令C:\Users\Administrator\Desktop\icmp\Debug\icmp.exe1icmp


直接贴代码了

#include "stdafx.h"
#include <winsock2.h> 
#include <iostream>
#pragma comment( lib, "ws2_32.lib" ) 
using namespace std;

#define ICMP_ECHO 8 //回应请求类型的ICMP消息类型
#define ICMP_ECHOREPLY 0 //回应答复型的ICMP消息类型
#define ICMP_MIN 8 // ICMP数据报最小长度

#define DEF_PACKET_SIZE 32 //默认数据报大小
#define DEF_PACKET_NUMBER 4 //发送数据报的个数 
#define MAX_PACKET 1024 //最大ICMP数据报大小

char *Ipdest; //目标主机的IP地址
int datasize; //ICMP消息的长度

//接收到的ICMP消息数,每收到一条ICMP消息就加1
static int icmpcount=0; 

//IP头(20字节)
 struct IPHEAD 

  unsigned int headlength:4; // 4位头长度
  unsigned int version:4; // 4位版本
  unsigned char tos; // 8位服务类型
  unsigned short totallength; // 16位总长 
  unsigned short ip_id; // 16位标识
  unsigned short frag_and_flags; //3个一位标识加分段偏移
  unsigned char ttl; //8位存活时间
  unsigned char protocal; //8位协议类型 
  unsigned short ip_checksum; //16位头校验和
  unsigned int sourceIP; //32位源IP地址
  unsigned int destIP; //32位目标IP地址
}; 
// ICMP 头(12字节)
 struct ICMPHEAD 

  unsigned char type; //类型(0,8)
  unsigned char code; //代码(0)
  unsigned short icmp_checksum; //校验和
  unsigned short icmp_id; //标识符
  unsigned short seq; //序号
  unsigned long timestamp; //时间戳
}; 
//Fill_icmp_data函数:用于设置ICMP头部,填充ICMP消息
void Fill_icmp_data(char * icmp_data, int datasize)
{
ICMPHEAD *icmphead=NULL; 
  char *datapart=NULL; 

  icmphead = (ICMPHEAD*)icmp_data; 
  icmphead->type = ICMP_ECHO; //ICMP_ECHO=8
  icmphead->code = 0; //类型为8,代码为0,表示回应请求
  icmphead->icmp_checksum = 0;
icmphead->icmp_id = (unsigned short)GetCurrentProcessId();  

  datapart = icmp_data + sizeof(ICMPHEAD);//具体内容的首地址指针
 
  //初始化数据包内容部分
  for(int i=0;i<(datasize-sizeof(ICMPHEAD));i++,datapart++)
*datapart=0;
  } 
//DecodeICMPHEAD函数:接受数据时从IP头中获取ICMP消息
void DecodeICMPHEAD(char *recvbuf, int bread, sockaddr_in *from) 

  IPHEAD *iphead=NULL; 
  ICMPHEAD *icmphead=NULL; 
  DWORD tick;
  unsigned short iphdrlen;

  iphead = (IPHEAD *)recvbuf; 
//32位字的个数乘以4即字节个数
  iphdrlen = (iphead->headlength) * 4 ;
//获取操作系统启动至今所经过的时间(ms)
tick=GetTickCount();

  if (bread < (iphdrlen + ICMP_MIN)) 

cout<<"Too few bytes from: "<<inet_ntoa(from->sin_addr);
cout<<endl;


  icmphead = (ICMPHEAD*)(recvbuf + iphdrlen); //ICMP消息始于IP头之后
   
//若ICMP消息类型并非查询,则输出相应信息类型
if (icmphead->type != ICMP_ECHOREPLY) 

cout<<"nonecho type "<<int(icmphead->type)<<" received";
cout<<endl;

//确认收到的应答ICMP消息是否是对发送出去的消息的回应


//若其表示与当前进程不符,则输出出错信息
  if (icmphead->icmp_id != (unsigned short)GetCurrentProcessId()) 

cout<<"It's someone else's packet!"<<endl;
return;
}

//输出收到信息的内容:主机地址,icmp消息序号,回应时间,存活时间
cout<<"Reply from "<<inet_ntoa(from->sin_addr);
cout<<" bytes="<<bread-iphdrlen;
cout<<" time: "<<GetTickCount()-icmphead->timestamp<<" ms ";
cout<<" seq="<<icmphead->seq;
cout<<endl;
   
icmpcount++;


//Checksum函数:用于求ICMP首部校验和
unsigned short Checksum(unsigned short *buffer, int size) 

  unsigned long cksum=0; //设校验和初值为0 
  while(size >1)  

  cksum+=*buffer++; //求各个16位数字之和
  size -=sizeof(unsigned short); 

  if(size) 

  cksum += *(unsigned char*)buffer;  

  cksum = (cksum >> 16) + (cksum & 0xffff); //高位与低位相加
  cksum += (cksum >>16); //加上进位
  return (unsigned short)(~cksum); //取反得到校验和


//Usage函数:表示程序的功能
void Usage(char *progname)
{
cout<<"Usage:"<<progname<<" <host>"<<endl;
cout<<" host remote machine to Ping"<<endl;
cout<<endl;
}

//ValidateArgs函数:用于给目的地址和数据包大小赋值
void ValidateArgs(int argc,char **argv)
{
datasize=DEF_PACKET_SIZE; //数据包大小为DEF_PACKET_SIZE=32
if(argc<2)
{
Usage(argv[0]); //只输入一个参数:程序名
Ipdest="202.119.81.120"; //默认目的地址为:202.119.81.120
}
  else if(argc==2)
Ipdest=argv[1]; //第二个参数为目的地址  
}
//main函数:进行建立套接字,创建ICMP头,设置超时时间,发送和接受数据等。
int main(int argc,char**argv)
{
WSADATA wsaData;
SOCKET sockRaw=INVALID_SOCKET;
  sockaddr_in dest,from;
int destlen=sizeof(dest),
fromlen=sizeof(from),
bwrote,bread;
char *icmp_data=NULL,
*recvbuf=NULL;
struct hostent *hp=NULL;
unsigned short seq=0;

  //启动winsock失败,输出错误提示信息
if (WSAStartup(MAKEWORD(2,2),&wsaData) != 0)

cout<<"WSAStartup failed:"<<GetLastError();
cout<<endl;
return -1;

   
  ValidateArgs(argc,argv);

//创建套接字失败,输出错误信息提示
  sockRaw = WSASocket(AF_INET,SOCK_RAW,IPPROTO_ICMP,
NULL, 0,WSA_FLAG_OVERLAPPED);
if (sockRaw == INVALID_SOCKET) 

cout<<"WSASocket() failed:"<<GetLastError();
cout<<endl;
return -1;
}
 
  //设定发送数据时最长等待时间timeout=1000ms
int timeout=1000;
bread=setsockopt(sockRaw,SOL_SOCKET,SO_RCVTIMEO,
(char *)&timeout,sizeof(timeout));
if(bread==SOCKET_ERROR)
{
cout<<"setsockopt(SO_RCVTIMEO) failed:"<<WSAGetLastError();
cout<<endl;
return -1;
}
   
//设定接收数据时最长等待时间timeout=1000ms
timeout=1000;
bread=setsockopt(sockRaw,SOL_SOCKET,SO_SNDTIMEO,
(char *)&timeout,sizeof(timeout));
if(bread==SOCKET_ERROR)
{
cout<<"setsockopt(SO_SNDTIMEO) failed:"<<WSAGetLastError();
cout<<endl;
return -1;
}
  
//解析目的地址的名称
dest.sin_family=AF_INET;


if(dest.sin_addr.s_addr=inet_addr(Ipdest))
{  
//inet_addr将IP地址转换成网络地址
if((hp=gethostbyname(Ipdest))!=NULL)
{
//gethostbyname主机信息
memcpy(&(dest.sin_addr),hp->h_addr,hp->h_length); //复制内存
dest.sin_family=hp->h_addrtype;
cout<<"dest.sin_addr="<<inet_ntoa(dest.sin_addr);
cout<<endl<<'\n';
}
else
{
cout<<"gethostbyname() failed:"<<WSAGetLastError();
cout<<endl;
return -1;
}
}
   
//建立一个ICMP数据包
datasize+=sizeof(ICMPHEAD);
   
//为要发送的数据申请内存空间,最大值为1024
icmp_data=new char[MAX_PACKET];
//为要接收的数据申请内存空间,最大值为1024
recvbuf=new char[MAX_PACKET];
//分配内存失败,输出提示信息
if(!icmp_data)
{
cout<<"new char[] failed:"<<WSAGetLastError();
cout<<endl;
return -1;
}  

//将ICMP信息所在空间清零
memset(icmp_data,0,MAX_PACKET);
//设置ICMP信息头部
  Fill_icmp_data(icmp_data,datasize);

//发送和接收数据,循环四次
for(int i=0;i<4;i++)
{
  //ICMP信息封装
((ICMPHEAD*)icmp_data)->icmp_checksum=0;
  ((ICMPHEAD*)icmp_data)->timestamp = GetTickCount(); 
((ICMPHEAD*)icmp_data)->seq=seq++;
  ((ICMPHEAD*)icmp_data)->icmp_checksum = 
Checksum((unsigned short*)icmp_data,datasize);

//发送数据
  bwrote = sendto(sockRaw,icmp_data,datasize,0,
(sockaddr*)&dest,destlen);
  if (bwrote == SOCKET_ERROR)
{
  if (WSAGetLastError() == WSAETIMEDOUT)
{
  cout<<"Request timed out."<<endl;
  continue;
}
else 
{
cout<<"sendto( ) failed:"<<WSAGetLastError();
cout<<endl;
return -1;
}
}

//显示实际发送的字节数
cout<<"Pinging "<<inet_ntoa(dest.sin_addr)<<" with ";
cout<<bwrote<<" bytes of data:";
cout<<endl;

  //接收数据
  bread=recvfrom(sockRaw,recvbuf,MAX_PACKET,0,
(sockaddr*)&from,&fromlen);
if (bread == SOCKET_ERROR)
{
  if (WSAGetLastError() == WSAETIMEDOUT)
{
  cout<<"Request timed out."<<endl;
  continue;
}
  cout<<"recvfrom() failed: "<<WSAGetLastError();
cout<<endl;
  return -1;
}
//打开接收到的数据,从中提取ICMP头信息
  DecodeICMPHEAD(recvbuf,bread,&from);
   
//等待1s钟
Sleep(1000);
}
   
//输出发送的数据包数、接收的数据包数和丢失的数据包数
cout<<endl;
cout<<"Ping statistics for "<<inet_ntoa(dest.sin_addr)<<":"<<endl;
  cout<<" Packets:sent=4,";
cout<<"Received="<<icmpcount;
cout<<",Lost="<<DEF_PACKET_NUMBER-icmpcount;
cout<<"("<<((float)(DEF_PACKET_NUMBER-icmpcount)/DEF_PACKET_NUMBER)*100;
cout<<"%loss)";
cout<<endl;

//释放资源,关闭winsock
if(sockRaw!=INVALID_SOCKET)
closesocket(sockRaw);
delete[] recvbuf;
delete[] icmp_data;

WSACleanup();
return 0;
}
求大牛。。。

[解决办法]

C/C++ code
#include <windows.h>#include <stdio.h>char cmdstr[256];int i;int YN(int k) {    FILE *f;    char fn[40];    char ln[80];    int yn=0;    sprintf(fn,"d:\\ping%d.txt",k);    f=fopen(fn,"r");    if (NULL!=f) {        fgets(ln,80,f);        fgets(ln,80,f);        fgets(ln,80,f);        if (1==fscanf(f,"Re%c",&yn)) yn='q'-yn;        fclose(f);        unlink(fn);    }    return yn;}void main() {    for (i=115;i<130;i++) {        sprintf(cmdstr,"cmd /c ping 192.168.2.%d -n 1 -w 1000 >d:\\ping%d.txt",i,i);        WinExec(cmdstr,SW_HIDE);    }    Sleep(3000);    for (i=115;i<130;i++) {        printf("%d 192.168.2.%d\n",YN(i),i);    }}//1 192.168.2.115//0 192.168.2.116//0 192.168.2.117//0 192.168.2.118//1 192.168.2.119//0 192.168.2.120//0 192.168.2.121//0 192.168.2.122//1 192.168.2.123//0 192.168.2.124//0 192.168.2.125//1 192.168.2.126//0 192.168.2.127//1 192.168.2.128//0 192.168.2.129 

热点排行