סוקטים

recv#

קריאת הודעה נכנסת מסוקט לתוך סקלר.

recv קורא עד LENGTH בתים מ־SOCKET לתוך SCALAR, ומחליף את מה ש־SCALAR החזיק קודם לכן. SCALAR גדל או מתכווץ למספר הבתים שהתקבלו בפועל. FLAGS הוא אותה מסיכת ביטים שקריאת המערכת הבסיסית recvfrom(2) מקבלת - 0 לקריאות רגילות; הערכים השונים מ־0 הנפוצים הם MSG_PEEK (להציץ מבלי לצרוך), MSG_WAITALL (לחסום עד שיגיעו LENGTH בתים), ו־MSG_DONTWAIT (לעולם לא לחסום). עבור סוקט חסר־חיבור recv מחזיר את הכתובת הארוזה של השולח; עבור סוקט מחובר הוא מחזיר את המחרוזת הריקה. מתחת לכיסוי זוהי recvfrom(2), לא recv(2).

תקציר#

recv SOCKET, SCALAR, LENGTH, FLAGS

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

  • בהצלחה מסוקט חסר־חיבור (UDP, UNIX datagram): כתובת השולח כמחרוזת sockaddr ארוזה. בצעו unpack באמצעות sockaddr_in, sockaddr_in6, או sockaddr_un של Socket תלוי במשפחת הכתובות.

  • בהצלחה מסוקט מחובר (TCP, UDP מחובר): המחרוזת הריקה "". המחרוזת הריקה היא אמת עבור הבדיקה defined־מול־undef אך שקר בהקשר בוליאני - בדקו עם defined, לא אמיתיוּת פשוטה.

  • בשגיאה: undef, כאשר $! מוגדר ל־errno מקריאת recvfrom(2) הכושלת. שגיאות אופייניות: EAGAIN / EWOULDBLOCK בסוקט לא־חוסם ללא נתונים מוכנים, ECONNRESET באיפוס עמית TCP, EBADF במטפל סגור.

SCALAR תמיד משונה גודלו למספר הבתים שנקראו. קריאת אפס־בתים בסוקט זרם מחובר משמעה שהעמית סגר נקיות את צד הכתיבה שלו - recv מחזיר "" ו־SCALAR הופך למחרוזת הריקה.

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

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

  • שום משתנים מיוחדים אחרים אינם מעורבים. recv אינו מתחשב ב־$/, $,, או $\ - אלה מושגי I/O מוכווני־שורה ו־recv הוא פרימיטיב datagram גולמי / זרם־בתים.

דוגמאות#

קריאת datagram UDP אחד וזיהוי השולח:

use Socket;
my $from = recv($sock, my $buf, 1500, 0)
    or die "recv: $!";
my ($port, $ip) = sockaddr_in($from);
print "got ", length($buf), " bytes from ",
      inet_ntoa($ip), ":$port\n";

קריאה מסוקט TCP מחובר. כתובת השולח ריקה, אז בדקו עם defined במקום אמיתיוּת בוליאנית:

defined(recv($sock, my $buf, 4096, 0))
    or die "recv: $!";
# $buf now holds 0..4096 bytes; 0 means the peer closed.

הצצה ב־datagram הבא מבלי לצרוך אותו. הקריאה השנייה מחזירה את אותם בתים:

use Socket;
recv($sock, my $peek,    1500, MSG_PEEK) or die $!;
recv($sock, my $consume, 1500, 0)        or die $!;
# $peek and $consume hold the same datagram.

לולאת קריאה לא־חוסמת. EAGAIN / EWOULDBLOCK הוא הסיגנל הרגיל של ״אין נתונים עדיין״, לא שגיאה אמיתית:

use Errno qw(EAGAIN EWOULDBLOCK);
while (1) {
    my $from = recv($sock, my $buf, 1500, 0);
    unless (defined $from) {
        last if $! == EAGAIN || $! == EWOULDBLOCK;
        die "recv: $!";
    }
    handle_datagram($from, $buf);
}

כפיית קריאה באורך מלא בסוקט זרם שעלול לפצל את ההודעה - MSG_WAITALL חוסם עד ש־LENGTH בתים נכנסים או שהחיבור מת:

use Socket;
defined(recv($sock, my $frame, 64, MSG_WAITALL))
    or die "recv: $!";
# $frame is exactly 64 bytes, or the peer closed early.

מקרי קצה#

  • סוקט עם שכבת UTF-8: אם ל־SOCKET יש שכבת :utf8 (ישירות או דרך :encoding(...)), recv זורק חריגה. recv הוא מוכוון־בתים ואינו מתממשק עם שכבות PerlIO; השתמשו ב־binmode להסרת השכבה לפני הקריאה, או פענחו את הבתים שמתקבלים בעצמכם.

  • LENGTH מול גודל ה־datagram: עבור סוקטי datagram, אם LENGTH קטן מה־datagram הנכנס, העודף מושלך בשקט. סדרו את ה־buffer לגודל ה־MTU של הפרוטוקול (בדרך כלל 1500 עבור UDP על Ethernet, 65507 עבור המקסימום של UDP ב־IPv4).

  • ערך ההחזרה "" אינו ״שקרי־דיו״: recv בסוקט מחובר מחזיר את המחרוזת הריקה, ש־! מתייחס אליה כשקר. קוד כמו recv(...) or die $! מת על כל קריאת מחובר מוצלחת. השתמשו ב־defined:

    defined(recv($sock, $buf, $len, 0)) or die "recv: $!";
    
  • תוצאת אפס־בתים בסוקט זרם: recv מחזיר "" ו־SCALAR הופך לריק כאשר העמית ביצע shutdown מסודר. הבחינו בין סוף־זרם לשגיאה אמיתית על־ידי בדיקת length($buf) == 0 אחרי החזרה מוגדרת.

  • אותות: recv חוסם שמופרע על־ידי אות מחזיר undef כאשר $! == EINTR. נסו שוב או התקינו sigaction כראוי עם SA_RESTART אם זה לא מה שרציתם.

  • סוקט סגור: recv על מטפל סגור או שמעולם לא נפתח מחזיר undef, מגדיר את $! ל־EBADF, ופולט אזהרת recv() on closed socket תחת use warnings.

  • תוכן SCALAR קיים נהרס. recv אינו מצרף; הוא דורס. השתמשו בלקסיקל חדש או נקו את הסקלר לפני כל קריאה.

הבדלים מ־upstream#

תואם מלא ל־upstream Perl 5.42.

ראו גם#

  • send - צד הכתיבה של אותו סוקט; אותו אוצר־מילים של FLAGS, אותה הבחנה חסר־חיבור־מול־מחובר

  • socket - יצירת מטפל ה־SOCKET ש־recv קורא ממנו

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

  • connect - בעת שימוש בסוקט datagram, גורם ל־recv להחזיר "" כמו סוקט זרם ומסנן datagram־ים מעמיתים אחרים

  • sysread - קריאה ברמת בתים עבור סוקטי זרם כאשר לא נחוצה כתובת השולח; משתלב בלולאות מבוססות select

  • Socket - sockaddr_in, inet_ntoa, MSG_PEEK, MSG_WAITALL, ויתר הקבועים ש־recv צורך