getsockopt#
Διαβάζει μία επιλογή υποδοχής από τον πυρήνα ως αδιαφανή πακεταρισμένη συμβολοσειρά.
Η getsockopt ζητά από τον πυρήνα την τρέχουσα τιμή της επιλογής με όνομα OPTNAME στο επίπεδο πρωτοκόλλου LEVEL στην SOCKET. Ο πυρήνας δεν επιστρέφει τιμή με τύπο - επιστρέφει έναν ωμό ενταμιευτή bytes του οποίου η διάταξη καθορίζεται από το ζεύγος (LEVEL, OPTNAME). Αποκωδικοποιείτε αυτόν τον ενταμιευτή με unpack, συνήθως με το πρότυπο "i" ή "I", επειδή οι περισσότερες επιλογές είναι απλοί ακέραιοι.
Σύνοψη#
getsockopt SOCKET, LEVEL, OPTNAME
Τι επιστρέφεται#
Μια πακεταρισμένη συμβολοσειρά που περιέχει την απάντηση του πυρήνα σε περίπτωση επιτυχίας, ή undef σε περίπτωση αποτυχίας με το $! ρυθμισμένο στο σφάλμα του συστήματος. Τα περιεχόμενα της συμβολοσειράς είναι αδιαφανή bytes - το μήκος και η διάταξή της εξαρτώνται εξ ολοκλήρου από το (LEVEL, OPTNAME):
Οι επιλογές λογικής τιμής και ακεραίου (
SO_KEEPALIVE,SO_REUSEADDR,TCP_NODELAY, …) επιστρέφουν ως πακεταρισμένοint. Αποκωδικοποιήστε μεunpackχρησιμοποιώντας"i"ή"I".Τα χρονικά όρια (
SO_RCVTIMEO,SO_SNDTIMEO) επιστρέφουν ως πακεταρισμένοstruct timeval- δύοlongστις περισσότερες πλατφόρμες.Οι επιλογές δεσμευμένες σε διεύθυνση (
SO_PEERCRED,IP_MULTICAST_IF, structs linger, …) έχουν τις δικές τους διατάξεις· συμβουλευτείτε τοgetsockopt(2)και τις σχετικές σελίδες man πρωτοκόλλων για το ακριβές struct.
Πάντα ελέγχετε την τιμή επιστροφής πριν την αποκωδικοποίηση - η κλήση unpack σε undef αποδίδει κενό αποτέλεσμα και κρύβει το πραγματικό σφάλμα που καταγράφεται στο $!.
Καθολική κατάσταση που επηρεάζει#
Παραδείγματα#
Έλεγχος αν ο αλγόριθμος του Nagle είναι αυτή τη στιγμή απενεργοποιημένος (TCP_NODELAY ενεργό) σε μια υποδοχή TCP:
use Socket qw(IPPROTO_TCP TCP_NODELAY);
my $packed = getsockopt($sock, IPPROTO_TCP, TCP_NODELAY)
or die "getsockopt TCP_NODELAY: $!";
my $nodelay = unpack("I", $packed);
print "Nagle is ", $nodelay ? "off" : "on", "\n";
Ίδια ιδέα, αλλά με λήψη του αριθμού πρωτοκόλλου TCP κατά τον χρόνο εκτέλεσης από τη βάση πρωτοκόλλων του συστήματος αντί από σταθερά του Socket:
use Socket qw(TCP_NODELAY);
defined(my $tcp = getprotobyname("tcp"))
or die "no protocol entry for tcp";
my $packed = getsockopt($sock, $tcp, TCP_NODELAY)
or die "getsockopt: $!";
Ανάγνωση του SO_ERROR για εκκένωση και εκκαθάριση εκκρεμούς ασύγχρονου σφάλματος σε μη μπλοκαριστική υποδοχή μετά από connect ή αφότου η select την επισημάνει ως εγγράψιμη:
use Socket qw(SOL_SOCKET SO_ERROR);
my $packed = getsockopt($sock, SOL_SOCKET, SO_ERROR)
or die "getsockopt SO_ERROR: $!";
my $err = unpack("i", $packed);
if ($err) {
$! = $err;
die "asynchronous socket error: $!";
}
Ανάγνωση του τύπου υποδοχής (SOCK_STREAM, SOCK_DGRAM, …) ενός ήδη ανοιγμένου handle:
use Socket qw(SOL_SOCKET SO_TYPE SOCK_STREAM);
my $packed = getsockopt($sock, SOL_SOCKET, SO_TYPE)
or die "getsockopt SO_TYPE: $!";
my $type = unpack("i", $packed);
print "stream socket\n" if $type == SOCK_STREAM;
Ανάγνωση επιλογής struct timeval. Το SO_RCVTIMEO επιστρέφει δύο εγγενή long - δευτερόλεπτα και μικροδευτερόλεπτα:
use Socket qw(SOL_SOCKET SO_RCVTIMEO);
my $packed = getsockopt($sock, SOL_SOCKET, SO_RCVTIMEO)
or die "getsockopt SO_RCVTIMEO: $!";
my ($sec, $usec) = unpack("l!l!", $packed);
printf "receive timeout: %d.%06d s\n", $sec, $usec;
Οριακές περιπτώσεις#
Η
SOCKETδεν είναι ανοιχτή υποδοχή: η κλήση αποτυγχάνει, επιστρέφειundef, και θέτει το$!σεENOTSOCK("Socket operation on non-socket") ήEBADF("Bad file descriptor") για κλειστό handle.Άγνωστο
LEVEL/OPTNAME: ο πυρήνας απορρίπτει το αίτημα μεENOPROTOOPT("Protocol not available"). Δεν υπάρχει τρόπος να διακρίνετε αυτή την περίπτωση από την περίπτωση επιτυχίας εκτός από τον έλεγχο της τιμής επιστροφής.Ιδίωμα επιστροφής με αλήθεια: το συνηθισμένο
getsockopt(...) or dieλειτουργεί επειδή μια επιτυχημένη κλήση επιστρέφει μη κενή πακεταρισμένη συμβολοσειρά. Μια απάντηση μηδενικού μήκους θα έκανε το ιδίωμα να αστοχήσει, αλλά καμία επιλογή του πυρήνα δεν επιστρέφει ενταμιευτή μηδενικού μήκους στην πράξη - κάθε ορισμένη επιλογή έχει τουλάχιστον ένα byte payload.Πλάτος αποκωδικοποίησης ακεραίου: χρησιμοποιήστε
"i"ή"I"για επιλογές μεγέθουςint(SO_KEEPALIVE,TCP_NODELAY,SO_ERROR, …)· χρησιμοποιήστε"l!"ή"L!"μόνο όταν η τεκμηριωμένη διάταξη της επιλογής χρησιμοποιεί όντως εγγενέςlong. Λάθος πλάτος επιστρέφει σιωπηρά τον λάθος αριθμό σε πλατφόρμες LP64.Μη πακετάρετε την απάντηση χειροκίνητα: η
getsockoptεπιστρέφει ό,τι έγραψε ο πυρήνας, συμπεριλαμβανομένης κάθε συμπλήρωσης. Επαναπακετάρετε μόνο σε πλήρεις κύκλους μέσω τηςsetsockopt, και τότε περάστε τον ενταμιευτή πίσω αυτούσιο αντί να τον ανασυγκροτείτε.Καμία σταθερά χωρίς
Socket: ταSOL_SOCKET,IPPROTO_TCP,TCP_NODELAY,SO_ERROR, και συγγενή δεν είναι ενσωματωμένα ονόματα. Εισάγετέ τα από τοSocketμεuse Socket qw(...)ήuse Socket qw(:all).
Διαφορές από το upstream#
Πλήρως συμβατό με το upstream Perl 5.42.
Δείτε επίσης#
setsockopt- το μισό εγγραφής· ορίζει την επιλογή της οποίας την τιμή ανακτά ηgetsockoptSocket- πηγή των σταθερώνSOL_*,IPPROTO_*,SO_*,TCP_*,IP_*που περνάτε ωςLEVELκαιOPTNAMEunpack- απαιτείται για την αποκωδικοποίηση της πακεταρισμένης συμβολοσειράς bytes που παραδίδει ο πυρήναςgetprotobyname- τρόπος κατά τον χρόνο εκτέλεσης για την απόκτηση του αριθμού πρωτοκόλλουLEVELόταν δεν θέλετε να εισάγετε τις σταθερέςIPPROTO_*από τοSocketgetsockname- αδελφή κλήση ενδοσκόπησης· επιστρέφει την τοπική διεύθυνση που είναι δεσμευμένη στηνSOCKETαντί για μία επιλογήsocket- δημιουργεί την υποδοχή την οποία στη συνέχεια ερωτά ηgetsockopt