מידע רשת

getservent#

קריאת הרשומה הבאה ממסד נתוני השירותים של המערכת.

getservent עובר על מסד הנתונים /etc/services רשומה אחת בכל פעם, ומניב את אותה רשימת שדות כמו getservbyname ו־getservbyport אך ללא מפתח חיפוש. כל קריאה מקדמת סמן פנימי; הסמן נפתח בקריאה הראשונה, מוחזר לאחור על־ידי setservent, ומשוחרר על־ידי endservent. הוא משקף את שגרת ספריית C של POSIX getservent(3) ויורש כל מוזרות ניידות שזה מצריך.

תקציר#

my ($name, $aliases, $port, $proto) = getservent;
my $name = getservent;        # scalar context

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

בהקשר רשימה, ארבעה שדות התואמים את הסדר המתועד עבור כל וריאנט getserv*:

  • $name - שם שירות קנוני, לדוגמה "http".

  • $aliases - מחרוזת מופרדת ברווחים של שמות חלופיים, לדוגמה "www www-http". לא מערך; פצלו אותה בעצמכם אם אתם זקוקים לכזה.

  • $port - מספר פורט כמספר שלם מקומי (סדר בתים של מארח), לדוגמה 80.

  • $proto - פרוטוקול תעבורה, בדרך כלל "tcp" או "udp".

בהקשר סקלר, רק $name. כאשר הסמן מגיע לסוף הקובץ, getservent מחזיר את הרשימה הריקה בהקשר רשימה ו־undef בהקשר סקלר - לולאת while (my @e = getservent) הניבית נסמכת על כך.

כדי להמיר את הכינויים לרשימה:

my @alt = split / /, $aliases;

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

  • סמן מסד נתונים פנימי עבור /etc/services - משותף עם getservbyname, getservbyport, setservent ו־endservent. כל חיפוש לפי־שם או לפי־פורט בפלטפורמות מסוימות מחזיר לאחור או סוגר את הסמן הזה כתופעת לוואי; איטרו בלולאה צמודה או עטפו את האיטרציה ב־setservent / endservent למען הביטחון.

  • $! - נקבע כאשר קריאת ה־C הבסיסית מדווחת על שגיאה.

  • אינו בטוח־thread. getservent שומר מצב לכל־תהליך, לא לכל־thread; שני threads המאיטרים בו־זמנית ישלבו רשומות ואף אחד מהם לא יראה את הרשימה המלאה.

דוגמאות#

מעבר על מסד נתוני השירותים המלא והדפסת כל רשומה:

while (my ($name, $aliases, $port, $proto) = getservent) {
    print "$name/$proto $port\n";
}
endservent;

איפוס הסמן לפני האיטרציה כך שקריאות מוקדמות במקומות אחרים בתוכנית לא יוכלו להשאיר אותו באמצע־הזרם:

setservent(0);
while (my @e = getservent) {
    # @e is ($name, $aliases, $port, $proto)
}
endservent;

איסוף שירותי TCP בלבד לתוך האש שמפתחו הוא הפורט:

my %tcp;
while (my ($name, undef, $port, $proto) = getservent) {
    $tcp{$port} = $name if $proto eq 'tcp';
}
endservent;

השתמשו בממשק מונחה־עצמים לפי־שם מ־Net::servent, אשר עוקף את ה־built-in ומחזיר עצם blessed עם מתודות accessor:

use Net::servent;
while (my $s = getservent) {
    printf "%-20s %5d/%s\n", $s->name, $s->port, $s->proto;
}

מקרי קצה#

  • סוף קובץ מחזיר ריק / undef, לא שגיאה. ערך שקר סקלרי יחיד בהקשר רשימה (my @e = getservent המניב רשימה ריקה) הוא הסיומת. אל תבדקו את $! כדי לאתר סוף איטרציה.

  • /etc/services חסר: במערכות ללא הקובץ, הקריאה הראשונה מחזירה את הרשימה הריקה מיד ו־$! נקבע. שום דבר בקריאה אינו מאותת על ההבדל בין מסד נתונים ריק לבין חסר - בדקו את $! לפני שתניחו שמסד הנתונים היה פשוט ריק.

  • שיתוף סמן עם חיפושים לפי־שם / לפי־פורט: קריאה ל־getservbyname או getservbyport באמצע לולאת getservent עלולה לאפס את הסמן בפלטפורמות מסוימות. סיימו את המעבר תחילה או פתחו מחדש עם setservent.

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

  • תוכניות מבוססות־threads: האיטרציה היא לכל־תהליך. תאמו גישה עם מנעול, או העדיפו getservbyname / getservbyport לשאילתות נקודתיות בקוד מבוסס־threads.

  • הקשר סקלר מחזיר רק את השם. אם אתם זקוקים לפורט, קראו בהקשר רשימה גם כאשר אכפת לכם רק משדה אחד.

הבדלים מ־upstream#

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

ראו גם#

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

  • getservbyport - חיפוש שירות יחיד לפי הפורט המספרי שלו

  • setservent - החזרת הסמן המשותף לאחור לפני האיטרציה כך שקריאות קודמות לא יוכלו להשאיר אותו באמצע־הזרם

  • endservent - שחרור הסמן כאשר המעבר הסתיים, ושחרור file descriptor הבסיסי

  • getprotoent - אותה תבנית איטרטור עבור /etc/protocols, בדרך כלל מזווג בפתרון tuple של (port, proto)

  • Net::servent - עטיפה מונחית־עצמים שה־accessors שלה מסירים את הצורך לזכור את סדר השדות