socketpair#
יוצר זוג סוקטים ללא שם, מחוברים, שמדברים זה עם זה.
socketpair פותח שני מטפלי קובץ רעננים ב־SOCKET1 וב־SOCKET2 כבר מחווטים יחד, כך שכל דבר שנכתב לאחד יוצא מהאחר. אין כתובות, אין bind, אין listen, אין accept. השימוש הנפוץ ביותר הוא לדבר עם תהליך־ילד שנוצר על־ידי fork - כל צד שומר מטפל אחד ועושה close לאחר.
תקציר#
use Socket;
socketpair(SOCKET1, SOCKET2, DOMAIN, TYPE, PROTOCOL) or die $!;
socketpair(my $s1, my $s2, AF_UNIX, SOCK_STREAM, PF_UNSPEC) or die $!;
מה מקבלים בחזרה#
אמת בהצלחה, שקר בכישלון (כש־$! מוגדר). בהצלחה שני ארגומנטי מטפלי הקובץ מאוכלסים במטפלים רעננים; בכישלון הם נשארים ללא שינוי. תמיד בדוק את ערך ההחזרה - כל שילוב של domain/type/protocol תלוי בפלטפורמה.
socketpair(my $a, my $b, AF_UNIX, SOCK_STREAM, PF_UNSPEC)
or die "socketpair: $!";
הקבועים DOMAIN, TYPE, ו־PROTOCOL מגיעים ממודול Socket. AF_UNIX עם SOCK_STREAM ו־PF_UNSPEC הוא ברירת המחדל הניידת.
מצב גלובלי שהוא נוגע בו#
$!מוגדר בכישלון ל־errnoשל המערכת.$^F- file descriptor המקסימלי של המערכת שמתחתיו close-on-exec אינו מוגדר. במערכות עםFD_CLOEXEC, descriptors מעל$^Fמקבלים close-on-exec אוטומטית; מתחתיו, הם שורדיםexec. ברירת המחדל היא2(stdin/stdout/stderr). הגבה אותו לפניsocketpairאם אתה רוצה שהמטפלים החדשים יירשו דרךexec.
דוגמאות#
pipe רגיל של הורה/ילד תוך שימוש ב־stream socketpair. כל צד סוגר את הקצה שאינו זקוק לו, כך ש־EOF מתפשט נכון:
use Socket;
socketpair(my $child, my $parent, AF_UNIX, SOCK_STREAM, PF_UNSPEC)
or die "socketpair: $!";
my $pid = fork // die "fork: $!";
if ($pid == 0) {
close $child;
print $parent "hello from child\n";
close $parent;
exit;
}
close $parent;
chomp(my $msg = <$child>); # "hello from child"
waitpid $pid, 0;
זרם דו־כיווני: שני התהליכים קוראים וגם כותבים על אותו מטפל. אין צורך ב־shutdown מאחר שאף צד אינו סוגר כיוון מוקדם:
use Socket;
socketpair(my $a, my $b, AF_UNIX, SOCK_STREAM, PF_UNSPEC) or die $!;
my $pid = fork // die $!;
if ($pid == 0) {
close $a;
while (my $line = <$b>) {
chomp $line;
print $b "echo: $line\n";
}
exit;
}
close $b;
print $a "ping\n";
chomp(my $reply = <$a>); # "echo: ping"
close $a;
waitpid $pid, 0;
אמולציה של pipe עם socketpair. shutdown הופך סוקט דו־כיווני לערוץ חד־כיווני:
use Socket;
socketpair(my $rdr, my $wtr, AF_UNIX, SOCK_STREAM, PF_UNSPEC) or die $!;
shutdown($rdr, 1); # reader cannot write
shutdown($wtr, 0); # writer cannot read
זוג datagram - הודעות שומרות גבולות, כך ש־recv יחיד מחזיר בדיוק send אחד:
use Socket;
socketpair(my $a, my $b, AF_UNIX, SOCK_DGRAM, PF_UNSPEC) or die $!;
send($a, "one", 0) or die $!;
send($a, "two", 0) or die $!;
recv($b, my $m1, 64, 0); # "one"
recv($b, my $m2, 64, 0); # "two"
מקרי קצה#
AF_UNIXהוא ה־domain הנייד היחיד. ברוב המערכותsocketpairעובד רק עםAF_UNIX; משפחות אחרות מחזירותEAFNOSUPPORT. השתמש בקבוע, לא ב־1מקודד־קשיח.פלט לא־מאוגר. מטפלי stream socketpair מאוגרים כמו כל מטפל קובץ אחר. הגדר את
$|על הכותב (לאחרselectשלו) או שהקורא יחסום בהמתנה לפלט שעדיין נמצא ב־buffer של ההורה.autoflushמ־IO::Handleהוא הצורה הרגילה:$parent->autoflush(1);
סגור את שני הקצוות אחרת EOF לעולם לא מגיע. stream socketpair מספק EOF על קורא רק לאחר שכל עותק כתיב של מטפל העמית נסגר. ילד ששוכח לעשות
closeלקצה ההורה יתלה את ההורה על<$handle>לנצח.Close-on-exec דרך
$^F. מטפלי קובץ שה־descriptor המספרי שלהם גדול מ־$^FמקבליםFD_CLOEXECבפלטפורמות שתומכות בכך, כך שהם נעלמים דרךexec. הגבה את$^Fלפני הקריאה אם המטפל חייב לשרודexec.לא ממומש בפלטפורמה. אם קריאת המערכת
socketpair(2)הבסיסית אינה קיימת, perl מעלה חריגה במקום להחזיר שקר. לכוד עםevalאם אתה צריך ליפול חזרה.Datagram מול stream.
SOCK_STREAMהוא מוכוון־בתים (אין גבולות הודעה, השתמש במסגור שורות חדשות או קידומות אורך).SOCK_DGRAMשומר גבולות הודעה אך מאבד אותם בשקט אם buffer הקבלה קטן מההודעה.PROTOCOL. עבורAF_UNIXהפרוטוקול נשכח מהלב;PF_UNSPEC(או0) הוא מקובל. ציון פרוטוקול שאינו תואם לשילוב domain/type מחזירEPROTONOSUPPORT.
הבדלים מהמקור#
תאימות מלאה עם Perl 5.42 המקורי.
ראו גם#
socket- יוצר סוקט יחיד כאשר רק קצה אחד שייך לך (השני מגיע מהרשת דרךacceptאוconnect)pipe- ערוץ בתים חד־כיווני; קל יותר מ־socketpairאך אינו יכול לבצע תעבורה דו־כיוונית בקריאה אחתsend/recv- I/O מוכוון־הודעות, נדרש עבור זוגות סוקטיםSOCK_DGRAMfork- השותף האופייני:socketpairאחד לפני ה־fork נותן להורה ולילד צינור מן המוכןSocket- מקור שלAF_UNIX,SOCK_STREAM,SOCK_DGRAM,PF_UNSPECוהקבועים האחרים ש־socketpairמצפה להם$^F- סף שמעליו descriptors חדשים מקבלים close-on-exec; חשוב כאשר המטפלים חייבים לשרודexec