Υποδοχές (sockets)

send#

Στέλνει ένα μήνυμα σε μια υποδοχή.

Η send γράφει το βαθμωτό MSG στο SOCKET μέσω του στρώματος υποδοχών του λειτουργικού συστήματος, όχι μέσω PerlIO. Σε συνδεδεμένη υποδοχή (SOCK_STREAM μετά από connect, ή αποδεκτό ομότιμο) η μορφή τριών ορισμάτων εκδίδει μια send(2) - χρησιμοποιήστε τη μορφή τεσσάρων ορισμάτων σε μη συνδεδεμένη υποδοχή datagram (SOCK_DGRAM) για να δρομολογήσετε κάθε μήνυμα στο TO, κάτι που πυροδοτεί την sendto(2) στο παρασκήνιο. Το FLAGS είναι η μάσκα bits που δέχεται η κλήση συστήματος (συνήθως 0· δείτε το man page της πλατφόρμας σας για την send(2) σχετικά με MSG_DONTWAIT, MSG_OOB, MSG_NOSIGNAL και παρόμοια).

Σύνοψη#

send SOCKET, MSG, FLAGS, TO
send SOCKET, MSG, FLAGS

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

Το πλήθος των bytes που έγιναν δεκτά από τον πυρήνα, ή undef σε σφάλμα με ρυθμισμένο το $!. Ελέγχετε πάντα την τιμή επιστροφής:

my $n = send $sock, $buf, 0
    or die "send failed: $!";

Δύο ιδιότητες δαγκώνουν τους χρήστες:

  • Το πλήθος είναι bytes, όχι χαρακτήρες. Το length $buf σε συμβολοσειρά πλατιών χαρακτήρων και το επιστρεφόμενο πλήθος δεν θα συμφωνούν.

  • Σε υποδοχές SOCK_STREAM ο πυρήνας ενδέχεται να δεχτεί λιγότερα bytes από όσα του δώσατε - σύντομη εγγραφή. Επαναλάβετε σε βρόχο μέχρι να εκκενωθεί ολόκληρος ο ενταμιευτής, ή χρησιμοποιήστε syswrite που έχει την ίδια σημασιολογία σύντομης εγγραφής αλλά λειτουργεί σε οποιοδήποτε filehandle.

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

  • $! - τίθεται στο σφάλμα του συστήματος σε αποτυχία.

  • Η στοίβα στρωμάτων PerlIO της υποδοχής δεν συμβουλεύεται. Τα στρώματα εξόδου (:utf8, :encoding(...), :crlf) δεν έχουν καμία επίδραση σε αυτό που γράφει η send. Ειδικότερα, ένα στρώμα :utf8 κάνει την send να ρίξει εξαίρεση αντί να κωδικοποιήσει σιωπηλά - το στρώμα υποδοχής και το στρώμα PerlIO δεν μπορούν να κατέχουν και τα δύο το byte framing.

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

Συνδεδεμένο TCP - μορφή τριών ορισμάτων:

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

Μη συνδεδεμένο UDP - μορφή τεσσάρων ορισμάτων με ρητό προορισμό:

use Socket;
socket my $sock, PF_INET, SOCK_DGRAM, getprotobyname("udp")
    or die "socket: $!";
my $to = sockaddr_in(514, inet_aton("10.0.0.1"));
send $sock, "<14>hello syslog\n", 0, $to
    or die "send: $!";

Χειρισμός σύντομων εγγραφών σε υποδοχή ροής:

my $offset = 0;
while ($offset < length $buf) {
    my $n = send $sock, substr($buf, $offset), 0;
    defined $n or die "send: $!";
    $offset += $n;
}

Αποστολή με σημαία - το MSG_DONTWAIT κάνει μία μη μπλοκαριστική προσπάθεια και επιστρέφει undef με το $! ρυθμισμένο σε EAGAIN/EWOULDBLOCK αν ο ενταμιευτής του πυρήνα είναι γεμάτος:

use Socket qw(MSG_DONTWAIT);
my $n = send $sock, $buf, MSG_DONTWAIT;
if (!defined $n) {
    if ($!{EAGAIN} || $!{EWOULDBLOCK}) {
        # back off, retry later
    } else {
        die "send: $!";
    }
}

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

  • Πλατιοί χαρακτήρες: το πέρασμα συμβολοσειράς με codepoints πάνω από 0xFF σε υποδοχή bytes γράφει την κωδικοποίηση UTF-8 κάθε χαρακτήρα και εκπέμπει προειδοποίηση Wide character in send υπό use warnings. Κωδικοποιήστε ρητά με Encode::encode πριν την κλήση της send.

  • Στρώμα :utf8 στην υποδοχή: η send πεθαίνει. Είτε ανοίξτε την υποδοχή χωρίς το στρώμα, είτε καλέστε binmode $sock για να το αφαιρέσετε πριν την πρώτη send. Ένα στρώμα :encoding(...) προσθέτει σιωπηρά το :utf8, οπότε απαγορεύεται και αυτό.

  • Μορφή τεσσάρων ορισμάτων σε συνδεδεμένη υποδοχή: το πέρασμα TO σε συνδεδεμένη υποδοχή SOCK_STREAM είναι σφάλμα - ο πυρήνας επιστρέφει EISCONN. Χρησιμοποιήστε τη μορφή τριών ορισμάτων αφού γίνει η σύνδεση.

  • Μορφή τριών ορισμάτων σε μη συνδεδεμένη υποδοχή datagram: αποτυγχάνει με ENOTCONNEDESTADDRREQ σε ορισμένες πλατφόρμες). Είτε connect-άρετε πρώτα την υποδοχή datagram (που καρφώνει έναν προεπιλεγμένο ομότιμο), είτε παρέχετε το TO.

  • Κενό MSG σε UDP: έγκυρο - στέλνει datagram μηδενικού μήκους που ο ομότιμος μπορεί να διαβάσει με recv. Σε TCP είναι no-op που επιστρέφει 0.

  • SIGPIPE σε κλεισμένο ομότιμο ροής: η εγγραφή σε SOCK_STREAM της οποίας ο απομακρυσμένος άκρος έχει κλείσει εγείρει SIGPIPE, που εξ ορισμού τερματίζει τη διεργασία. Περάστε MSG_NOSIGNAL στα FLAGS (Linux) ή εγκαταστήστε $SIG{PIPE} = 'IGNORE' για να λάβετε αντί αυτού επιστροφή EPIPE.

  • sendmsg(2): η Perl εκθέτει τις send/sendto, όχι την sendmsg. Οι scatter/gather εγγραφές και τα ancillary δεδομένα (credentials, file descriptors πάνω από AF_UNIX) απαιτούν άρθρωμα XS όπως το Socket::MsgHdr.

  • Μη-socket filehandle: η send σε μη-socket επιστρέφει undef με το $! ρυθμισμένο σε ENOTSOCK. Χρησιμοποιήστε syswrite για pipes και κανονικά αρχεία.

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

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

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

  • recv - η αντίστροφη· διαβάζει bytes από υποδοχή με τους ίδιους περιορισμούς στρωμάτων και το ίδιο όρισμα FLAGS

  • syswrite - ακατέργαστη εγγραφή που παρακάμπτει την ενταμίευση PerlIO σε οποιοδήποτε filehandle· χρησιμοποιήστε την για pipes και αρχεία όπου η send αρνείται να λειτουργήσει

  • connect - εγκαθιδρύει τη διεύθυνση ομότιμου που σας επιτρέπει να χρησιμοποιήσετε τη μορφή τριών ορισμάτων της send

  • socket - δημιουργεί το filehandle στο οποίο γράφει η send· ο τύπος υποδοχής (SOCK_STREAM έναντι SOCK_DGRAM) αποφασίζει ποια μορφή της send είναι νόμιμη

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

  • binmode - αφαιρεί ένα αδέσποτο στρώμα :utf8 που διαφορετικά θα έκανε την send να ρίξει εξαίρεση