מידע רשת

gethostent#

מחזיר את הרשומה הבאה ממסד נתוני המארחים.

gethostent walks the host database - on traditional Unix systems the /etc/hosts file, on modern systems whatever NSS source is configured

  • returning one record per call until the database is exhausted. Use it when you want to enumerate every known host, not when you want to resolve a single name: gethostbyname is the right tool for a targeted lookup.

סמן האיטרציה משותף עם sethostent (שמחזיר אותו לאחור) ועם endhostent (שסוגר אותו). בין שתי הקריאות הללו gethostent מחזיר כל רשומה בסדר, ואז מחזיר את הרשימה הריקה (או undef בהקשר סקלר) ברגע שמגיעים לסוף מסד הנתונים.

תקציר#

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

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

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

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

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

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

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

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

בסוף מסד הנתונים ההחזרה היא רשימה ריקה. הבחנה שכדאי לזכור: ההערה ב־perlfunc של upstream שרשומה חסרה עשויה להחזיר ״ערך אמת בודד וחסר משמעות״ חלה על חיפושים לפי שם ולפי כתובת, לא על gethostent - איטרציה מעבר לסוף היא רשימה ריקה נקייה.

הקשר סקלר - רק ה־$name הקנוני, או undef בסוף מסד הנתונים. השתמשו בהקשר רשימה בכל פעם שאתם צריכים משהו מעבר לשם; שחזור השדות האחרים אינו אפשרי בדיעבד.

המירו כתובת ארוזה מתוך @addrs באמצעות Socket::inet_ntoa עבור IPv4 או באמצעות unpack ישירות:

use Socket;
print inet_ntoa($addrs[0]), "\n";

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

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

  • $? - נקבע לערך h_errno של C במקרה של כשל, היכן שהפלטפורמה חושפת אותו. סוף־מסד־נתונים רגיל אינו כשל ומותיר את $? ללא שינוי.

  • $! - gethostent הוא איטרטור על מסד נתונים, לא עטיפת syscall במובן של open/read. שגיאות DNS ו־NSS צפות דרך h_errno (דרך $?), לא דרך $!.

דוגמאות#

מנו כל מארח במסד הנתונים:

use Socket;
sethostent(1);
while (my ($name, $aliases, $type, $len, @addrs) = gethostent) {
    my @dotted = map { inet_ntoa($_) } @addrs;
    print "$name  @dotted\n";
}
endhostent;

הקשר סקלר - רשמו רק את השמות הקנוניים:

sethostent(0);
while (defined(my $name = gethostent)) {
    print "$name\n";
}
endhostent;

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

use Socket;
my %ip_of;
sethostent(1);
while (my ($name, $aliases, undef, undef, @addrs) = gethostent) {
    next unless @addrs;
    $ip_of{$name} = inet_ntoa($addrs[0]);
    $ip_of{$_}    = inet_ntoa($addrs[0]) for split ' ', $aliases;
}
endhostent;

print $ip_of{"localhost"} // "not in hosts DB", "\n";

ממשק לפי־רשומה דרך עקיפת Net::hostent - מתודות accessor במקום פירוק מיקומי:

use Net::hostent;
while (my $h = gethostent) {
    printf "%-30s %s\n", $h->name, join(",", @{$h->aliases});
}

מקרי קצה#

  • אין הפניה לאחור משתמעת. gethostent אינו פותח או מחזיר לאחור את מסד הנתונים בעצמו. הקריאה הראשונה לאחר תחילת התוכנית עובדת מפני שספריית C פותחת את מסד הנתונים בעצלתיים, אך ברגע שמגיעים לסוף, קריאות נוספות ממשיכות להחזיר סוף־מסד־נתונים עד ש־sethostent מחזיר את הסמן לאחור. תמיד צמדו מנייה ל־sethostent / endhostent מפורשים.

  • ארגומנט STAYOPEN ל־sethostent. העברת ערך אמת מבקשת מהספרייה להשאיר את קובץ מסד הנתונים פתוח לאורך החיפושים, מה שחשוב למקורות NSS שאחרת היו מתחברים מחדש בכל קריאה. העברת 0 מתירה לספרייה לסגור ולפתוח מחדש בין קריאות.

  • סוף־מסד־נתונים הוא רשימה ריקה, לא undef. בהקשר רשימה תנאי הלולאה while (my @r = gethostent) עובד מפני שרשימה ריקה היא שקר. בהקשר סקלר השתמשו ב־while (defined(my $name = gethostent)) - שם מארח "0" תקף תיאורטית והיה מסיים שגויות לולאה מבוססת־אמיתיות.

  • @addrs עלול להיות ריק גם עבור רשומה שמוחזרת בחלק מ־backends של NSS. הגנו על שלב פירוק־הכתובת:

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

  • ערבוב מקורות NSS. במערכות מבוססות glibc מסד נתוני המארחים עשוי לשאוב מ־/etc/hosts, DNS, mDNS, ומודולי NSS אחרים, בהתאם ל־nsswitch.conf. מודולי NSS מבוססי־DNS בדרך־כלל אינם מבצעים מנייה - gethostent כנגד מסד נתוני מארחים מבוסס־DNS בלבד מחזיר את הרשימה הריקה מיידית. ברוב הפריסות האמיתיות רק מקור files תורם רשומות לאיטרציה.

  • שילוב עם חיפושים לפי שם / לפי כתובת. קריאה ל־gethostbyname או ל־gethostbyaddr יכולה לאפס את הסמן המשותף. סיימו את האיטרציה תחילה, או הפעילו אותה מחדש עם sethostent לאחר החיפוש.

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

הבדלים מ־upstream#

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

ראו גם#

  • sethostent - מחזיר את האיטרטור לאחור ושולט האם מסד הנתונים נשאר פתוח לאורך הקריאות

  • endhostent - סוגר את האיטרטור ומשחרר את ה־handle של מסד הנתונים

  • gethostbyname - חיפוש ממוקד לפי שם במקום מנייה מלאה

  • gethostbyaddr - חיפוש הפוך ממוקד לפי כתובת ארוזה

  • getnetent - אותה תבנית איטרציה עבור מסד נתוני הרשתות

  • Socket::inet_ntoa - הופך כתובת ארוזה מתוך @addrs למחרוזת dotted-quad