ping 程序实现
1.软件使用说明
本软件由源码和可执行文件.exe构成,运行.exe后可以看到控制台界面和一行提示“请输入要ping的域名或ip地址:”,在其后输入以www开头的域名或点分十进制格式的ip地址后回车,就能够ping对应的域名或ip地址。对于要ping的域名,软件会ping所有经过DNS域名解析服务器根据主机名解析得到对应的IP地址,因为一个域名可能对应到多个服务器,所以解析到的ip地址不一定只有一个。
实现的功能包括:
(1) 可以指定ping的目标主机ip, 并且支持域名,如”www.baidu.com”。
(2) 每次发送4个ICMP回送请求报文,每个请求报文的数据大小为32B,发送超时和接收超时时间为1000ms。
(3) 对于发出的每个ICMP回送请求报文,若收到应答报文,显示每个应答报文的数据大小(B),源IP、序号、响应时间(ms);若发送超时或接收超时,显示“Request time out.”。
(4) 最后显示用户名和ping的统计信息,统计信息包括发出的请求报文个数、收到的应答报文个数、丢包个数和丢包率。
2.API和数据结构说明
引用的API:
API函数名 | API函数原型 | 说明 |
---|---|---|
WSAStartup | int WSAAPI WSAStartup(In WORD wVersionRequested, Out LPWSADATA lpWSAData ); | 初始化 |
WSACreateEvent | WSAEVENT WSAAPI WSACreateEvent(void); | 生成事件 |
GetCurrentProcessId | DWORD WINAPI GetCurrentProcessId( VOID ); | 获取进程Id |
WSASocketW | SOCKET WSAAPI WSASocketW( In int af,In int type,In int protocol,In_opt LPWSAPROTOCOL_INFOW lpProtocolInfo,In GROUP g,In DWORD dwFlags); | 套接字 |
WSAEventSelect | int WSAAPI WSAEventSelect( In SOCKET s, In_opt WSAEVENT hEventObject, In long lNetworkEvents ); | 选择事件 |
WSACleanup | int WSAAPI WSACleanup( void ); | 清除内容 |
sendto | int WSAAPI sendto( In SOCKET s, In_reads_bytes(len) const char FAR * buf, In int len, In int flags, In_reads_bytes(tolen) const struct sockaddr FAR * to, In int tolen ); | 发送数据包 |
WSAWaitForMultipleEvents | DWORD WSAAPI WSAWaitForMultipleEvents( In DWORD cEvents, In_reads(cEvents) const WSAEVENT FAR * lphEvents, In BOOL fWaitAll, In DWORD dwTimeout, In BOOL fAlertable ); | 等待事件 |
WSAEnumNetworkEvents | int WSAAPI WSAEnumNetworkEvents( In SOCKET s, In WSAEVENT hEventObject, Out LPWSANETWORKEVENTS pNetworkEvents ); | 联合网络事件 |
recvfrom | int WSAAPI recvfrom( In SOCKET s, Out_writes_bytes_to(len, return) __out_data_source(NETWORK) char FAR * buf, In int len, In int flags, Out_writes_bytes_to_opt(*fromlen, *fromlen) struct sockaddr FAR * from, Inout_opt int FAR * romlen ); | 接收数据包 |
GetLocalTime | VOID WINAPI GetLocalTime( Out LPSYSTEMTIME lpSystemTime ); | 获取本地时间 |
SystemTimeToFileTime | BOOL WINAPI SystemTimeToFileTime( In CONST SYSTEMTIME* lpSystemTime, Out LPFILETIME lpFileTime ); | 系统时间转文件时间 |
gethostbyname | struct hostent FAR * WSAAPI gethostbyname( In_z const char FAR * name ); | 获取主机信息 |
GetLastError | DWORD WINAPI GetLastError( VOID ); | 返回错误结果 |
定义的数据结构:
struct IPHeader
{
BYTE m_byVerHLen; //4位版本+4位首部长度
BYTE m_byTOS; //服务类型
USHORT m_usTotalLen; //总长度
USHORT m_usID; //标识
USHORT m_usFlagFragOffset; //3位标志+13位片偏移
BYTE m_byTTL; //TTL
BYTE m_byProtocol; //协议
USHORT m_usHChecksum; //首部检验和
ULONG m_ulSrcIP; //源IP地址
ULONG m_ulDestIP; //目的IP地址
};
struct ICMPHeader
{
BYTE m_byType; //类型
BYTE m_byCode; //代码
USHORT m_usChecksum; //检验和
USHORT m_usID; //标识符
USHORT m_usSeq; //序号
ULONG m_ulTimeStamp; //时间戳(非标准ICMP头部)
};
struct PingReply
{
USHORT m_usSeq; //响应序列号
DWORD m_dwRoundTripTime; //往返时间
DWORD m_dwBytes; //数据包大小
DWORD m_dwTTL; //生存时间
};
class ParseUrl //解析url
{
public:
ParseUrl(); //构造函数
~ParseUrl(); //析构函数
BOOL Ping(DWORD dwDestIP, PingReply *pPingReply = NULL, DWORD dwTimeout = 1000); //设定超时时间
BOOL Ping(char *szDestIP, PingReply *pPingReply = NULL, DWORD dwTimeout = 1000); //设定超时时间
private:
BOOL PingCore(DWORD dwDestIP, PingReply *pPingReply, DWORD dwTimeout);
USHORT CalCheckSum(USHORT *pBuffer, int nSize); //校验和
ULONG GetTickCountCalibrate();
private:
SOCKET m_sockRaw;
WSAEVENT m_event;
USHORT m_usCurrentProcID;
char *m_szICMPData;
BOOL m_bIsInitSucc;
private:
static USHORT s_usPacketSeq;
};