2012-06-10 243 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()