bind#
Σύνδεση τοπικής διεύθυνσης σε μια υποδοχή.
Η bind είναι το περιτύλιγμα της Perl για την κλήση συστήματος POSIX bind(2). Συσχετίζει το ήδη ανοιγμένο filehandle SOCKET με την τοπική διεύθυνση NAME, ώστε οι επόμενες κλήσεις listen / accept (για διακομιστή) ή connect / send (για πελάτη με σταθερή τοπική διεύθυνση) να χρησιμοποιούν αυτή τη διεύθυνση ως πηγή τους. Το NAME είναι μια πακεταρισμένη δομή διεύθυνσης στη μορφή που αναμένει η οικογένεια διευθύνσεων της υποδοχής - η εργασία του πακεταρίσματος είναι δική σας, τυπικά μέσω βοηθητικών συναρτήσεων του Socket όπως `sockaddr_in` ή `sockaddr_un`.
Σύνοψη#
bind SOCKET, NAME
Τι επιστρέφεται#
Αληθής τιμή σε επιτυχία, ψευδής σε αποτυχία (με την $! να τίθεται στο υποκείμενο errno: EADDRINUSE, EACCES, EADDRNOTAVAIL, κ.λπ.). Ελέγχετε πάντα την τιμή επιστροφής - σε αντίθεση με την print, μια αποτυχημένη bind είναι σφάλμα κατά τη φάση ρύθμισης που πρέπει να ματαιώσει το πρόγραμμα:
bind $sock, $addr
or die "bind failed: $!";
Καθολική κατάσταση που επηρεάζει#
Καμία άμεσα. Η bind θέτει την $! σε αποτυχία· αυτή είναι η μόνη καθολική του διερμηνέα που εμπλέκεται. Η ίδια η υποδοχή πρέπει να είναι ήδη ανοιχτή - τυπικά παράγεται από την socket ή την socketpair - και η bind μεταβάλλει την κατάστασή της στην πλευρά του πυρήνα, όχι κάποια μεταβλητή σε επίπεδο Perl.
Παραδείγματα#
Δέσμευση μιας υποδοχής διακομιστή TCP στη θύρα 9000 σε όλες τις τοπικές διεπαφές και έναρξη ακρόασης. Το INADDR_ANY επιλέγει «οποιαδήποτε τοπική διεύθυνση»· η πακεταρισμένη μορφή προέρχεται από το `sockaddr_in`:
use Socket;
socket(my $srv, PF_INET, SOCK_STREAM, getprotobyname("tcp"))
or die "socket: $!";
bind($srv, sockaddr_in(9000, INADDR_ANY))
or die "bind: $!";
listen($srv, SOMAXCONN)
or die "listen: $!";
Δέσμευση μιας υποδοχής πελάτη σε συγκεκριμένη τοπική διεύθυνση πριν τη σύνδεση - χρησιμοποιείται όταν ο απομακρυσμένος ομότιμος φιλτράρει με βάση τη διεύθυνση IP πηγής, ή όταν ένας υπολογιστής διαθέτει πολλές διεπαφές και χρειάζεστε την εξερχόμενη κίνηση σε συγκεκριμένη:
use Socket;
socket(my $cli, PF_INET, SOCK_STREAM, getprotobyname("tcp"))
or die "socket: $!";
bind($cli, sockaddr_in(0, inet_aton("192.0.2.17")))
or die "bind: $!"; # port 0 = kernel picks one
connect($cli, sockaddr_in(443, inet_aton("93.184.216.34")))
or die "connect: $!";
Δέσμευση ενός ακροατή τομέα UNIX σε μια διαδρομή του συστήματος αρχείων. Η διαδρομή δεν πρέπει να υπάρχει ήδη - η bind δημιουργεί τον κόμβο υποδοχής και τον αφήνει πίσω όταν η διεργασία τερματίσει, οπότε καθαρίστε τον μόνοι σας:
use Socket;
my $path = "/tmp/myapp.sock";
unlink $path; # clear stale socket from prior run
socket(my $srv, PF_UNIX, SOCK_STREAM, 0)
or die "socket: $!";
bind($srv, sockaddr_un($path))
or die "bind $path: $!";
listen($srv, 5) or die "listen: $!";
Δέσμευση μιας υποδοχής UDP σε σταθερή τοπική θύρα, ώστε οι απαντήσεις από τον ομότιμο να επιστρέφουν σε προβλέψιμη διεύθυνση:
use Socket;
socket(my $udp, PF_INET, SOCK_DGRAM, getprotobyname("udp"))
or die "socket: $!";
bind($udp, sockaddr_in(5300, INADDR_ANY))
or die "bind: $!";
Η εκ νέου δέσμευση μιας προηγουμένως απελευθερωμένης θύρας σε σύντομο χρονικό διάστημα απαιτεί το SO_REUSEADDR· αλλιώς η bind αποτυγχάνει με EADDRINUSE κατά τη διάρκεια του παραθύρου TIME_WAIT:
use Socket;
setsockopt($srv, SOL_SOCKET, SO_REUSEADDR, pack("l", 1))
or die "setsockopt: $!";
bind($srv, sockaddr_in(9000, INADDR_ANY))
or die "bind: $!";
Οριακές περιπτώσεις#
Το
SOCKETπρέπει να είναι ήδη ανοιχτό. Ηbindδεν δημιουργεί την υποδοχή - καλέστε πρώτα τηνsocket. Ένα κλειστό ή ποτέ-ανοιγμένο filehandle αποτυγχάνει μεEBADF.Το
NAMEείναι μια πακεταρισμένη συμβολοσειρά bytes, όχι αναγνώσιμη από άνθρωπο διεύθυνση. Περάστε την έξοδο των`sockaddr_in`,`sockaddr_in6`ή`sockaddr_un`από τοSocket. Το πέρασμα μιας απλής συμβολοσειράς όπως"127.0.0.1:9000"παράγειEINVALή χειρότερα - ο πυρήνας διαβάζει τα bytes ωςstruct sockaddr.Η θύρα 0 σημαίνει «αφήστε τον πυρήνα να επιλέξει». Μετά από μια επιτυχημένη
bindμε θύρα 0, ανακτήστε την πραγματική θύρα με τηνgetsocknameκαι το`sockaddr_in`σε λειτουργία αποπακεταρίσματος.Οι θύρες κάτω από 1024 απαιτούν αυξημένα προνόμια σε Unix - η
bindαποτυγχάνει μεEACCESγια μια διεργασία χωρίς προνόμια.Το
EADDRINUSEείναι η πιο κοινή αποτυχία. Πυροδοτείται όταν μια άλλη διεργασία κατέχει τη διεύθυνση, όταν μια προγενέστερη υποδοχή στην ίδια διεύθυνση βρίσκεται ακόμα σεTIME_WAIT, ή όταν καλείτε τηνbindδύο φορές στην ίδια υποδοχή. ΤοSO_REUSEADDR(βλέπεsetsockopt) αντιμετωπίζει την περίπτωσηTIME_WAIT· οι υπόλοιπες είναι γνήσιες συγκρούσεις.Οι υποδοχές τομέα UNIX αφήνουν πίσω εγγραφή στο σύστημα αρχείων που επιβιώνει της διεργασίας. Αφαιρέστε την πριν από μια νέα
bind(unlink $path) και κατά τον καθαρό τερματισμό.Η δέσμευση μετά από
connectείναι σφάλμα. Όταν μια υποδοχή έχει συνδεθεί, η τοπική της διεύθυνση είναι καθορισμένη. Καλέστε πρώτα τηνbindαν χρειάζεστε συγκεκριμένη διεύθυνση πηγής.Οι υποδοχές IPv6 χρησιμοποιούν
`sockaddr_in6`καιPF_INET6· η ανάμειξη οικογενειών μεταξύ της υποδοχής και της πακεταρισμένης διεύθυνσης αποτυγχάνει μεEAFNOSUPPORT.
Διαφορές από το upstream#
Πλήρως συμβατό με το upstream Perl 5.42.
Δείτε επίσης#
socket- δημιουργία του filehandle υποδοχής στο οποίο συνδέεται ηbind· πρέπει να καλείται πρώτηconnect- το αντίστοιχο στην πλευρά του πελάτη· θέτει την απομακρυσμένη διεύθυνση αντί της τοπικήςlisten- επισήμανση μιας δεσμευμένης υποδοχής ως πρόθυμης να δεχτεί εισερχόμενες συνδέσειςaccept- άντληση της επόμενης εκκρεμούς σύνδεσης από μια δεσμευμένη υποδοχή που ακούειgetsockname- ανάκτηση της πραγματικής διεύθυνσης που επέλεξε ηbind, ειδικά μετά από δέσμευση στη θύρα 0setsockopt- ορισμός τουSO_REUSEADDRκαι άλλων πριν τηνbindγια έλεγχο της επαναχρησιμοποίησης διεύθυνσηςSocket- πακετάρει και αποπακετάρει το όρισμαNAME· πηγή των`sockaddr_in`,`sockaddr_un`,INADDR_ANY,PF_INETκαι σχετικών σταθερών