Πληροφορίες δικτύου

getservbyname#

Αναζητά μια υπηρεσία δικτύου με βάση το κειμενικό όνομα και το πρωτόκολλό της.

Η getservbyname συμβουλεύεται τη βάση δεδομένων υπηρεσιών του συστήματος (τυπικά /etc/services, ή ό,τι το nsswitch.conf δρομολογεί ως πηγή services) και επιστρέφει την εγγραφή της οποίας το όνομα ή το ψευδώνυμο ταιριάζει με το NAME υπό το πρωτόκολλο μεταφοράς που κατονομάζει το PROTO. Είναι το Perl wrapper γύρω από την κλήση getservbyname(3) της βιβλιοθήκης C, και είναι ο τρόπος για να μετατρέψετε το "https" σε 443 χωρίς να κωδικοποιήσετε σταθερά τον αριθμό.

Και τα δύο ορίσματα είναι συμβολοσειρές. Το NAME είναι το όνομα υπηρεσίας ή ψευδώνυμο ("http", "ssh", "imaps")· το PROTO είναι το όνομα πρωτοκόλλου ("tcp", "udp", "sctp") - όχι αριθμός, και όχι σταθερά τύπου SOCK_STREAM.

Σύνοψη#

my $port                            = getservbyname NAME, PROTO;   # scalar
my ($name, $aliases, $port, $proto) = getservbyname NAME, PROTO;   # list

Τι επιστρέφεται#

Σε βαθμωτό περιβάλλον, ο αριθμός θύρας ως απλός ακέραιος σε host byte order - έτοιμος για τροφοδοσία στην pack με "n" ή σε έναν κατασκευαστή sockaddr_in. Αν δεν ταιριάζει καμία εγγραφή, η επιστροφή είναι undef.

Σε περιβάλλον λίστας, τα τέσσερα πεδία της εγγραφής servent:

  • $name - κανονικό όνομα υπηρεσίας (το πρωτεύον όνομα, όχι το ψευδώνυμο με το οποίο αναζητήσατε).

  • $aliases - συμβολοσειρά εναλλακτικών ονομάτων διαχωρισμένη με κενά.

  • $port - αριθμός θύρας, host byte order.

  • $proto - κανονικό όνομα πρωτοκόλλου όπως επιστρέφεται από τον resolver, κανονικά ίσο με το PROTO που περάσατε.

Αν δεν ταιριάζει καμία εγγραφή σε περιβάλλον λίστας, η επιστροφή είναι η κενή λίστα.

Η θύρα είναι σε host byte order. Τα APIs δικτύου περιμένουν network byte order, οπότε περάστε την μέσω pack με το πρότυπο "n" - ή αφήστε το Socket να το κάνει μέσω της sockaddr_in.

Καθολική κατάσταση που επηρεάζει#

  • Διατηρεί ανοιχτό handle στη βάση δεδομένων υπηρεσιών μεταξύ κλήσεων όταν η βάση έχει ανοίξει με setservent χρησιμοποιώντας μη-μηδενικό STAYOPEN. Η endservent την κλείνει.

  • Θέτει το $! σε αποτυχίες αναζήτησης που προέρχονται από σφάλμα σε επίπεδο συστήματος (αρχείο βάσης δεδομένων που λείπει, μη προσπελάσιμο backend NSS). Ένα απλό «δεν υπάρχει τέτοια υπηρεσία» αναφέρεται με επιστροφή undef / κενής λίστας, όχι θέτοντας το $!.

Παραδείγματα#

Επιλύστε μια γνωστή υπηρεσία στη θύρα της:

my $port = getservbyname("https", "tcp");
print $port, "\n";                    # 443

Πλήρης εγγραφή σε περιβάλλον λίστας:

my ($name, $aliases, $port, $proto) = getservbyname("http", "tcp");
print "$name ($aliases) -> $port/$proto\n";
                                      # www (www-http http) -> 80/tcp
                                      # (exact aliases depend on /etc/services)

Κατασκευάστε ένα sockaddr_in για την connect, μετατρέποντας τη θύρα από host order σε network order με pack:

use Socket;
my $port  = getservbyname("smtp", "tcp")
    or die "smtp/tcp not in services db";
my $addr  = sockaddr_in($port, inet_aton("mail.example.com"));
socket(my $s, AF_INET, SOCK_STREAM, getprotobyname("tcp")) or die $!;
connect($s, $addr) or die "connect: $!";

Διακρίνετε το «δεν βρέθηκε» από το «λάθος πρωτόκολλο» - μια υπηρεσία που υπάρχει υπό tcp αλλά όχι udp επιστρέφει undef όταν το πρωτόκολλο δεν ταιριάζει:

defined(getservbyname("https", "tcp")) or die "expected 443";
defined(getservbyname("https", "udp")) or warn "no https/udp entry";

Αναζήτηση με ψευδώνυμο - τα ψευδώνυμα επιλύονται το ίδιο με το κανονικό όνομα, αλλά το επιστρεφόμενο $name είναι πάντα το κανονικό:

my ($name) = getservbyname("www", "tcp");
print $name, "\n";                    # "http" on most systems

Οριακές περιπτώσεις#

  • Άγνωστη υπηρεσία: επιστρέφει undef σε βαθμωτό περιβάλλον, την κενή λίστα σε περιβάλλον λίστας. Το $! δεν τίθεται για απλή αστοχία - μόνο για υποκείμενα σφάλματα συστήματος.

  • Άγνωστο πρωτόκολλο: το ίδιο με άγνωστη υπηρεσία. Η getservbyname("ssh", "xyzzy") δεν επιστρέφει τίποτα· δεν εγείρεται ξεχωριστό σφάλμα.

  • Διάκριση πεζών-κεφαλαίων: τα ονόματα υπηρεσίας και πρωτοκόλλου συγκρίνονται χωρίς διάκριση πεζών-κεφαλαίων από τον resolver του συστήματος σε κάθε πλατφόρμα που υποστηρίζουμε· τα "HTTPS" και "https" δίνουν την ίδια απάντηση.

  • Η θύρα είναι σε host byte order: το να την περάσετε απευθείας σε μορφή επί της γραμμής είναι σφάλμα. Χρησιμοποιήστε pack("n", $port) ή sockaddr_in($port, $addr) - και τα δύο χειρίζονται τη μετατροπή.

  • Τα NAME και PROTO είναι και τα δύο απαιτούμενα. Δεν υπάρχει μορφή με ένα όρισμα· η παράλειψη του PROTO είναι σφάλμα κατά τη μεταγλώττιση.

  • Παγίδα προτεραιότητας: όπως κάθε υποψήφιο ονομασμένου μοναδιαίου τελεστή σε αυτή την οικογένεια, η getservbyname είναι τελεστής λίστας. Βάλτε παρενθέσεις όταν συνδυάζετε με τελεστές:

    getservbyname "http", "tcp" == 80      # WRONG: parses as
                                           # getservbyname("http", ("tcp" == 80))
    getservbyname("http", "tcp") == 80     # right
    
  • Threads: σε συστήματα με getservbyname_r(3), η Perl χρησιμοποιεί διαφανώς την επανεισερχόμενη παραλλαγή. Στις λίγες πλατφόρμες που δεν τη διαθέτουν, ταυτόχρονες αναζητήσεις από πολλαπλά threads μπορούν να αλλοιώσουν τα αποτελέσματα η μία της άλλης.

  • Διεπαφή ανά όνομα: το Net::servent (core) περιτυλίγει αυτή την κλήση και επιστρέφει αντικείμενο με ονομασμένες προσπελάσεις, με κόστος μίας εκχώρησης ανά αναζήτηση.

Διαφορές από το upstream#

Πλήρως συμβατό με το upstream Perl 5.42.

Δείτε επίσης#

  • getservbyport - αντίστροφη αναζήτηση: θύρα + πρωτόκολλο → εγγραφή υπηρεσίας

  • getservent - διασχίστε κάθε εγγραφή στη βάση δεδομένων υπηρεσιών, μία εγγραφή τη φορά

  • setservent - επαναφέρετε στην αρχή (ή ανοίξτε μόνιμα) τη βάση δεδομένων υπηρεσιών πριν από μια διάσχιση

  • endservent - κλείστε τη βάση δεδομένων υπηρεσιών που άνοιξε η setservent

  • getprotobyname - συμπληρωματική αναζήτηση για το όρισμα PROTO όταν χρειάζεστε επίσης τον αριθμητικό αριθμό πρωτοκόλλου του

  • Socket - οι sockaddr_in και pack_sockaddr_in καταναλώνουν τη θύρα σε host order που επιστρέφεται εδώ