网络编程 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:%d\n", 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:%d\n", WSAGetLastError);
        return -1;
    }

    Ret = recvfrom(sockRaw, recvBuf, 1024, 0, (SOCKADDR*)&from, &Len);
    if (Ret == SOCKET_ERROR) {
        if (WSAGetLastError() == WSAETIMEDOUT) {
            printf("timed out\n");
            continue;
        }
        printf("recvfrom() failed:%d\n", WSAGetLastError());
        return -1;
    }

    //开始解析接收到的ICMP
    int Tick = ::GetTickCount();
    if (Ret < sizeof(IpHeader) + sizeof(ICMP_HDR))
        printf("too few bytes from %s\n", inet_ntoa(from.sin_addr));
    ICMP_HDR* pRecvIcmp = (ICMP_HDR*)(recvBuf + sizeof(IpHeader));
    if (pRecvIcmp->icmp_type != 0) {//回显
        printf("nonecho type %d recvd\n", 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 ms\n", Tick - pRecvIcmp->icmp_timestamp);
    Sleep(1000);
}

return 0;

}
图片说明

3个回答

上面的是在VS2015上运行的,在VS2013上运行的结果还不一样
图片说明

图片说明

你ping的是127.0.0.1啊,超时了

baby00qi
baby00qi 127.0.0.1不是主机地址吗,为什么会超时啊?
3 年多之前 回复
Csdn user default icon
上传中...
上传图片
插入图片
抄袭、复制答案,以达到刷声望分或其他目的的行为,在CSDN问答是严格禁止的,一经发现立刻封号。是时候展现真正的技术了!
立即提问