2012-07-12 15 views
7

için IPv4/IPv6 adresi ve port ayarı (IPv4 ve IPv6 ile çalışması gerekir). Şimdi, nerede olursam sockaddr_storage kullanıyorum, ancak şimdi bir sockaddr_storage'u ayarlamak zorundayım. Ama doğru yolun ne olduğunu bilmiyorum. Önceki kod oldu: Bu eski tarzıdır Görüldüğü üzere (IPv4 kullandığı)Ben <strong>AF-bağımsız</strong> kod tabanına bir <strong>IPv4</strong> uygulamayı taşıma ediyorum bir sockaddr_storage'ın yapıya

void DataSocket::SetLocalAddr(const char *addr, const int port) 
{ 
    this->laddr.sin_port = htons(port); 
    if(addr != NULL) 
     this->laddr.sin_addr.s_addr = inet_addr(addr); 
    else 
     this->laddr.sin_addr.s_addr = inet_addr("0.0.0.0"); 
} 

:

// defined in data_socket.h 
struct sockaddr_in laddr; 

Şimdi sin_port sin_addr ve setleri bu fonksiyon yoktur.

Artık değişikliklerim aşağıda. GetAddrFamily() olduğunda

void DataSocket::SetLocalAddr(const char *addr, const int port) 
{ 
switch (this->GetAddrFamily(addr)) { 
    case AF_INET: 
     (struct sockaddr_in *) this->laddr.sin_port = htons(port); 
     if(addr != NULL) 
      inet_pton(AF_INET, addr, (struct sockaddr_in *) this->laddr.sin_addr); 
     else 
      inet_pton(AF_INET, "0.0.0.0", (struct sockaddr_in *) this->laddr.sin_addr); 
     break; 

    case AF_INET6: 
     (struct sockaddr_in6 *) this->laddr.sin6_port = htons(port); 
     if(addr != NULL) 
      inet_pton(AF_INET6, addr, (struct sockaddr_in6 *) this->laddr.sin6_addr); 
     else 
      inet_pton(AF_INET6, "0:0:0:0:0:0:0:0", (struct sockaddr_in6 *) this->laddr.sin6_addr); 
     break; 

    default: 
     return NULL; 

} 

}

: Önce sockaddr_in Sonra sockaddr_storage

// defined in data_socket.h 
struct sockaddr_storage laddr; 

için değiştirdik ben desteklemek için yukarıdaki IPv4 ve IPv6 kod değişti :

int DataSocket::GetAddrFamily(const char *addr) 
{ 
    struct addrinfo hints, *res; 
    int status, result; 

    memset(&hints, 0, sizeof(hints)); 
    hints.ai_family = AF_UNSPEC; 
    hints.ai_socktype = SOCK_STREAM; 

    if ((status = getaddrinfo(addr, 0, &hints, &res)) != 0) 
    { 
     fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(status)); 
     return false; 
    } 

    result = res->ai_family; // This might be AF_INET, AF_INET6,etc.. 
    freeaddrinfo(res); // We're done with res, free it up 

    return result; 
} 

Benim yolum karmaşık gibi görünüyor. Bunu yapmanın doğru yolu bu mu? Burada örneğin, Getting IPV4 address from a sockaddr structure

Ben iyi çözümü bulmaya çalışıyorum: ben değiştim Çünkü sockaddr_in aslında sadece bu sorunun tersini istiyorum sockaddr_storage için http://www.kame.net/newsletter/19980604/ o inet_ntop() ve inet_pton() Ancak bazıları hiç kullanmıyorum diyor (Beej'in ağ öğreticisi gibi) inet_ntop() ve inet_pton()'un IPv6 tabanlı bir uygulama için kullanılması gerektiğini söylüyor.

Uygulama biçimim doğru mu, yoksa değiştirmeli miyim?

+1

Bu bir nedeni :: address_v6'. – Chad

+1

C üye fonksiyonlarını kazandığında bana haber ver. – Puppy

+0

@DeadMG, "c" etiketi için özür dileriz –

cevap

5

ederim getaddrinfo örneğin ağır işleri yapmasına izin öneriyoruz. Ben `gibi :: asio :: ip :: address`, uzak` artırmak `:: asio :: ip :: address_v4` artırmak ve özetler :: asio :: ip artırmak neden

void DataSocket::SetLocalAddr(const char *addr, const unsigned short int port) 
{ 
    struct addrinfo hints, *res; 
    int status; 
    char port_buffer[6]; 

    sprintf(port_buffer, "%hu", port); 

    memset(&hints, 0, sizeof(hints)); 
    hints.ai_family = AF_UNSPEC; 
    hints.ai_socktype = SOCK_STREAM; 
    /* Setting AI_PASSIVE will give you a wildcard address if addr is NULL */ 
    hints.ai_flags = AI_NUMERICHOST | AI_NUMERICSERV | AI_PASSIVE; 

    if ((status = getaddrinfo(addr, port_buffer, &hints, &res) != 0) 
    { 
     fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(status)); 
     return; 
    } 

    /* Note, we're taking the first valid address, there may be more than one */ 
    memcpy(&this->laddr, res->ai_addr, res->ai_addrlen); 

    freeaddrinfo(res); 
} 
+0

Kod için teşekkürler. Ama ben 'memcpy (& bu-> laddr, res-> ai_addr, res-> ai_addrlen) satırıyla karıştırıldım. "Res-> ai_addr" bir sockaddr yapısıdır, sanırım otomatik olarak "sockaddr_in" veya "sockaddr_in6" 'ya dönüştürülür? Bu “laddr” içine nasıl saklanır (çünkü bu “laddr” bir “sockaddr_storage” yapısıdır)? –

+0

Ve sanırım 'getaddrinfo' içinde 'port'un port_buffer'instead'i kullanmalıyım, çünkü getaddrinfo()' bir const char * (aka string) istisnadır? –

+1

'res-> ai_addr',' sockaddr_in' veya 'sockaddr_in6' gibi' struct sockaddr' türlerinin bazı varyasyonlarını işaret eder. Dönüşüm gerçekleşmiyor, yapı sadece olduğu gibi kopyalanıyor. 'struct sockaddr_storage', hepsinin ortak bir üstbilgiyi paylaştığı "sockaddr" değişkenlerinden herhangi birine dönüştürülmesine izin veren bir boyut ve düzenden ibarettir. re: bir dize bağlantı noktası olarak geçirme, rahatsız etmem, ama bu senin kodun. (Ayrıca, sabit yazım hatası, getaddrinfo tampon olması gerekiyordu) – Hasturkun

1

Eğer doğru anlıyorsam this ilk üyeye gönderiliyorsunuz? Bunu yapma, üye ismini ver.

{ 
struct sockaddr_in * in4 = reinterpret_cast< struct sockaddr_in * >(&this->addr); 
in4->laddr.sin_port = htons(port); 
... etc 
} 

An bunun için C C++ ve olmadıklarından, kullanımı:

Ben de bir şey gibi {} kapsam ve vakaların ikisi için yerel bir değişken tanıtarak okunmasını kolaylaştıracak C++ stili dökümler. C++ 'daki C stili dökümler çok belirsiz.

İlgili konular