getsockname#
Επιστρέφει την τοπική διεύθυνση μιας συνδεδεμένης ή δεσμευμένης υποδοχής.
Η getsockname ρωτά τον πυρήνα σε ποια διεύθυνση και θύρα είναι δεσμευμένη η SOCKET σε αυτή την άκρη της σύνδεσης. Το αποτέλεσμα είναι η ίδια πακεταρισμένη δομή sockaddr που ο πυρήνας παραδίδει στην accept ή που θα δίνατε στην bind - αποπακετάρετέ την με τον κατάλληλο βοηθό από το Socket (για παράδειγμα sockaddr_in για IPv4, sockaddr_in6 για IPv6). Χρήσιμη όταν ένας υπολογιστής έχει πολλαπλές διεπαφές και χρειάζεται να ξέρετε από ποια σας προσέγγισε ένας πελάτης, ή όταν ζητήσατε από τον πυρήνα μια εφήμερη θύρα μέσω bind με θύρα 0 και τώρα θέλετε να μάθετε τη θύρα που επέλεξε.
Σύνοψη#
getsockname SOCKET
Τι επιστρέφεται#
Σε επιτυχία, το πακεταρισμένο sockaddr για την τοπική άκρη της SOCKET ως συμβολοσειρά bytes της οποίας η διάταξη ταιριάζει με την οικογένεια διευθύνσεων της υποδοχής. Σε αποτυχία, undef με ορισμένη την $! (τυπικά ENOTSOCK αν η SOCKET δεν είναι υποδοχή, ή EBADF αν δεν είναι ανοιχτό filehandle).
Η τιμή επιστροφής είναι αδιαφανή bytes. Μην την επιθεωρείτε απευθείας - δώστε την στον κατάλληλο για την οικογένεια αποπακεταριστή:
use Socket;
my $packed = getsockname($sock) or die "getsockname: $!";
my ($port, $addr) = sockaddr_in($packed); # IPv4
Για κώδικα ανεξάρτητο από οικογένεια διευθύνσεων, καλέστε πρώτα την sockaddr_family στο αποτέλεσμα και κάντε dispatch βάσει της επιστρεφόμενης σταθεράς AF_*.
Καθολική κατάσταση που επηρεάζει#
Καμία. Η getsockname είναι ένα καθαρό περιτύλιγμα κλήσης συστήματος - δεν διαβάζει ούτε γράφει την $_, εκτός της $!, ούτε καμία άλλη καθολική του διερμηνευτή.
Παραδείγματα#
Ανακαλύψτε την εφήμερη θύρα που εκχώρησε ο πυρήνας μετά από bind(…, 0):
use Socket;
socket(my $srv, AF_INET, SOCK_STREAM, 0) or die $!;
bind($srv, sockaddr_in(0, INADDR_ANY)) or die $!;
my ($port) = sockaddr_in(getsockname($srv));
print "listening on port $port\n";
Εντοπίστε σε ποια τοπική IP σας προσέγγισε ένας συνδεδεμένος πελάτης, σε έναν υπολογιστή με πολλαπλές διεπαφές:
use Socket;
my $mysockaddr = getsockname($sock);
my ($port, $myaddr) = sockaddr_in($mysockaddr);
printf "Connect to %s [%s]\n",
scalar gethostbyaddr($myaddr, AF_INET),
inet_ntoa($myaddr);
Παραλλαγή IPv6 - αποπακετάρισμα με sockaddr_in6:
use Socket;
my ($port, $addr) = sockaddr_in6(getsockname($sock));
printf "local: [%s]:%d\n", inet_ntop(AF_INET6, $addr), $port;
Dispatch ανεξάρτητο από οικογένεια όταν η υποδοχή μπορεί να είναι είτε IPv4 είτε IPv6:
use Socket qw(sockaddr_family sockaddr_in sockaddr_in6
inet_ntop AF_INET AF_INET6);
my $name = getsockname($sock) or die "getsockname: $!";
if (sockaddr_family($name) == AF_INET) {
my ($port, $addr) = sockaddr_in($name);
printf "%s:%d\n", inet_ntoa($addr), $port;
} else {
my ($port, $addr) = sockaddr_in6($name);
printf "[%s]:%d\n", inet_ntop(AF_INET6, $addr), $port;
}
Οριακές περιπτώσεις#
Μη δεσμευμένη υποδοχή: Μια υποδοχή που έχει δημιουργηθεί αλλά δεν έχει ποτέ δεσμευθεί ή συνδεθεί τυπικά επιστρέφει ένα sockaddr με τη διεύθυνση wildcard και θύρα
0. Δεν είναι σφάλμα - ο πυρήνας απλώς αναφέρει «δεν έχει εκχωρηθεί ακόμη τοπικό όνομα».Δεν είναι υποδοχή: Αν δοθεί ανοιχτό filehandle που δεν είναι υποδοχή (απλό αρχείο, σωλήνωση), επιστρέφει
undefμε την$!ορισμένη σεENOTSOCK.Κλειστό filehandle: Επιστρέφει
undefμε την$!ορισμένη σεEBADF. Υπόuse warningsεκπέμπεται προειδοποίησηgetsockname() on closed socket.Υποδοχές πεδίου Unix: Η πακεταρισμένη μορφή είναι sockaddr
AF_UNIX· αποπακετάρετε μεunpack_sockaddr_un. Η διαδρομή μπορεί να είναι μικρότερη από αυτήν που δώσατε στηνbind, και στο Linux μπορεί να αρχίζει με ένα byte NUL για υποδοχές αφηρημένου χώρου ονομάτων.Διεύθυνση wildcard με IPv4: Μια υποδοχή δεσμευμένη στο
INADDR_ANYαναφέρει εδώ τη διεύθυνση wildcard (0.0.0.0), όχι τη συγκεκριμένη διεύθυνση της διεπαφής που προσέγγισε ο ομότιμος. Για να μάθετε τη διεύθυνση-στόχο του ομοτίμου πρέπει να χρησιμοποιήσετε τηνgetsocknameαφού ο πυρήνας έχει δρομολογήσει τη σύνδεση (μετά τηνaccept), ή να συμβουλευτείτε τοIP_PKTINFOμέσωgetsockopt.Κλήση πριν από
bind/connect: Η συμπεριφορά εξαρτάται από την πλατφόρμα αλλά είναι αβλαβής. Το Linux επιστρέφει ένα μηδενισμένο sockaddr της οικογένειας της υποδοχής· μερικά BSD επιστρέφουνundefμεEINVAL. Στηριχτείτε σε αυτήν μόνο αφού έχουν ολοκληρωθεί ηbind, ηconnectή ηaccept.
Διαφορές από το upstream#
Πλήρως συμβατό με το upstream Perl 5.42.
Δείτε επίσης#
getpeername- η κατοπτρική κλήση: επιστρέφει το sockaddr της απομακρυσμένης άκρης για μια συνδεδεμένη υποδοχήbind- θέτει την τοπική διεύθυνση· ηgetsocknameδιαβάζει πίσω αυτό που πράγματι δέσμευσε ο πυρήνας, συμπεριλαμβανομένων εφήμερων θυρών που επελέγησαν για εσάςaccept- επιστρέφει το απομακρυσμένο sockaddr απευθείας, οπότε σπάνια χρειάζεστεgetsocknameστην αποδεκτή υποδοχή, εκτός αν ο ακροατής δεσμεύτηκε σε wildcard και θέλετε τη συγκεκριμένη τοπική διεύθυνσηsocket- δημιουργεί την υποδοχή της οποίας το τοπικό όνομα αναφέρει ηgetsocknameSocket- το άρθρωμα που παρέχει τους αποπακεταριστές (sockaddr_in,sockaddr_in6,unpack_sockaddr_un,sockaddr_family) που εφαρμόζετε στην τιμή επιστροφήςgetsockopt- για πληροφορίες διεύθυνσης προορισμού ανά πακέτο (IP_PKTINFO) όταν μια υποδοχή δεσμευμένη σε wildcard χρειάζεται να γνωρίζει τη συγκεκριμένη τοπική διεύθυνση ενός εισερχόμενου datagram