【问题标题】:RAW ICMP socket: recvfrom() not recieving any dataRAW ICMP 套接字:recvfrom() 未收到任何数据
【发布时间】:2017-02-13 01:09:16
【问题描述】:

以下代码是一个旨在发送 ICMP 回显请求和接收回复的程序。

/*
    Forgive my lack of error handling :)
*/
SOCKET ASOCKET = INVALID_SOCKET;
struct sockaddr saddr;
struct sockaddr_in *to = (struct sockaddr_in *) &saddr;
struct sockaddr_in from;
int fromsize = sizeof(from);
std::string ip = "[arbitrary ip address]";

struct ICMP {
    USHORT type;
    USHORT code;
    USHORT cksum;
    USHORT id;
    USHORT seq;
}*_ICMP;

char sendBuffer[sizeof(struct ICMP)];
char recvBuffer[256];

WSADATA wsaData;
WSAStartup(MAKEWORD(2, 2), &wsaData);

memset(&saddr, NULL, sizeof(saddr));
ASOCKET = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);

//  Configure timeout
DWORD timeoutmilsec = 3000;
setsockopt(ASOCKET, SOL_SOCKET, SO_RCVTIMEO, (char *)&timeoutmilsec, sizeof(timeoutmilsec));

to->sin_family = AF_INET;
inet_pton(AF_INET, ip.c_str(), &(to->sin_addr));

_ICMP = new ICMP();

_ICMP->type = 8;
_ICMP->code = 0;
_ICMP->cksum = 0;
_ICMP->id = rand();
_ICMP->seq++;
// I have omitted my declaration of checksum() for simplicity
_ICMP->cksum = checksum((u_short *)_ICMP, sizeof(struct ICMP));

memcpy(sendBuffer, _ICMP, sizeof(struct ICMP));

if (sendto(ASOCKET, sendBuffer, sizeof(sendBuffer), NULL, (sockaddr *)&saddr, sizeof(saddr)) == SOCKET_ERROR)
{
    printf("sendto() failed with error: %u\n", WSAGetLastError());
    return false;
}

if (recvfrom(ASOCKET, recvBuffer, sizeof(recvBuffer), NULL, (sockaddr *)&from, &fromsize) == SOCKET_ERROR)
{
    if (WSAGetLastError() == TIMEOUTERROR)
    {
        printf("Timed out\n\n");
        return false;
    }

    printf("recvfrom() failed with error: %u\n", WSAGetLastError());
    return false;
}

我的问题是我的recvfrom() 调用没有收到任何数据并返回 TIMEOUTERROR (10060) 尽管 ping 已回复(Wireshark 捕获请求和正在发送的回复) . sendto() 有效,但 recvfrom() 行为怪异,我不知道问题出在哪里。

我觉得有趣的是recvfrom() 只会在网关告诉我主机不可达时接收数据;如果主机可访问且已响应 ping,则不会。

【问题讨论】:

  • 可能是 Windows 防火墙阻止了数据包?

标签: c++ windows sockets raw-sockets


【解决方案1】:

问题出在struct ICMP

ICMP 的typecode 应该是unsigned char

ICMP 的头部应该是 8 字节,而 struct ICMP 的大小是 10 字节。

所以应该改为:

struct ICMP {
    unsigned char type;
    unsigned char code;
    USHORT cksum;
    USHORT id;
    USHORT seq;
}*_ICMP;

【讨论】:

    【解决方案2】:

    事实证明,我的防火墙一直在阻止响应。我的代码中唯一的错误是我的 ICMP 结构的大小(由 cshu 提到)。

    感谢大家的帮助。

    【讨论】:

      猜你喜欢
      • 2010-11-10
      • 2013-01-28
      • 2018-12-10
      • 2020-02-22
      • 1970-01-01
      • 1970-01-01
      • 2015-05-23
      • 1970-01-01
      • 2016-07-10
      相关资源
      最近更新 更多