2017-02-13 157 views
2

以下代码是一个旨在发送ICMP回应请求并接收回复的程序。RAW ICMP套接字:recvfrom()没有收到任何数据

/* 
    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)(Wireshark的捕获请求和应答发送)。 sendto()工程,但recvfrom()行为怪异,我无法弄清楚问题是什么。

我觉得有趣的是recvfrom()只有当网关告诉我主机无法访问时才会收到数据;如果主机可以访问并已响应ping,则不会发生。

+1

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

回答

1

原来的全部时间,这是我防火墙阻止响应。我的代码中唯一的错误是我的ICMP结构的大小(由cshu提及)。

感谢大家的帮助。

3

问题出在struct ICMP

typecode ICMP应该是unsigned char

ICMP头应为8字节,但大小为struct ICMP为10个字节。

所以应该改为:

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

正确,请参见[RFC 792](https://tools.ietf.org/html/rfc792)。 – EJP

相关问题