סוקטים

send#

שולח הודעה על סוקט.

send כותב את הסקלר MSG ל־SOCKET דרך שכבת הסוקטים של מערכת ההפעלה, לא דרך PerlIO. על סוקט מחובר (SOCK_STREAM לאחר connect, או עמית מתקבל) הצורה תלת־ארגומנטית מנפיקה send(2) - השתמשו בצורה ארבע־ארגומנטית על סוקט datagram לא־מחובר (SOCK_DGRAM) כדי לנתב כל הודעה ל־TO, מה שמפעיל sendto(2) תחת המכסה. FLAGS היא המסכה הביטית שקריאת המערכת מקבלת (בדרך כלל 0; ראו את דף ה־man של send(2) של הפלטפורמה שלכם עבור MSG_DONTWAIT, MSG_OOB, MSG_NOSIGNAL, וחבריהם).

תקציר#

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

מה מקבלים בחזרה#

מספר הבתים שהקרנל קיבל, או undef בשגיאה כאשר $! מוגדר. תמיד בדקו את ערך ההחזרה:

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

שתי תכונות נושכות אנשים:

  • הספירה היא בתים, לא תווים. length $buf על מחרוזת רחבה והספירה המוחזרת לא יסכימו.

  • על סוקטי SOCK_STREAM הקרנל עשוי לקבל פחות בתים ממה שנתתם לו - כתיבה קצרה. בצעו לולאה עד שכל ה־buffer נוקז, או השתמשו ב־syswrite שיש לו את אותה סמנטיקת כתיבה קצרה אך עובד על כל מטפל קובץ.

מצב גלובלי שהוא נוגע בו#

  • $! - מוגדר לשגיאת המערכת בכישלון.

  • מחסנית שכבת PerlIO של הסוקט אינה נבדקת. שכבות פלט (:utf8, :encoding(...), :crlf) אין להן השפעה על מה ש־send כותב. בפרט, שכבת :utf8 גורמת ל־send לזרוק חריגה במקום לקודד בשקט - שכבת הסוקט ושכבת PerlIO אינן יכולות שתיהן להחזיק במסגור בתים.

דוגמאות#

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: $!";

טיפול בכתיבות קצרות על סוקט stream:

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 אם buffer הקרנל מלא:

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: $!";
    }
}

מקרי קצה#

  • תווים רחבים: העברת מחרוזת עם נקודות קוד מעל 0xFF על סוקט בתים כותבת את קידוד ה־UTF-8 של כל תו ופולטת אזהרה Wide character in send תחת use warnings. קודדו במפורש עם Encode::encode לפני קריאה ל־send.

  • שכבת :utf8 על הסוקט: send זורק שגיאה. או פתחו את הסוקט ללא השכבה, או קראו ל־binmode $sock כדי לפשוט אותה לפני ה־send הראשון. שכבת :encoding(...) מוסיפה במשתמע :utf8, אז גם היא אסורה.

  • צורה ארבע־ארגומנטית על סוקט מחובר: העברת TO לסוקט SOCK_STREAM מחובר היא שגיאה - הקרנל מחזיר EISCONN. השתמשו בצורה תלת־ארגומנטית לאחר ההתחברות.

  • צורה תלת־ארגומנטית על סוקט datagram לא־מחובר: נכשל עם ENOTCONN (או EDESTADDRREQ בחלק מהפלטפורמות). או בצעו connect על סוקט ה־datagram קודם (מה שנועל עמית ברירת מחדל), או ספקו TO.

  • MSG ריק על UDP: תקף - שולח datagram באורך אפס שהעמית יכול לקרוא עם recv. על TCP זה no-op שמחזיר 0.

  • SIGPIPE על עמית stream סגור: כתיבה ל־SOCK_STREAM שהקצה המרוחק שלו נסגר מעלה SIGPIPE, שכברירת מחדל מסיים את התהליך. העבירו MSG_NOSIGNAL ב־FLAGS (Linux) או התקינו $SIG{PIPE} = 'IGNORE' כדי לקבל החזרת EPIPE במקום.

  • sendmsg(2): Perl חושף send/sendto, לא sendmsg. כתיבות scatter/gather ונתונים מסייעים (אישורים, descriptorים של קובץ מעל AF_UNIX) דורשים מודול XS כגון Socket::MsgHdr.

  • מטפל קובץ שאינו סוקט: send על לא־סוקט מחזיר undef כאשר $! מוגדר ל־ENOTSOCK. השתמשו ב־syswrite ל־pipeים וקבצים רגילים.

הבדלים מהמקור#

תאימות מלאה עם Perl 5.42 המקורי.

ראו גם#

  • recv - ההפוך; קורא בתים מסוקט עם אותן הגבלות שכבה ואותו ארגומנט FLAGS

  • syswrite - כתיבה גולמית שעוקפת buffering של PerlIO על כל מטפל קובץ; השתמשו בה ל־pipeים וקבצים שבהם send מסרב לעבוד

  • connect - קובע את כתובת העמית שמאפשרת לכם להשתמש בצורה תלת־ארגומנטית של send

  • socket - יוצר את מטפל הקובץ ש־send כותב אליו; סוג הסוקט (SOCK_STREAM לעומת SOCK_DGRAM) קובע איזו צורה של send חוקית

  • bind - מקצה כתובת מקומית; דרוש לפני send על סוקט datagram אם העמית מצפה לתשובות לפורט ידוע

  • binmode - פושט שכבת :utf8 תועה שאחרת תגרום ל־send לזרוק שגיאה