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
gethostbynameis 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-quadSocket::inet_aton- עוזר טהור משם־לארוז כאשר אין צורך ברשומת המארח המלאה