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- κλείστε τη βάση δεδομένων υπηρεσιών που άνοιξε ηsetserventgetprotobyname- συμπληρωματική αναζήτηση για το όρισμαPROTOόταν χρειάζεστε επίσης τον αριθμητικό αριθμό πρωτοκόλλου τουSocket- οιsockaddr_inκαιpack_sockaddr_inκαταναλώνουν τη θύρα σε host order που επιστρέφεται εδώ