# Υποδοχές UNIX-domain και UDP Δεν φτάνει κάθε υποδοχή μέσα από ένα δίκτυο. Αυτή η σελίδα καλύπτει δύο ελαφρύτερους συγγενείς της υποδοχής TCP από την [προηγούμενη σελίδα](sockets-tcp.md): ένα **ζεύγος υποδοχών UNIX-domain** για δύο σχετιζόμενες διεργασίες σε ένα μηχάνημα, και μια **υποδοχή UDP** για datagrams χωρίς σύνδεση. Και τα δύο χρησιμοποιούν την ίδια οικογένεια ενσωματωμένων συναρτήσεων [`socket`](../../p5/core/perlfunc/socket.md) και τους ίδιους βοηθούς διευθύνσεων `Socket`. Τα περιτυλίγματα υψηλού επιπέδου `IO::Socket::*` δεν είναι διαθέσιμα στην PetaPerl, οπότε οι συνταγές παραμένουν στο ενσωματωμένο επίπεδο. ## Ένα ζεύγος υποδοχών για γονέα και παιδί Η [`socketpair`](../../p5/core/perlfunc/socketpair.md) δημιουργεί δύο συνδεδεμένες υποδοχές σε μία κλήση, χωρίς διευθύνσεις, χωρίς `bind`, και χωρίς `connect`. Είναι το ιδανικό κανάλι μεταξύ ενός γονέα και ενός παιδιού που πρόκειται να δημιουργήσει με fork: πλήρως αμφίδρομο (και τα δύο άκρα μπορούν να διαβάζουν και να γράφουν), τοπικό, και ήδη συνδεδεμένο τη στιγμή που επιστρέφει. ```perl 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`](../../p5/core/perlfunc/pipe.md); Ένας σωλήνας είναι μονόδρομος - ο αναγνώστης διαβάζει, ο εγγραφέας γράφει, και αυτό είναι καθορισμένο κατά τη δημιουργία. Ένα ζεύγος υποδοχών είναι αμφίδρομο: κάθε άκρο και διαβάζει και γράφει, οπότε μια ανταλλαγή αίτησης-και-απάντησης χρειάζεται μία κλήση `socketpair` αντί για δύο σωλήνες καλωδιωμένους σε αντίθετες κατευθύνσεις. Ο κανόνας autoflush από το TCP ισχύει αμετάβλητος: ορίστε τον σε κάθε άκρο πριν από την πρώτη εγγραφή, αλλιώς μια αίτηση με ενταμιευτή δεν φτάνει ποτέ στην άλλη πλευρά και οι δύο διεργασίες μπλοκάρουν. ## Μια ανταλλαγή datagram UDP Το UDP είναι χωρίς σύνδεση. Δεν υπάρχει `connect`, ούτε `accept`, ούτε ροή - μόνο διακριτά μηνύματα, καθένα διευθυνσιοδοτημένο προς έναν προορισμό και καθένα διατηρώντας τα δικά του όρια. Ένας παραλήπτης δένεται σε μια θύρα· ένας αποστολέας του εκτοξεύει ένα datagram με [`send`](../../p5/core/perlfunc/send.md)· ο παραλήπτης το συλλέγει με [`recv`](../../p5/core/perlfunc/recv.md), η οποία αναφέρει επίσης ποιος το έστειλε. ```perl 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`](../../p5/core/perlfunc/socketpair.md) - δύο συνδεδεμένες τοπικές υποδοχές - [`socket`](../../p5/core/perlfunc/socket.md) - δημιουργεί ένα άκρο datagram ή ροής - [`bind`](../../p5/core/perlfunc/bind.md) - προσαρτά τον παραλήπτη σε μια τοπική θύρα - [`send`](../../p5/core/perlfunc/send.md) - εκτοξεύει ένα datagram προς μια διεύθυνση - [`recv`](../../p5/core/perlfunc/recv.md) - συλλέγει ένα datagram και τον αποστολέα του - [`getsockname`](../../p5/core/perlfunc/getsockname.md) - ανακαλύπτει τη δεμένη θύρα ## Επόμενο Για κοινόχρηστη μνήμη και σηματοφόρους - κανάλια που κατέχει ο πυρήνας αντί για ροές μεταξύ διεργασιών - δείτε [IPC System V](sysv-ipc.md).