سؤال

لدي (حسب ما أستطيع قوله) إعداد Linux يعمل بشكل مثالي (Ubuntu 8.04) حيث تكون جميع الأدوات (nslookup، وcurl، وwget، وfirefox، وما إلى ذلك) قادرة على حل العناوين.ومع ذلك، يفشل التعليمة البرمجية التالية:

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

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

لقد تأكدت من الأمور التالية:

  • يستطيع Perl حل العناوين باستخدام gethostbyname (أي يعمل الكود أدناه):

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

  • يعمل كود المصدر الأصلي ضمن Windows

  • هذه هي الطريقة التي من المفترض أن تعمل (أي.يجب أن يحل أسماء المضيفين)، نظرًا لأن LWP يحاول استخدام هذا السلوك (في الحقيقة لقد عثرت على المشكلة من خلال محاولة تصحيح سبب عدم عمل LWP بالنسبة لي)
  • لا يؤدي تشغيل البرنامج النصي إلى إرسال طلبات DNS (لذلك لا يحاول حتى حل الاسم).تم التحقق باستخدام Wireshark
هل كانت مفيدة؟

المحلول

من نظرة سريعة، الكود التالي من 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;
}

يقترح (إذا نظرت إلى المتصل بهذا الرمز) الحل البديل للإضافة MultiHomed => 1, إلى الكود الخاص بك.

بدون هذا الحل البديل، يبدو أن الكود أعلاه يحاول الاتصال inet_aton("hostname.com") باستخدام inet_aton() من المقبس.pm.هذا يعمل بالنسبة لي في كل من Win32 وUnix، لذلك أعتقد أن هذا هو المكان الذي يكمن فيه الكسر بالنسبة لك.

يرى المقبس.xs للكود المصدر لـ 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 );
        }
    }

يبدو أن Perl gethostbyname() يعمل بشكل أفضل من C gethostbyname() بالنسبة لك.

نصائح أخرى

هل يمكن أن تخبرنا بالضبط كيف فشل التعليمات البرمجية الخاصة بك؟لديك رمز التحقق من الخطأ ولكنك لم تبلغ عن الخطأ!

لقد قمت للتو بتجربة الكود الأصلي (مع إضافة "استخدام IO::Socket::INET" على جهاز Mac OS X وهو يعمل بشكل جيد.

أظن أن خيار Multihomed يعد اختراقًا غير ضروري وأن هناك مشكلة أخرى هي السبب الجذري لمشكلتك.

تأكد من أن لديك البيان

use IO::Socket::INET;

في بداية التعليمات البرمجية المصدر الخاصة بك.إذا تركت هذا خارجًا، فمن المحتمل أنك تتلقى رسالة الخطأ:

لا يمكن تحديد موقع الكائن "الجديد" عبر الحزمة "io :: socket :: inet"

علاوة على ذلك، يمكنك التحقق من أن DNS يعمل باستخدام Net::DNS::Resoler، راجع المزيد من المعلومات هنا.

use Net::DNS;

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

# Perform a lookup, using the searchlist if appropriate.
my $answer = $res->search('example.com');
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top