setsockopt#
Θέτει σε ανοιχτή υποδοχή μια επιλογή σε επίπεδο πυρήνα.
Η setsockopt είναι το περιτύλιγμα Perl γύρω από την κλήση συστήματος POSIX setsockopt(2). Γράφει την επιλογή που κατονομάζει το OPTNAME στο LEVEL πρωτοκόλλου, στο ήδη ανοιγμένο filehandle SOCKET, χρησιμοποιώντας την τιμή πακεταρισμένη στο OPTVAL. Είναι το κουμπί για όλα όσα ο πυρήνας σας αφήνει να ρυθμίσετε σε μια υποδοχή - επαναχρήση διεύθυνσης, keepalives, χρονικά όρια, αλγόριθμος του Nagle, συμμετοχή σε multicast, μεγέθη ενταμιευτών αποστολής και λήψης, συμπεριφορά του SO_LINGER στο close, και ούτω καθεξής. Τα συμβολικά ονόματα για το LEVEL και το OPTNAME προέρχονται από το άρθρωμα Socket.
Σύνοψη#
setsockopt SOCKET, LEVEL, OPTNAME, OPTVAL
Τι επιστρέφεται#
Αληθής τιμή σε επιτυχία, undef σε αποτυχία (με την $! τεθειμένη στο υποκείμενο errno: EBADF, ENOPROTOOPT, EINVAL, ENOTSOCK, κ.λπ.). Πάντα ελέγχετε την τιμή επιστροφής - μια σιωπηρά αγνοημένη επιλογή σημαίνει ότι το πρόγραμμα τρέχει με προεπιλογές που διαφέρουν από αυτό που διαβάζει ο κώδικας:
setsockopt($sock, SOL_SOCKET, SO_REUSEADDR, pack("l", 1))
or die "setsockopt SO_REUSEADDR: $!";
Καθολική κατάσταση που επηρεάζει#
Καμία άμεσα. Η setsockopt θέτει την $! σε αποτυχία· αυτή είναι η μόνη καθολική του διερμηνέα που εμπλέκεται. Η επίδραση είναι στην κατάσταση της υποδοχής από την πλευρά του πυρήνα, όχι σε καμία μεταβλητή σε επίπεδο Perl.
OPTVAL - πακεταρισμένα bytes ή σκέτος ακέραιος#
Οι περισσότερες επιλογές υποδοχών δέχονται σημαία C int. Η setsockopt δέχεται και τις δύο μορφές για ευκολία:
Μια πακεταρισμένη συμβολοσειρά bytes της οποίας η διάταξη ταιριάζει με τον τύπο C της επιλογής, τυπικά δομημένη με
pack:pack("l", 1)για λογική τιμή,pack("ll", $on_secs, $on_usecs)γιαstruct timeval,pack("ii", $on, $linger)γιαstruct linger.Έναν απλό ακέραιο, που είναι συντομογραφία για το
pack("i", OPTVAL). Βολικό γιαSO_REUSEADDR,TCP_NODELAY, και άλλες λογικές σημαίες:setsockopt($sock, IPPROTO_TCP, TCP_NODELAY, 1);
Επιλογές των οποίων η τιμή είναι struct (SO_LINGER, SO_RCVTIMEO, IP_ADD_MEMBERSHIP) πρέπει να περαστούν ως ρητά πακεταρισμένη συμβολοσειρά μέσω pack. Σκέτος ακέραιος εκεί παράγει EINVAL ή, χειρότερα, γράφει σιωπηρά μνήμη λάθος μεγέθους που ο πυρήνας παρερμηνεύει.
Παραδείγματα#
Απενεργοποιήστε τον αλγόριθμο του Nagle σε υποδοχή TCP ώστε μικρές εγγραφές να φεύγουν αμέσως - χρήσιμο για πρωτόκολλα ευαίσθητα σε καθυστέρηση (διαδραστικά κελύφη, κίνηση παιχνιδιών, RPC):
use Socket qw(IPPROTO_TCP TCP_NODELAY);
setsockopt($sock, IPPROTO_TCP, TCP_NODELAY, 1)
or die "TCP_NODELAY: $!";
Επιτρέψτε σε διακομιστή να επανασυνδέσει θύρα που εξακολουθεί να είναι σε TIME_WAIT από προηγούμενη διεργασία - η μοναδικά πιο κοινή κλήση setsockopt στην πράξη, και πρέπει να γίνει πριν την bind:
use Socket qw(SOL_SOCKET SO_REUSEADDR);
setsockopt($srv, SOL_SOCKET, SO_REUSEADDR, pack("l", 1))
or die "SO_REUSEADDR: $!";
bind($srv, sockaddr_in(9000, INADDR_ANY))
or die "bind: $!";
Θέστε χρονικό όριο λήψης ώστε μια μπλοκαριστική recv ή ανάγνωση από την υποδοχή να επιστρέψει με EAGAIN / EWOULDBLOCK μετά από 5 δευτερόλεπτα αντί να κρεμάει για πάντα. Η τιμή της επιλογής είναι πακεταρισμένο struct timeval:
use Socket qw(SOL_SOCKET SO_RCVTIMEO);
my $tv = pack("l!l!", 5, 0); # 5 seconds, 0 microseconds
setsockopt($sock, SOL_SOCKET, SO_RCVTIMEO, $tv)
or die "SO_RCVTIMEO: $!";
Ενεργοποιήστε τα probes keepalive του TCP ώστε ημι-ανοιχτές συνδέσεις (κατέρρευσε ο ομότιμος, τραβήχτηκε το καλώδιο) να γίνονται τελικά αντιληπτές και η υποδοχή να σφάλλει αντί να μπλοκάρει επ” αόριστον:
use Socket qw(SOL_SOCKET SO_KEEPALIVE);
setsockopt($sock, SOL_SOCKET, SO_KEEPALIVE, 1)
or die "SO_KEEPALIVE: $!";
Κάντε την close να μπλοκάρει για έως 10 δευτερόλεπτα ενώ ο πυρήνας εκκενώνει μη απεσταλμένα δεδομένα, και μετά να απορρίπτει και να κάνει reset. Το SO_LINGER παίρνει struct δύο ακεραίων: τη σημαία ενεργοποίησης και το χρονικό όριο σε δευτερόλεπτα:
use Socket qw(SOL_SOCKET SO_LINGER);
setsockopt($sock, SOL_SOCKET, SO_LINGER, pack("ii", 1, 10))
or die "SO_LINGER: $!";
Μεγαλώστε τον ενταμιευτή λήψης του πυρήνα για υποδοχή μαζικής μεταφοράς. Ο πυρήνας τυπικά διπλασιάζει την τιμή που ζητάτε και την περιορίζει στο net.core.rmem_max:
use Socket qw(SOL_SOCKET SO_RCVBUF);
setsockopt($sock, SOL_SOCKET, SO_RCVBUF, 1 << 20) # 1 MiB
or die "SO_RCVBUF: $!";
Οριακές περιπτώσεις#
Το
SOCKETπρέπει να είναι ήδη ανοιχτό. Ηsetsockoptδεν δημιουργεί την υποδοχή - καλέστε πρώταsocket. Κλεισμένο ή ποτέ ανοιγμένο filehandle αποτυγχάνει μεEBADF.Η σειρά έχει σημασία. Η
SO_REUSEADDRπρέπει να τεθεί πριν τηνbind. ΗSO_KEEPALIVEμπορεί να μπει πριν ή μετά τηνconnect, αλλά για υποδοχές διακομιστή θέστε την στο αποδεκτό θυγατρικό filehandle που επιστρέφει ηaccept, όχι σε αυτό που ακούει - οι επιλογές δεν διαδίδονται πάντα.Η συντομογραφία ακεραίου είναι
pack("i", N), όχιpack("l", N). Σε πλατφόρμες όπου τοintκαι τοlongδιαφέρουν σε μέγεθος, το να περάσετε σκέτο ακέραιο και το να περάσετεpack("l", N)γράφουν διαφορετικό αριθμό bytes. Και τα δύο τυχαίνει να λειτουργούν για τις κοινές λογικές επιλογές μεγέθουςintσε LP64 Linux, αλλά η συντομογραφία είναι η φορητή προεπιλογή.Επιλογές με τιμή τύπου struct χρειάζονται ρητό
pack. ΟιSO_LINGER,SO_RCVTIMEO,SO_SNDTIMEO,IP_ADD_MEMBERSHIP,IP_MREQ, και παρόμοιες παίρνουν structs σταθερής διάταξης. Περάστε πακεταρισμένη συμβολοσειρά σωστού μήκους ή ο πυρήνας απορρίπτει την κλήση μεEINVAL.Το
LEVELεπιλέγει τον χώρο ονομάτων της επιλογής.SOL_SOCKETγια γενικές επιλογές,IPPROTO_TCPγια ειδικές του TCP (TCP_NODELAY,TCP_KEEPIDLE),IPPROTO_IPγια IPv4 (IP_TTL,IP_ADD_MEMBERSHIP),IPPROTO_IPV6για IPv6. ΑναντιστοιχίαLEVELκαιOPTNAMEδίνειENOPROTOOPT.Επιλογές μόνο για ανάγνωση ή μη υποστηριζόμενες αποτυγχάνουν με
ENOPROTOOPT. Αυτό ενεργοποιείται επίσης όταν ο πυρήνας απλώς δεν γνωρίζει την επιλογή - συνηθισμένο όταν αντιγράφεται κώδικας μεταξύ λειτουργικών συστημάτων.Προνομιακές επιλογές. Λίγες επιλογές (
SO_PRIORITYπάνω από κάποιες τιμές,IP_TRANSPARENT,SO_BINDTODEVICE) απαιτούνCAP_NET_ADMINσε Linux· μια κλήση χωρίς προνόμια αποτυγχάνει μεEPERM.Η ανάγνωση πίσω γίνεται με την
getsockopt, όχι με τηνsetsockopt. Ηsetsockoptδεν έχει μορφή ερώτησης· χρησιμοποιήστε τηνgetsockoptγια να επιβεβαιώσετε τι πραγματικά αποθήκευσε ο πυρήνας (μπορεί να στρογγυλοποιήσει, να περικόψει ή να διπλασιάσει την τιμή).
Διαφορές από το upstream#
Πλήρως συμβατό με το upstream Perl 5.42.
Δείτε επίσης#
getsockopt- ο αντίστοιχος ερώτησης· διαβάστε πίσω μια επιλογή για να δείτε τι πράγματι εφάρμοσε ο πυρήναςsocket- δημιουργεί το filehandle υποδοχής που ρυθμίζει ηsetsockopt· πρέπει να κληθεί πρώτηbind- θέστε τοSO_REUSEADDRμεsetsockoptπριν καλέσετεbindσε υποδοχή διακομιστήaccept- επιλογές που τίθενται στον listener δεν διαδίδονται όλες· εφαρμόστε ξανά τις επιλογές ανά σύνδεση στο αποδεκτό handlepack- δομεί τη συμβολοσειρά bytesOPTVALγια επιλογές με τιμή τύπου struct όπως οιSO_LINGERκαιSO_RCVTIMEOSocket- πηγή τωνSOL_SOCKET,IPPROTO_TCP,SO_REUSEADDR,TCP_NODELAY, και των υπολοίπων συμβολικών σταθερών