sendto和recvfrom的问题
问题如下:
自己先填充了一个ICMP数据包的缓冲区,然后通过sendto发送,接着用recvfrom准备接收返回的信息,为什么recvfrom会一直挂起收不到数据呢?
socket采用下面函数构造:
socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);
[解决办法]
这就太难说了, 信息太少了。
[解决办法]
网络编程初期的问题基本都是自己实现上的小bug,莫名其妙的
写多了自然就不出了
[解决办法]
下个UNIX网络编程看一下原始套接字章节的ICMP示例吧,网上的个人代码很难信赖。
[解决办法]
给个例子吧:
- C/C++ code
#include "stdio.h"#include "Winsock2.h"#pragma comment( lib, "ws2_32.lib" ) //;typedef struct IpHeader{ unsigned char Version_HLen; unsigned char TOS; unsigned short Length; unsigned short Ident; unsigned short Flags_Offset; unsigned char TTL; unsigned char Protocol; unsigned short Checksum; unsigned int SourceAddr; unsigned int DestinationAddr;} Ip_Header;typedef struct IcmpHeader{ BYTE Type; BYTE Code; USHORT Checksum; USHORT ID; USHORT Sequence;} Icmp_Header;USHORT checksum(USHORT *buff, int size){ unsigned long cksum = 0; while (size > 1) { cksum += *buff++; size -= sizeof(USHORT); } if (size) { cksum += *(UCHAR*)(buff); } cksum = (cksum >> 16) + (cksum &0xffff); cksum += (cksum >> 16); return (USHORT)(~cksum);}int main(int argc, char *argv[]){ WSADATA wsaData; sockaddr_in DestAddr; Ip_Header *ip; Icmp_Header *icmp; Icmp_Header *SendIcmp; int Timeout = 1000; //char DestIpAddr[100] = "192.168.1.3"; // char IcmpBuffer[8] = "";//too small char IcmpBuffer[32] = ""; SOCKET IcmpSocket; char RecvBuffer[1024]; sockaddr_in addr; int Len = sizeof(addr); int Result; struct hostent * hp; if (argc !=2 ) {//rendb printf("Please input the dest!\n"); return 0; } if ((Result = WSAStartup(MAKEWORD(2, 2), &wsaData)) != 0) { printf("WSAStartup failed with error %d\n", Result); return 0; } hp = gethostbyname(argv[1]);//rendb if(hp==NULL){ printf("gethostbyname error %d!\n",WSAGetLastError()); return -1; } IcmpSocket = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP); if (IcmpSocket == INVALID_SOCKET) { printf("socket failed with error %d\n", WSAGetLastError()); return 0; } Result = setsockopt(IcmpSocket, SOL_SOCKET, SO_RCVTIMEO, (char*) &Timeout, sizeof(Timeout)); if (Result == SOCKET_ERROR) { printf("setsockopt failed with error %d \n", WSAGetLastError()); return 0; } memset(&DestAddr, 0, sizeof(DestAddr)); // DestAddr.sin_addr.s_addr = inet_addr(DestIpAddr); memcpy(&(DestAddr.sin_addr),hp->h_addr,hp->h_length);//rendb DestAddr.sin_port = htons(0); DestAddr.sin_family = AF_INET; SendIcmp = (Icmp_Header*)IcmpBuffer; SendIcmp->Type = 8; SendIcmp->Code = 0; SendIcmp->ID = (USHORT)GetCurrentProcessId(); SendIcmp->Sequence = htons(1); SendIcmp->Checksum = 0; SendIcmp->Checksum = checksum((USHORT*)IcmpBuffer, sizeof(IcmpBuffer)); printf("ping %s ...\n",inet_ntoa(DestAddr.sin_addr)); Result = sendto(IcmpSocket, IcmpBuffer, sizeof(IcmpBuffer), 0, (SOCKADDR*) &DestAddr, sizeof(DestAddr)); if (Result == SOCKET_ERROR) { printf("sendto failed with error %d \n", WSAGetLastError()); return 0; } Result = recvfrom(IcmpSocket, RecvBuffer, 1024, 0, (sockaddr*) &addr, &Len); if (Result == SOCKET_ERROR) { if (WSAGetLastError() != WSAETIMEDOUT) { printf("recvfrom failed with error %d \n", WSAGetLastError()); return 0; } else { printf("Host %s may be down.\n", inet_ntoa(DestAddr.sin_addr)); } } if (Result < sizeof(Ip_Header) + sizeof(Icmp_Header)) { printf("data error from %d\n", inet_ntoa(addr.sin_addr)); } ip = (Ip_Header*)RecvBuffer; if ((ip->SourceAddr == DestAddr.sin_addr.s_addr) && (ip->Protocol == IPPROTO_ICMP)) { icmp = (Icmp_Header*)(RecvBuffer + sizeof(Ip_Header)); if (icmp->Type != 0) { printf("type error %d ", icmp->Type); return 0; } if (icmp->ID != GetCurrentProcessId()) { printf("id error %d\n", icmp->ID); return 0; } else if ((icmp->Type == 0) && (icmp->ID == GetCurrentProcessId())) { //printf("Host %s is up.\n", DestIpAddr); printf("Host %s is up.\n", argv[1]); } } if (closesocket(IcmpSocket) == SOCKET_ERROR) { printf("closesocket failed with error %d\n", WSAGetLastError()); return 0; } if (WSACleanup() == SOCKET_ERROR) { printf("WSACleanup failed with error %d\n", WSAGetLastError()); return 0; } return 1;}