2013-07-03 3 views
1

Я новичок в сырых сокетах. Раньше я работал над сокетами, но я никогда ничего не делал с сырыми сокетами. Я получаю сообщение об ошибке # 10049 -> WSAEADDRNOTAVAIL "Невозможно назначить запрошенный адрес" @ "sendto"Использование исходных сокетов (C++)

Надеюсь, что вы можете мне помочь!

мой код:

#include <WinSock2.h> 
#include <stdio.h> 

typedef unsigned char U8; 
typedef unsigned short U16; 

struct ipheader 
{ 
    U8 length : 4;// : 4; 
    U8 version : 4; 

    U8 differentiated_services_field; 
    U16 total_length; 
    U16 ident; 
    U16 fragment; // fragment offset // first 8 bit = flags not 8 bit 
    U8 ttl; // time to live 
    U8 protocol; 
    U16 checksum; 
    in_addr src; 
    in_addr dst; 
}; 

struct udpheader 
{ 
    U16 srcport; 
    U16 dstport; 
    U16 length; 
    U16 checksum; 
}; 


#define CON_SERVER_IP   "127.0.0.1" 
#define CON_SERVER_PORT   1234 

#define MY_PORT     9191 
#define MY_IP     "127.0.0.1" 

#define DATA_LENGTH 16 
#define WHOLE_LENGTH (20+8+DATA_LENGTH) 

// http://www.c-worker.ch/tuts/raw_icmp.php 
unsigned short Checksum(unsigned short *p_usBuffer,int iSize) 
{ 
    unsigned long lCheckSum = 0; 
    while(iSize > 1) 
    { 
     lCheckSum += *p_usBuffer++; 
     iSize -= sizeof(unsigned short); 
    } 
    if(iSize) 
     lCheckSum += *(unsigned char*)p_usBuffer; // + 0 entfällt, da überflüßig 
    lCheckSum = ((lCheckSum >> 16) + (lCheckSum & 0xffff)) + (lCheckSum >> 16); 
    return (unsigned short)(~lCheckSum); 
} 
int main(int argc,char* argv[]) 
{ 
    WSADATA wsa; 
    WSAStartup(MAKEWORD(2,0),&wsa); 

    char packet[WHOLE_LENGTH]; 

    ZeroMemory(packet,WHOLE_LENGTH); 

    ipheader* pIpHeader = (ipheader*)&packet; 
    udpheader* pUDPHeader = (udpheader*) &packet + sizeof(ipheader); 

    SOCKADDR_IN sAddr; 
    ZeroMemory(&sAddr,sizeof(SOCKADDR_IN)); 
    sAddr.sin_family = AF_INET; 
    sAddr.sin_port = htons(CON_SERVER_PORT); 
sAddr.sin_addr.s_addr = inet_addr(CON_SERVER_IP); // thank you BevynQ 

    pIpHeader->length = 5; 
    pIpHeader->version = 4; 
    pIpHeader->differentiated_services_field = 0; 
    pIpHeader->total_length = sizeof(ipheader) + sizeof(udpheader) + DATA_LENGTH; 
    pIpHeader->ident = htonl(54321); 
    pIpHeader->fragment = 0; 
    pIpHeader->ttl = 65; 
    pIpHeader->protocol = IPPROTO_UDP; 
    pIpHeader->checksum = 0; 
    pIpHeader->src.s_addr = inet_addr(MY_IP); 
    pIpHeader->dst.s_addr = inet_addr(CON_SERVER_IP); 

    pUDPHeader->srcport = htons(MY_PORT); 
    pUDPHeader->dstport = htons(CON_SERVER_PORT); 
    pUDPHeader->length = sizeof(udpheader) + DATA_LENGTH; 
    pUDPHeader->checksum = 0; 

    strcpy(packet+sizeof(ipheader)+sizeof(udpheader),"Lets go\n"); 

    pUDPHeader->checksum = Checksum((unsigned short*)packet+sizeof(ipheader),sizeof(udpheader)+DATA_LENGTH); 

    pIpHeader->checksum = Checksum((unsigned short*)packet,WHOLE_LENGTH); 

    printf("UDPHeader checksum:\t0x%04X\n",pUDPHeader->checksum); 
    printf("IPHeader checksum:\t0x%04X\n",pIpHeader->checksum); 


    SOCKET sock = socket(AF_INET,SOCK_RAW,IPPROTO_RAW); 
    if(sock == INVALID_SOCKET) 
    { 
     printf("socket generation failed (%d)\n",WSAGetLastError()); 
     goto q1; 
    } 

    int i = sendto(sock,packet,WHOLE_LENGTH,0,(SOCKADDR*)&sAddr,sizeof(SOCKADDR_IN)); 
    printf("sendto: %i (%d)\n",i,WSAGetLastError()); 
q1: 
    printf("\n\n\n\nDone\n"); 
    getchar(); 
    return 0; 
} 

Edit: Ошибка не встречающийся больше, но нет никакой связи установлено. Я снова займусь этим завтра. Благодарим за помощь!

Редактировать2: пакет не может быть отправлен, поскольку параметр IP_HDRINCL не установлен. Делая это, она работает;)

+0

выглядит как будто вы только настройки порта. вам также нужно установить IP-адрес. – BevynQ

+0

Как предложение, вы должны попробовать [libtins] (http://libtins.sourceforge.net/). Он обрабатывает внутренние сокеты и внутренние интерфейсы протоколов для вас. – mfontanini

+0

Спасибо BevynQ. Я добавил его на свой пост и исправил указатели (& пакет). – TaTaTa

ответ

0

попробовать

SOCKADDR_IN sAddr; 
ZeroMemory(&sAddr,sizeof(SOCKADDR_IN)); 
sAddr.sin_family = AF_INET; 
sAddr.sin_port = htons(CON_SERVER_PORT); 
inet_pton(AF_INET, CON_SERVER_IP, &sAddr.sin_addr);