socket#
יצירת מטפל קובץ של סוקט.
socket פותח סוקט מהסוג המתואר על ידי DOMAIN, TYPE, ו־PROTOCOL ומחבר אותו ל־SOCKET, שהופך למטפל קובץ שמיש של Perl. זוהי ציפוי דק של Perl מעל קריאת המערכת socket(2) - לא יותר, לא פחות. הסוקט החדש אינו קשור ואינו מחובר; אתם עדיין זקוקים ל־bind, connect, או listen+accept כדי לעשות איתו משהו. ייבאו את הקבועים הסימבוליים עם use Socket; לפני הקריאה - כתיבת השלמים הגולמיים ניידת רק במקרה.
תקציר#
use Socket;
socket SOCKET, DOMAIN, TYPE, PROTOCOL
מה מקבלים בחזרה#
1 בהצלחה, undef בכישלון (כאשר $! מוגדר ל־errno מ־socket(2) הבסיסי). בהצלחה SOCKET הוא כעת מטפל קובץ שניתן לבצע עליו bind, connect, send / recv, או לקרוא ולכתוב עם אופרטורי קלט/פלט רגילים ברגע שהוא מגיע למצב מחובר. ערך ההחזרה שווה לבדיקה בכל קריאה - כישלון כאן משמעו שאין לכם משהו שימושי להעביר לקריאת הסוקט הבאה, שאז תיכשל בדרך מבלבלת יותר.
socket my $sock, PF_INET, SOCK_STREAM, getprotobyname("tcp")
or die "socket: $!";
SOCKET יכול להיות מטפל קובץ של bareword (SOCK), glob (*SOCK), או סקלר לא־מוגדר שיעבור autovivify להפניה אנונימית למטפל קובץ. הצורה שעברה autovivify היא הניב המודרני והיחיד שמתחם נקי עם my.
מצב גלובלי שהוא נוגע בו#
$!- מוגדר ל־errnoמ־socket(2)בכישלון.$^F- סף ה־descriptor של המערכת. על מערכות עם close-on-exec, ה־descriptor החדש מקבלFD_CLOEXECמוגדר כאשר המספר שלו עולה על$^F(ברירת מחדל2, כך ש־descriptorים 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, האזנה:
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: $!";
סוקט stream של תחום 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, לא קבועים שלמים, והקריאה נכשלת בגבול ה־syscall עםInvalid argument. הייבוא הוא מה שהופך אותם למספרים.SOCKETמודרס בהצלחה. אם החריץ מחזיק מטפל קובץ פתוח, הוא נסגר קודם. אין אזהרה - הסוקט הקודם פשוט נעלם בשקט. השתמשו במשתנהmyרענן לכל קריאה.כישלון משאיר את
SOCKETללא שינוי. בהחזרתundefהסקלר אינו נפתח ואינו משונה; ערך קודם (כולל סוקט מוקדם יותר שעדיין פתוח) עדיין שם.גבולות descriptor.
socketהיא הנקודה שבה מיצוי טבלת ה־descriptorEMFILE(לכל־תהליך) ו־ENFILE(כלל־מערכתי) צץ. שרתים ארוכי־ריצה צריכים להתייחס אליהם כברי־התאוששות ולא כקטלניים.EAFNOSUPPORT/EPROTONOSUPPORT/ESOCKTNOSUPPORT. הקרנל דחה את השלשה domain/type/protocol. סיבה נפוצה: בקשתPF_INET6על קרנל שנבנה ללא IPv6, או מספר פרוטוקול לא חוקי שעבר מחיפושgetprotobynameישן.מצב לא־חוסם הוא צעד נפרד.
socketמחזיר descriptor חוסם. השתמשו ב־fcntlעםF_SETFL+O_NONBLOCK(או המקבילה שלIO::Socket) אם אתם זקוקים לקלט/פלט לא־חוסם.Close-on-exec הוא אוטומטי מעבר ל־
$^F. Perl מגדירFD_CLOEXECעל ה־descriptor החדש כאשר מספר ה־fd שלו גדול מ־$^F. סוקט לא ישרוד אם כןexecאלא אם הורדתם את הסף הזה או ניקיתם את הדגל עםfcntl.ערכי domain/type מספריים אינם ניידים.
2במקרה הואAF_INETב־Linux; הוא משהו אחר במקומות אחרים. תמיד עברו דרך קבועי המודולSocket.
הבדלים מהמקור#
תאימות מלאה עם Perl 5.42 המקורי.
ראו גם#
bind- חיבור סוקט שנוצר על ידיsocketלכתובת מקומית, דרוש לפניlistenאו לפני שליחה מפורט ידועconnect- יוזם חיבור יוצא על סוקטSOCK_STREAM, או מגדיר את עמית ברירת המחדל על סוקטSOCK_DGRAMlisten- סימון סוקטSOCK_STREAMקשור כפסיבי כדי ש־acceptיוכל למשוך ממנו חיבוריםaccept- מחזיר את החיבור הבא הממתין על סוקט מאזין כמטפל קובץ רענןsocketpair- יצירת זוג סוקטים מחוברים בקריאה אחת; הבחירה הרגילה כששני הקצוות חיים באותו תהליך או הורה/ילדSocket- המודול שמספק אתPF_INET,SOCK_STREAM,inet_aton,pack_sockaddr_inושאר הקבועים והאורזים שמעבירים ל־socket$^F- סף descriptor ששולט ב־close-on-exec עבור הסוקט החדש