Υποδοχές UNIX-domain και UDP#
Δεν φτάνει κάθε υποδοχή μέσα από ένα δίκτυο. Αυτή η σελίδα καλύπτει δύο ελαφρύτερους συγγενείς της υποδοχής TCP από την προηγούμενη σελίδα: ένα ζεύγος υποδοχών UNIX-domain για δύο σχετιζόμενες διεργασίες σε ένα μηχάνημα, και μια υποδοχή UDP για datagrams χωρίς σύνδεση.
Και τα δύο χρησιμοποιούν την ίδια οικογένεια ενσωματωμένων συναρτήσεων socket και τους ίδιους βοηθούς διευθύνσεων Socket. Τα περιτυλίγματα υψηλού επιπέδου IO::Socket::* δεν είναι διαθέσιμα στην PetaPerl, οπότε οι συνταγές παραμένουν στο ενσωματωμένο επίπεδο.
Ένα ζεύγος υποδοχών για γονέα και παιδί#
Η socketpair δημιουργεί δύο συνδεδεμένες υποδοχές σε μία κλήση, χωρίς διευθύνσεις, χωρίς bind, και χωρίς connect. Είναι το ιδανικό κανάλι μεταξύ ενός γονέα και ενός παιδιού που πρόκειται να δημιουργήσει με fork: πλήρως αμφίδρομο (και τα δύο άκρα μπορούν να διαβάζουν και να γράφουν), τοπικό, και ήδη συνδεδεμένο τη στιγμή που επιστρέφει.
use Socket;
socketpair(my $child_end, my $parent_end, AF_UNIX, SOCK_STREAM, PF_UNSPEC)
or die "socketpair: $!";
my $kid = fork() // die "fork: $!";
if ($kid == 0) {
# Child keeps its end, closes the parent's.
close $parent_end;
$child_end->autoflush(1);
print $child_end "child-says-hi\n";
my $back = <$child_end>;
print "child got: $back"; # child got: ack
exit 0;
}
# Parent keeps its end, closes the child's.
close $child_end;
$parent_end->autoflush(1);
my $msg = <$parent_end>;
print "parent got: $msg"; # parent got: child-says-hi
print $parent_end "ack\n";
waitpid($kid, 0);
Γιατί να καταφύγετε στην socketpair αντί για ένα απλό pipe; Ένας σωλήνας είναι μονόδρομος - ο αναγνώστης διαβάζει, ο εγγραφέας γράφει, και αυτό είναι καθορισμένο κατά τη δημιουργία. Ένα ζεύγος υποδοχών είναι αμφίδρομο: κάθε άκρο και διαβάζει και γράφει, οπότε μια ανταλλαγή αίτησης-και-απάντησης χρειάζεται μία κλήση socketpair αντί για δύο σωλήνες καλωδιωμένους σε αντίθετες κατευθύνσεις.
Ο κανόνας autoflush από το TCP ισχύει αμετάβλητος: ορίστε τον σε κάθε άκρο πριν από την πρώτη εγγραφή, αλλιώς μια αίτηση με ενταμιευτή δεν φτάνει ποτέ στην άλλη πλευρά και οι δύο διεργασίες μπλοκάρουν.
Μια ανταλλαγή datagram UDP#
Το UDP είναι χωρίς σύνδεση. Δεν υπάρχει connect, ούτε accept, ούτε ροή - μόνο διακριτά μηνύματα, καθένα διευθυνσιοδοτημένο προς έναν προορισμό και καθένα διατηρώντας τα δικά του όρια. Ένας παραλήπτης δένεται σε μια θύρα· ένας αποστολέας του εκτοξεύει ένα datagram με send· ο παραλήπτης το συλλέγει με recv, η οποία αναφέρει επίσης ποιος το έστειλε.
use Socket;
# --- receiver on an ephemeral port ---
socket(my $server, PF_INET, SOCK_DGRAM, getprotobyname("udp"))
or die "socket: $!";
bind($server, sockaddr_in(0, INADDR_LOOPBACK)) or die "bind: $!";
my ($port) = sockaddr_in(getsockname($server));
my $kid = fork() // die "fork: $!";
if ($kid == 0) {
# Sender fires one datagram at the receiver's port.
socket(my $client, PF_INET, SOCK_DGRAM, getprotobyname("udp")) or die;
my $to = sockaddr_in($port, INADDR_LOOPBACK);
send($client, "hello-udp", 0, $to) or die "send: $!";
exit 0;
}
# recv fills $buf and returns the sender's packed address.
my $from = recv($server, my $buf, 65535, 0);
my ($sender_port, $sender_ip) = sockaddr_in($from);
print "got '$buf' from ", inet_ntoa($sender_ip), "\n";
# got 'hello-udp' from 127.0.0.1
waitpid($kid, 0);
Τι σας δίνει το UDP και τι όχι:
Τα όρια μηνύματος διατηρούνται. Ένα
sendείναι έναrecv. Έναrecvεπιστρέφει ακριβώς ένα datagram, ποτέ δύο συνενωμένα και ποτέ το μισό ενός. Το65535είναι το μέγιστο μήκος που είστε διατεθειμένοι να αποδεχτείτε· ένα συντομότερο datagram επιστρέφει το πραγματικό του μήκος.Δεν υπάρχει
connectούτε χειραψία. Ο αποστολέας δεν ανοίγει σύνδεση· διευθυνσιοδοτεί κάθε datagram με το τέταρτο όρισμα τηςsend. Ηrecvαναφέρει τη διεύθυνση του αποστολέα ώστε μια απάντηση να μπορεί να επιστρέψει με τον ίδιο τρόπο.Η παράδοση δεν είναι εγγυημένη. Τα datagrams UDP μπορούν να απορριφθούν, να διπλασιαστούν ή να αναδιαταχθούν από το δίκτυο. Πάνω από τη διεπαφή loopback, όπως σε αυτή τη συνταγή, αυτό ουσιαστικά δεν συμβαίνει ποτέ· πάνω από ένα πραγματικό δίκτυο πρέπει να χειριστείτε μόνοι σας την απώλεια αν έχει σημασία.
Διασταυρούμενοι σύνδεσμοι αναφοράς#
socketpair- δύο συνδεδεμένες τοπικές υποδοχέςsocket- δημιουργεί ένα άκρο datagram ή ροήςbind- προσαρτά τον παραλήπτη σε μια τοπική θύραsend- εκτοξεύει ένα datagram προς μια διεύθυνσηrecv- συλλέγει ένα datagram και τον αποστολέα τουgetsockname- ανακαλύπτει τη δεμένη θύρα
Επόμενο#
Για κοινόχρηστη μνήμη και σηματοφόρους - κανάλια που κατέχει ο πυρήνας αντί για ροές μεταξύ διεργασιών - δείτε IPC System V.