Υποδοχές (sockets)

socket#

Δημιουργεί filehandle υποδοχής.

Η socket ανοίγει μια υποδοχή του είδους που περιγράφουν τα DOMAIN, TYPE, και PROTOCOL και τη συνδέει με το SOCKET, το οποίο γίνεται χρησιμοποιήσιμο filehandle της Perl. Είναι το λεπτό περιτύλιγμα της Perl πάνω από την κλήση συστήματος socket(2) - τίποτα περισσότερο, τίποτα λιγότερο. Η νέα υποδοχή είναι μη δεσμευμένη και μη συνδεδεμένη· εξακολουθείτε να χρειάζεστε bind, connect, ή listen+accept για να κάνετε οτιδήποτε με αυτήν. Εισάγετε τις συμβολικές σταθερές με use Socket; πριν την κλήση - η γραφή των ωμών ακεραίων είναι φορητή μόνο κατά τύχη.

Σύνοψη#

use Socket;
socket SOCKET, DOMAIN, TYPE, PROTOCOL

Τι επιστρέφεται#

1 σε επιτυχία, undef σε αποτυχία (με το $! ρυθμισμένο στο errno από την υποκείμενη socket(2)). Σε επιτυχία το SOCKET είναι πλέον filehandle στο οποίο μπορείτε να καλέσετε bind, connect, send / recv, ή να διαβάσετε και να γράψετε με τους συνηθισμένους τελεστές I/O μόλις φτάσει σε συνδεδεμένη κατάσταση. Αξίζει να ελέγχετε την τιμή επιστροφής σε κάθε κλήση - μια αποτυχία εδώ σημαίνει ότι δεν έχετε τίποτα χρήσιμο να περάσετε στην επόμενη κλήση socket, η οποία στη συνέχεια θα αποτύχει με πιο συγκεχυμένο τρόπο.

socket my $sock, PF_INET, SOCK_STREAM, getprotobyname("tcp")
    or die "socket: $!";

Το SOCKET μπορεί να είναι bareword filehandle (SOCK), glob (*SOCK), ή απροσδιόριστο βαθμωτό που θα αυτο-δημιουργηθεί σε αναφορά ανώνυμου filehandle. Η μορφή αυτο-δημιουργίας είναι το σύγχρονο ιδίωμα και η μόνη που περιοριάζεται καθαρά με my.

Καθολική κατάσταση που επηρεάζει#

  • $! - τίθεται στο errno από την socket(2) σε αποτυχία.

  • $^F - το κατώφλι περιγραφέα αρχείου συστήματος. Σε συστήματα με close-on-exec, ο νέος περιγραφέας λαμβάνει σημαία FD_CLOEXEC όταν ο αριθμός του υπερβαίνει το $^F (προεπιλογή 2, οπότε οι περιγραφείς 0–2 παραμένουν κληρονομήσιμοι και όλα τα άλλα κλείνουν αυτόματα κατά την exec). Ανεβάστε το πριν την socket αν θέλετε συγκεκριμένα η νέα υποδοχή να επιβιώσει μιας exec.

Παραδείγματα#

Υποδοχή πελάτη για σύνδεση TCP. Δημιουργία, σύνδεση, επικοινωνία:

use Socket;
socket my $sock, PF_INET, SOCK_STREAM, getprotobyname("tcp")
    or die "socket: $!";
my $addr = pack_sockaddr_in(80, inet_aton("example.com"));
connect $sock, $addr or die "connect: $!";
syswrite $sock, "GET / HTTP/1.0\r\nHost: example.com\r\n\r\n";

Υποδοχή διακομιστή TCP που ακούει. Δημιουργία, σήμανση ως επαναχρησιμοποιήσιμη, bind, listen:

use Socket;
socket my $srv, PF_INET, SOCK_STREAM, getprotobyname("tcp")
    or die "socket: $!";
setsockopt $srv, SOL_SOCKET, SO_REUSEADDR, pack("l", 1)
    or die "setsockopt: $!";
bind $srv, pack_sockaddr_in(8080, INADDR_ANY) or die "bind: $!";
listen $srv, SOMAXCONN                        or die "listen: $!";

Υποδοχή UDP - SOCK_DGRAM αντί για SOCK_STREAM, και δεν χρειάζεται connect πριν την send όταν περνάτε ρητό προορισμό:

use Socket;
socket my $udp, PF_INET, SOCK_DGRAM, getprotobyname("udp")
    or die "socket: $!";
my $to = pack_sockaddr_in(53, inet_aton("1.1.1.1"));
send $udp, $query, 0, $to or die "send: $!";

Υποδοχή ροής τομέα Unix για τοπικό IPC. PF_UNIX με διαδρομή συστήματος αρχείων αντί για διεύθυνση IP:

use Socket;
socket my $sock, PF_UNIX, SOCK_STREAM, 0 or die "socket: $!";
connect $sock, pack_sockaddr_un("/run/app.sock") or die "connect: $!";

Αφήνοντας το PROTOCOL στην προεπιλογή 0. Ο πυρήνας επιλέγει το προεπιλεγμένο πρωτόκολλο για το ζεύγος domain/type - για PF_INET + SOCK_STREAM είναι TCP, για PF_INET + SOCK_DGRAM είναι UDP. Η μορφή getprotobyname παραπάνω είναι πιο ρητή αλλά η μορφή 0 είναι ισοδύναμη και αποφεύγει μία αναζήτηση:

use Socket;
socket my $sock, PF_INET, SOCK_STREAM, 0 or die "socket: $!";

Οριακές περιπτώσεις#

  • Το use Socket δεν είναι προαιρετικό. Χωρίς αυτό, τα PF_INET, SOCK_STREAM, και συγγενή είναι συμβολοσειρές bareword, όχι σταθερές ακέραιοι, και η κλήση αποτυγχάνει στο όριο της κλήσης συστήματος με Invalid argument. Η εισαγωγή είναι αυτό που τα μετατρέπει σε αριθμούς.

  • Το SOCKET αλλοιώνεται σε επιτυχία. Αν η θυρίδα κρατά ανοιχτό filehandle, κλείνει πρώτα. Δεν υπάρχει προειδοποίηση - η προηγούμενη υποδοχή απλώς εξαφανίζεται σιωπηρά. Χρησιμοποιήστε φρέσκια μεταβλητή my για κάθε κλήση.

  • Η αποτυχία αφήνει το SOCKET αμετάβλητο. Σε επιστροφή undef το βαθμωτό ούτε ανοίγεται ούτε τροποποιείται· μια προηγούμενη τιμή (συμπεριλαμβανομένης παλαιότερης, ακόμα ανοιχτής υποδοχής) είναι ακόμα εκεί.

  • Όρια περιγραφέων. Η socket είναι το σημείο όπου εμφανίζεται η εξάντληση πίνακα περιγραφέων EMFILE (ανά διεργασία) και ENFILE (σε επίπεδο συστήματος). Διακομιστές μακράς διάρκειας θα πρέπει να τα αντιμετωπίζουν ως ανακτήσιμα αντί ως μοιραία.

  • EAFNOSUPPORT / EPROTONOSUPPORT / ESOCKTNOSUPPORT. Ο πυρήνας απέρριψε την τριάδα domain/type/protocol. Συνηθισμένη αιτία: αίτημα για PF_INET6 σε πυρήνα χτισμένο χωρίς IPv6, ή μη έγκυρος αριθμός πρωτοκόλλου που πέρασε από μια παλιωμένη αναζήτηση getprotobyname.

  • Η μη μπλοκαριστική λειτουργία είναι ξεχωριστό βήμα. Η socket επιστρέφει μπλοκαριστικό περιγραφέα. Χρησιμοποιήστε fcntl με F_SETFL + O_NONBLOCK (ή το αντίστοιχο του IO::Socket) αν χρειάζεστε I/O χωρίς μπλοκάρισμα.

  • Το close-on-exec είναι αυτόματο πέρα από το $^F. Η Perl θέτει FD_CLOEXEC στον νέο περιγραφέα όταν ο αριθμός fd του είναι μεγαλύτερος από το $^F. Μια υποδοχή επομένως δεν θα επιβιώσει μιας exec εκτός αν χαμηλώσατε αυτό το κατώφλι ή καθαρίσατε τη σημαία με fcntl.

  • Οι αριθμητικές τιμές domain/type δεν είναι φορητές. Το 2 τυγχάνει να είναι το AF_INET στο Linux· είναι κάτι άλλο αλλού. Πάντα να περνάτε μέσω των σταθερών του αρθρώματος Socket.

Διαφορές από το upstream#

Πλήρως συμβατό με το upstream Perl 5.42.

Δείτε επίσης#

  • bind - συνδέει υποδοχή που δημιούργησε η socket με τοπική διεύθυνση, απαιτείται πριν την listen ή πριν την αποστολή από γνωστή θύρα

  • connect - εκκινεί εξερχόμενη σύνδεση σε υποδοχή SOCK_STREAM, ή ορίζει τον προεπιλεγμένο ομότιμο σε υποδοχή SOCK_DGRAM

  • listen - σημαίνει δεσμευμένη υποδοχή SOCK_STREAM ως παθητική ώστε η accept να μπορεί να αντλεί συνδέσεις από αυτήν

  • accept - επιστρέφει την επόμενη εκκρεμή σύνδεση σε υποδοχή που ακούει ως φρέσκο filehandle

  • socketpair - δημιουργία ζεύγους συνδεδεμένων υποδοχών σε μία κλήση· η συνηθισμένη επιλογή όταν και τα δύο άκρα ζουν στην ίδια διεργασία ή σε γονέα/παιδί

  • Socket - το άρθρωμα που παρέχει τα PF_INET, SOCK_STREAM, inet_aton, pack_sockaddr_in και τις υπόλοιπες σταθερές και packers που περνάτε στην socket

  • $^F - κατώφλι περιγραφέα που ελέγχει το close-on-exec για τη νέα υποδοχή