מידע רשת

gethostbyname#

חיפוש רשומת מארח לפי שם DNS.

gethostbyname מפענח שם מארח לכתובת IP שלו (או יותר) ולרשומה הקנונית באמצעות קריאה לשגרת C gethostbyname(3) של המערכת. מקרה השימוש האופייני - ״תן לי את ה־IP הארוז של המארח הזה״ - דורש את הצורה בהקשר סקלר ותו לא. הצורה בהקשר רשימה חושפת את רשומת המארח המלאה: שם קנוני, כינויים, משפחת כתובות, אורך כתובת, וכל כתובת רשומה.

תקציר#

my $packed_ip = gethostbyname $name;
my ($name, $aliases, $addrtype, $length, @addrs) = gethostbyname $name;

מה מקבלים בחזרה#

הקשר סקלר - כתובת ה־IP הראשונה כמחרוזת בינארית ארוזה (ארבעה בתים ל־IPv4, שישה־עשר ל־IPv6), או undef אם החיפוש נכשל. המרה ל־dotted-quad באמצעות Socket::inet_ntoa:

use Socket;
my $packed = gethostbyname("www.perl.org");
my $dotted = inet_ntoa($packed) if defined $packed;

הקשר רשימה - רשימה בת חמישה איברים המשקפת את struct hostent של C:

  • $name - שם המארח הקנוני.

  • $aliases - מחרוזת של שמות חלופיים מופרדים ברווח.

  • $addrtype - משפחת הכתובות, בדרך כלל AF_INET (2) או AF_INET6 (10).

  • $length - אורך כל כתובת בבתים (4 ל־IPv4, 16 ל־IPv6).

  • @addrs - כל כתובת שהוחזרה עבור השם, כל אחת מחרוזת בינארית ארוזה של $length בתים.

בכישלון חיפוש בהקשר רשימה, הערך המוחזר הוא הרשימה הריקה.

מצב גלובלי שהוא נוגע בו#

  • $? - נקבע לערך h_errno של C בכישלון, כאשר הפלטפורמה חושפת אותו. בדיקה באמצעות $? != 0 כדי להבחין בין ״אין מארח כזה״ (HOST_NOT_FOUND) ל״נסה שוב״ (TRY_AGAIN) וכדומה.

  • סמן האיטרציה של מסד נתוני המארחים המשותף עם gethostent, sethostent ו־endhostent. קריאה ל־gethostbyname עשויה לאפס סמן שהושאר פתוח על־ידי gethostent.

דוגמאות#

צורת סקלר - המקרה הנפוץ:

use Socket;
my $packed = gethostbyname("localhost");
defined $packed or die "cannot resolve localhost: $!";
print inet_ntoa($packed), "\n";      # 127.0.0.1

צורת רשימה - מנייה של כל כתובת עבור מארח רב־ביתי:

use Socket;
my ($name, $aliases, $type, $len, @addrs) = gethostbyname("www.example.com");
for my $addr (@addrs) {
    print inet_ntoa($addr), "\n";
}

פירוק כתובת IPv4 ידנית, ללא Socket:

my $packed = gethostbyname("127.0.0.1");
my ($a, $b, $c, $d) = unpack("W4", $packed);
print "$a.$b.$c.$d\n";               # 127.0.0.1

קדימה ואז לאחור - פענוח שם, ואז חיפוש הכתובת בחזרה:

use Socket;
my $packed = gethostbyname("www.perl.org");
my $back   = gethostbyaddr($packed, AF_INET);
print "$back\n";

ממשק לפי שם באמצעות עקיפת Net::hostent - מתודות accessor במקום פירוק מיקומי:

use Net::hostent;
my $h = gethostbyname("www.perl.org");
print $h->name, " ", join(",", @{$h->aliases}), "\n";

מקרי קצה#

  • יש לקרוא תמיד בהקשר סקלר כאשר רוצים ״את ה־IP״. הצורה בהקשר רשימה לעולם אינה מה שפותר מהיר רוצה, ומקצה ארבעה ערכי החזרה נוספים. תיעוד ה־upstream מציין זאת במפורש: ”Make sure gethostbyname is called in SCALAR context and that its return value is checked for definedness.“

  • יש לבדוק undef בצורת סקלר. חיפוש שנכשל מחזיר undef, לא מחרוזת ריקה. כתובת 0.0.0.0 מילולית, לעומת זאת, היא מחרוזת ארוזה תקפה בת ארבעה בתים, ומומרת למחרוזת בית־האפס, לא ל־undef.

  • @addrs עשוי להיות ריק בהקשר רשימה גם כאשר ארבעת ערכי ההחזרה הראשונים מוגדרים - חלק מהפותרים מייצרים רשומה ללא כתובות. תמיד לעבור איטרציה, לא לאנדקס [0] בעיוורון.

  • הכינויים הם סקלר אחד, לא רשימה. $aliases הוא מחרוזת יחידה מופרדת ברווחים. יש לפצל על רווח לבן אם נדרשת רשימה.

  • מחרוזות IP מספריות מתקבלות. העברת "127.0.0.1" מחזירה את הצורה הארוזה של הכתובת ללא נסיעה הלוך־ושוב ל־DNS - הפותר מקצר עבור קלט מספרי.

  • IPv6. gethostbyname מתשאל רק את משפחת הכתובות IPv4 (AF_INET). לפענוח dual-stack יש להשתמש ב־Socket::getaddrinfo, המחזיר רשומות עבור כל משפחת כתובות שהמארח מציע.

  • בטיחות thread. שגרת ה־C הבסיסית שומרת מצב סטטי לכל־תהליך עבור סמן המארח. קריאות במקביל ממספר threads עשויות לשלב תוצאות. סקריפטים הזקוקים לפענוח בטוח־thread צריכים להשתמש ב־Socket::getaddrinfo.

  • h_errno מול $!. כישלונות DNS קובעים את h_errno (חשוף דרך $?), לא errno / $!. בדיקת $! לאחר gethostbyname שנכשל היא חסרת משמעות.

הבדלים מ־upstream#

תואם מלא ל־upstream Perl 5.42.

ראו גם#

  • gethostbyaddr - החיפוש ההפוך: כתובת ארוזה ← רשומת מארח

  • gethostent - איטרציה על כל רשומה במסד נתוני המארחים במקום חיפוש שם אחד

  • sethostent - החזרת איטרטור המארחים לתחילה ובקרה האם הקובץ נשאר פתוח בין חיפושים

  • Socket::inet_ntoa - הופך את תוצאת הקשר־הסקלר הארוזה למחרוזת dotted-quad

  • Socket::inet_aton - עוזר טהור משם־לארוז כאשר אין צורך ברשומת המארח המלאה

  • unpack - פענוח ידני של הכתובת הארוזה כאשר Socket אינו זמין