问题描述
- 网络编程 ping程序有点问题,求大神帮忙看看
-
// ping.cpp : 定义控制台应用程序的入口点。#include "stdafx.h"
#include
#pragma comment(lib,"ws2_32")//定义ICMP首部
typedef struct icmp_hdr{
unsigned char icmp_type; //ICMP消息类型,回显请求:8,回显应答请求:0
unsigned char icmp_code; //代码,代码域进一步定义了请求或消息的类型
unsigned short icmp_checksum;//校验和
//下面是回显头
unsigned short icmp_id; //ICMP数据报的ID号;用来唯一标识此请求的ID号,通常设为进程ID
unsigned short icmp_sequence;//ICMP数据报的序列号
unsigned long icmp_timestamp;//时间戳,可选数据部分,可以忽略
}ICMP_HDR; ///struct IpHeader {
BYTE HeaderLength; //首部长度
BYTE Version; //版本
BYTE DS; //区分服务
WORD TotalLength; //总长度
WORD ID; //标识
BYTE FragmentOffset0; //片偏移
BYTE MF; //MF标识
BYTE DF; //DF标识
BYTE Reserved; //保留标识
BYTE FragmentOffset1; //片偏移
BYTE TTL; //生存时间
BYTE Protocol; //协议
WORD Checksum; //检验和
DWORD SourceAddress; //源地址
DWORD DestinationAddress;//目的地址
};USHORT checksum(USHORT* buffer, int size) //计算校验和
{
ULONG cksum = 0;while (size > 1) { //将数据以字为单位累加到cksum中 cksum += *buffer++; size -= sizeof(USHORT); } if (size) { //如果数据长度为奇数,最后一个字节将被扩展到字,累加的结果是一个双字 cksum += *(UCHAR*)buffer; } cksum = (cksum >> 16) + (cksum & 0xFFFF);//将双字的高16位于低16位相加 cksum += (cksum >> 16); return (USHORT)(~cksum); //最后取反得到校验和
}
int _tmain(int argc, _TCHAR* argv[])
{
WORD wVersionRequested = MAKEWORD(1, 1);
WSADATA wsaData;int err=WSAStartup(wVersionRequested,&wsaData); if (err != 0) return 0; if (LOBYTE(wsaData.wVersion) != 1 || HIBYTE(wsaData.wVersion) != 1){ WSACleanup(); return 0; } char* szDestIp = "127.0.0.1"; //目标IP地址,即要Ping的IP地址 SOCKET sockRaw = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP); //创建原始套接字 SOCKADDR_IN dest; //设置目的地址 dest.sin_family = AF_INET; dest.sin_addr.S_un.S_addr = inet_addr(szDestIp); dest.sin_port = htons(0); char buff[sizeof(ICMP_HDR)+32]; //创建ICMP封包 ICMP_HDR* pIcmp = (ICMP_HDR*)buff; //下面填写ICMP封包数据 pIcmp->icmp_type = 8;//请求一个ICMP回显 pIcmp->icmp_code = 0; pIcmp->icmp_checksum = 0; pIcmp->icmp_id = (USHORT)GetCurrentProcessId();//GetCurrentProcessId:获取当前进程的一个唯一标识符 pIcmp->icmp_sequence = 0; memset(buff, 'E', 32);//填充数据部分,可以为任意 int timeout = 1000; //设置接收超时处理 int _break = setsockopt(sockRaw, SOL_SOCKET, SO_RCVTIMEO, (char*)&timeout, sizeof(timeout)); if (_break == SOCKET_ERROR){ fprintf(stderr, "failed to set timeout:%dn", WSAGetLastError()); } if (bind(sockRaw, (sockaddr*)&dest, sizeof(dest)) == SOCKET_ERROR) { printf("bind error!n"); return 0; } //开始发送和接收ICMP封包 USHORT Seq = 0; char recvBuf[1024]; SOCKADDR_IN from; int Len = sizeof(from); while (1) { static int Count = 0; int Ret; if (Count++ == 4) break; pIcmp->icmp_checksum = 0; pIcmp->icmp_timestamp = GetTickCount(); pIcmp->icmp_sequence = Seq++; pIcmp->icmp_checksum = checksum((USHORT*)buff, sizeof(ICMP_HDR) + 32); Ret = sendto(sockRaw, buff, sizeof(ICMP_HDR) + 32, 0, (SOCKADDR*)&dest, sizeof(dest)); if (Ret == SOCKET_ERROR) { printf("sendto() failed:%dn", WSAGetLastError); return -1; } Ret = recvfrom(sockRaw, recvBuf, 1024, 0, (SOCKADDR*)&from, &Len); if (Ret == SOCKET_ERROR) { if (WSAGetLastError() == WSAETIMEDOUT) { printf("timed outn"); continue; } printf("recvfrom() failed:%dn", WSAGetLastError()); return -1; } //开始解析接收到的ICMP int Tick = ::GetTickCount(); if (Ret < sizeof(IpHeader) + sizeof(ICMP_HDR)) printf("too few bytes from %sn", inet_ntoa(from.sin_addr)); ICMP_HDR* pRecvIcmp = (ICMP_HDR*)(recvBuf + sizeof(IpHeader)); if (pRecvIcmp->icmp_type != 0) {//回显 printf("nonecho type %d recvdn", pRecvIcmp->icmp_type); return -1; } if (pRecvIcmp->icmp_id != GetCurrentProcessId()) { printf("someone else's packet!n"); return -1; } printf("%d bytes from %s:", Ret, inet_ntoa(from.sin_addr)); printf("icmp_seq = %d , ", pRecvIcmp->icmp_sequence); printf("time: %d msn", Tick - pRecvIcmp->icmp_timestamp); Sleep(1000); } return 0;
解决方案
上面的是在VS2015上运行的,在VS2013上运行的结果还不一样
解决方案三:
你ping的是127.0.0.1啊,超时了