利用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;
}
求大牛。。。
[解决办法]
#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