Domanda

Ho una (da quello che posso dire) una configurazione Linux perfettamente funzionante (Ubuntu 8.04) in cui tutti gli strumenti (nslookup, curl, wget, firefox, ecc.) sono in grado di risolvere gli indirizzi. Tuttavia, il seguente codice ha esito negativo:

$s = new IO::Socket::INET(
    PeerAddr => 'stackoverflow.com',
    PeerPort => 80,
    Proto => 'tcp',
);

die "Error: $!\n" unless $s;

Ho verificato le seguenti cose:

  • Perl è in grado di risolvere gli indirizzi con gethostbyname (ovvero il codice seguente funziona):

    my $ ret = gethostbyname ('stackoverflow.com'); stampa inet_ntoa ($ ret);

  • Il codice sorgente originale funziona su Windows

  • Ecco come dovrebbe funzionare (cioè dovrebbe risolvere i nomi host), dal momento che LWP cerca di usare questo comportamento (in effetti mi sono imbattuto nel problema cercando di eseguire il debug del motivo per cui LWP non funzionava per me)
  • L'esecuzione dello script non emette richieste DNS (quindi non tenta nemmeno di risolvere il nome). Verificato con Wireshark
È stato utile?

Soluzione

Da una rapida occhiata, il seguente codice da IO :: Socket :: INET

sub _get_addr {
    my($sock,$addr_str, $multi) = @_;
    my @addr;
    if ($multi && $addr_str !~ /^\d+(?:\.\d+){3}$/) {
        (undef, undef, undef, undef, @addr) = gethostbyname($addr_str);
    } else {
        my $h = inet_aton($addr_str);
        push(@addr, $h) if defined $h;
    }
    @addr;
}

suggerisce (se guardi il chiamante di questo codice) la soluzione per aggiungere MultiHomed = > 1, al tuo codice.

Senza questa soluzione alternativa, il codice sopra riportato sembra tentare di chiamare inet_aton (" hostname.com ") utilizzando inet_aton () da Socket.pm. Questo funziona per me sia in Win32 che in Unix, quindi immagino che sia qui che si trova la rottura per te.

Vedi Socket.xs per il codice sorgente di inet_aton :

void
inet_aton(host)
    char *  host
    CODE:
    {
        struct in_addr ip_address;
        struct hostent * phe;

        if (phe = gethostbyname(host)) {
            Copy( phe->h_addr, &ip_address, phe->h_length, char );
        } else {
            ip_address.s_addr = inet_addr(host);
        }

        ST(0) = sv_newmortal();
        if(ip_address.s_addr != INADDR_NONE) {
            sv_setpvn( ST(0), (char *)&ip_address, sizeof ip_address );
        }
    }

Sembra che Perhost gethostbyname () funzioni meglio di C gethostbyname () per te.

Altri suggerimenti

Potresti forse dirci esattamente come il tuo codice fallisce? C'è un codice di controllo degli errori lì dentro ma non hai segnalato qual è l'errore!

Ho appena provato il codice originale (con l'aggiunta di " usa IO :: Socket :: INET " sul mio computer Mac OS X e funziona benissimo.

Sospetto che l'opzione Multihomed sia un hack non necessario e che qualche altro problema sia la causa principale del tuo problema.

Assicurati di avere la dichiarazione

use IO::Socket::INET;

All'inizio del codice sorgente. Se lo lasci fuori, probabilmente stai ricevendo il messaggio di errore:

  

Impossibile individuare il metodo oggetto " new " attraverso   pacchetto " IO :: Socket :: INET "

Oltre a ciò potresti verificare che DNS stia funzionando usando Net :: DNS :: Resoler, vedi maggiori informazioni qui .

use Net::DNS;

my $res = Net::DNS::Resolver->new;

# Perform a lookup, using the searchlist if appropriate.
my $answer = $res->search('example.com');
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top