2012-06-10 207 views
0

这里是程序的代码,它应该发送一个简单的'ping'。我知道,我可以用IcmpSendEcho2()功能,但我决定这这样做:
Windows套接字错误10013

struct ICMPh 
{ 
unsigned char typ; 
unsigned char kod; 
unsigned short suma_spr; 
unsigned short id; 
unsigned short seq; 
}; 
unsigned short CalcChecksum (char *pBuffer, int nLen) 
{ 
    ////Checksum for ICMP is calculated in the same way as for IP header 
    //This code was taken from: http://www.netfor2.com/ipsum.htm 

    unsigned short nWord; 
    unsigned int nSum = 0; 
    int i; 


    for (i = 0; i < nLen; i = i + 2) 
    { 
     nWord =((pBuffer [i] << 8)& 0xFF00) + (pBuffer [i + 1] & 0xFF); 
     nSum = nSum + (unsigned int)nWord; 
    } 


while (nSum >> 16) 
    { 
     nSum = (nSum & 0xFFFF) + (nSum >> 16); 
    } 

    //One's complement the result 
    nSum = ~nSum; 

    return ((unsigned short) nSum); 
} 
int _tmain(int argc, _TCHAR* argv[]) 
{ 
WSADATA wsaData; 
if(WSAStartup(MAKEWORD(2,2),&wsaData)==SOCKET_ERROR) 
{ 
    cout<<"ERROR at startup:\n"; 
    cout<<WSAGetLastError()<<"\n"; 
    system("pause"); 
    WSACleanup(); 
    return -1; 
} 
SOCKET soc; 
int seq=0; 

soc=socket(AF_INET,SOCK_RAW,IPPROTO_ICMP); 
if(soc==INVALID_SOCKET) 
{ 
    cout<<"ERROR: INVALID SOCKET\n"; 
    cout<<WSAGetLastError()<<"\n"; 
    system("pause"); 
    WSACleanup(); 
    return -1; 
} 
char* addres=new char; 
cin>>addres; 

SOCKADDR_IN adr; 
adr.sin_addr.S_un.S_addr=inet_addr(addres); 
adr.sin_family=AF_INET; 
adr.sin_port=rand(); 

ICMPh icmp; 
icmp.kod=0; 
icmp.seq=htons(seq++); 
icmp.typ=8; 
icmp.suma_spr=0; 
icmp.id=htons(rand()); 

int size=32; 
char *buffer; 

buffer=new char[sizeof(ICMPh)+size]; 
memcpy_s(buffer,sizeof(ICMPh),&icmp,sizeof(ICMPh)); 
memset(buffer+sizeof(ICMPh),'x',size); 

icmp.suma_spr=htons(CalcChecksum(buffer,sizeof(ICMPh)+size)); 

memcpy_s(buffer,sizeof(ICMPh),&icmp,sizeof(ICMPh)); 

if(sendto(soc,buffer,sizeof(ICMPh)+size,0,(SOCKADDR*)&adr,sizeof(SOCKADDR_IN))==SOCKET_ERROR) 
{ 
    cout<<"FAIL at 'sendto':\n"; 
    cout<<WSAGetLastError()<<"\n"; 
    system("pause"); 
    WSACleanup(); 
    delete []buffer; 
    return -1; 
} 
else 
    cout<<"FINE"; 
WSACleanup(); 
system("pause"); 
delete []buffer; 
return 0; 
} 

这里是问题。一切工作正常,直到sendto()函数。我得到一个10013错误代码的形式WSAGetLastError()这意味着WSAEACCES Permission denied
我开始这个应用程序巫管理员privliges,所以我不知道为什么我不能使用这个插槽的配置,发送数据。

回答

2

对于sendto(),WSAEACCES与用户权限无关。如果您没有足够的权利使用RAW套接字,您将在socket()上得到错误。 Read the documentation。当sendto()报告WSAEACCES时,表示您的sockaddr_in结构未正确填写。我在您的代码中看到三个与此相关的错误:

1)在使用它之前,您没有清零sockaddr_in。这么做很重要。

2)您分配1个字符的缓冲器以接收来自用户的目标地址。对于IPv4地址(包括空终止符),缓冲区需要为16个字符。所以你有一个缓冲区溢出。

3)分配sin_port字段时,您不会调用htons()