2012-01-10 11 views
6

Po przypisaniu tego adresu jest to cannot assign requested address. Ale kiedy umieszczę adres lokalny (127.0.0.1), akceptuje go. Czemu???Wystąpił błąd w czasie wykonywania, który "Nie można przypisać żądanego adresu" w języku C pod Linuksem (Centos)

char* hostname = "192.168.1.8"; 

int sockfd; 
struct sockaddr_in my_addr; // my address information 
struct sockaddr_in their_addr; // connector's address information 
socklen_t addr_len; 
int numbytes; 
char buf[MAXBUFLEN]; 
int port =5000; 

if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) { 
    perror("socket"); 
    exit(1); 
} 
try 
{ 
    my_addr.sin_family = AF_INET;  // host byte order 
    my_addr.sin_addr.s_addr = inet_addr(hostname); 

    printf("Accepted/n"); 
    // automatically fill with my IP 
    my_addr.sin_port = htons(5000); // short, network byte order 
    memset(&(my_addr.sin_zero), '\0', 8); // zero the rest of the struct 

    if (bind(sockfd, (struct sockaddr *)&my_addr, sizeof(struct sockaddr)) == -1) 
    { 
     perror("bind"); 
     exit(1); 
    } 
    while (1) 
    { 
     addr_len = sizeof(struct sockaddr); 
     if ((numbytes = recvfrom(sockfd, buf, MAXBUFLEN-1 , 0, 
      (struct sockaddr *)&their_addr, &addr_len)) == -1) { 
      perror("recvfrom"); 
      exit(1); 
     } 

     //printf("got packet from %s\n",inet_ntoa(their_addr.sin_addr)); 
     //printf("packet is %d bytes long\n",numbytes); 
     buf[numbytes] = '\0'; 
     //printf("packet contains \"%s\"\n",buf); 
    } 

    close(sockfd); 
} 
catch(...) 
{ 
+3

Prawdopodobnie ponieważ lokalny adres urządzenia nie jest 192.168.1.8? –

+2

Ponadto oznaczono to jako C, ale widzę blok "try {...} catch (...) {...}". Czy to powinno być C++? –

Odpowiedz

11

Jeśli błąd się dzieje na bind (to nie jest takie oczywiste na podstawie treści zapytania od komunikatu o błędzie stan nie pojawia się w kodzie), to może być ponieważ adres nie jest dostępny.

Zwykle jest to już używane lub niedostępne na bieżącym hoście.

Z kilkoma wyjątkami można zazwyczaj wiązać tylko adresy IP przypisane do lokalnych interfejsów. Powinieneś sprawdzić, czy 192.168.1.8 jest w tej klasie. Jest pewien, że 127.0.0.1 będzie interfejsem lokalnym (stąd dlaczego działa), i że zadziała również INADDR_ANY - to prawdopodobnie "adres", którego powinieneś użyć, chyba że masz konkretną potrzebę ograniczenia się do jednego interfejsu.

Powinieneś sprawdzić errno po awarii i dopasować go do possibilities.


Tak na marginesie, i to chyba bez znaczenia problemu, w jaki ty zainicjowania sockaddr_in struktura (ustawienie pola następnie wybić resztę) wydaje się być mniej niż przenośny do mnie.

myślę, że byłoby bezpieczniej jest usunąć wiele po prostu ustawić co chcecie po tym, coś jak:

memset (&my_addr, 0, sizeof (my_addr)); 
my_addr.sin_family  = AF_INET; 
my_addr.sin_addr.s_addr = inet_addr (hostname); 
my_addr.sin_port  = htons (5000); 

przynajmniej, że sposób, kolejność pól w strukturze nie będzie wpływać na kod.


Możesz zobaczyć problem z następującym kodem. Po pierwsze, wymagane nagłówki:

#define __USE_GNU 
#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 
#include <sys/types.h> 
#include <sys/socket.h> 
#include <netinet/in.h> 

Następnie sprawdzanie argumentów i tworzenie gniazd.

int main (int argc, char *argv[]) { 
    int sockfd; 
    struct sockaddr_in me; 

    if (argc < 2) { 
     printf ("Need argument with IP address\n"); 
     return 1; 
    } 

    if ((sockfd = socket (AF_INET, SOCK_DGRAM, 0)) == -1) { 
     perror("socket"); 
     return 1; 
    } 

Następnie wiązanie się:

memset (&me, 0, sizeof (me)); 
    me.sin_family = AF_INET; 
    me.sin_addr.s_addr = inet_addr (argv[1]); 
    me.sin_port = htons (5000); 

    if (bind (sockfd, (struct sockaddr *)&me, sizeof(struct sockaddr)) == -1) 
    { 
     fprintf (stderr, "errno = %d ", errno); 
     perror("bind"); 
     exit(1); 
    } 

    close(sockfd); 

    return 0; 
} 

Po uruchomieniu że z pewnymi argumentami, widać to działa dobrze dla tych, w których adresy IP należą do lokalnych interfejsów (127.0.0.1 i 192.168.0.101), ale nie dla tych, które tego nie robią, jak 192.168.0.102:

pax> ifconfig | grep 'inet addr' 
     inet addr:192.168.0.101 Bcast:192.168.0.255 Mask:255.255.255.0 
     inet addr:127.0.0.1       Mask:255.0.0.0 
     inet addr:192.168.99.1 Bcast:192.168.99.255 Mask:255.255.255.0 
     inet addr:192.168.72.1 Bcast:192.168.72.255 Mask:255.255.255.0 

pax> ./testprog 127.0.0.1 

pax> ./testprog 192.168.0.101 

pax> ./testprog 192.168.0.102 
errno = 99 bind: Cannot assign requested address 

pax> grep '#define.*99' /usr/include/asm-generic/errno.h 
#define  EADDRNOTAVAIL  99  /* Cannot assign requested address */ 

A z linkiem do strony bind człowieka powyżej, patrz:

EADDRNOTAVAIL
              nieistniejący interfejs został wezwany lub Żądany adres nie był miejscowy.

+0

To jest bardzo szczegółowy przegląd kodu – bn00d

Powiązane problemy