socket — מודול socket¶
מודול זה מספק גישה לממשק socket של BSD.
הבדל מ-CPython
לשם יעילות ועקביות, אובייקטי socket ב-MicroPython מממשים ממשק stream (דמוי קובץ) באופן ישיר. ב-CPython, יש להמיר socket לאובייקט דמוי קובץ באמצעות המתודה makefile(). מתודה זו עדיין נתמכת על ידי MicroPython (אך אינה מבצעת דבר), כך שכאשר תאימות ל-CPython חשובה, הקפידו להשתמש בה.
תבנית/תבניות כתובת socket¶
תבנית כתובת ה-socket המקורית של מודול socket היא סוג נתונים אטום המוחזר על ידי הפונקציה getaddrinfo(), שיש להשתמש בה לפענוח כתובת טקסטואלית (כולל כתובות מספריות):
sockaddr = socket.getaddrinfo('www.micropython.org', 80)[0][-1]
# You must use getaddrinfo() even for numeric addresses
sockaddr = socket.getaddrinfo('127.0.0.1', 80)[0][-1]
# Now you can use that address
sock.connect(sockaddr)
שימוש ב-getaddrinfo() הוא הדרך היעילה ביותר (הן מבחינת זיכרון והן מבחינת כוח עיבוד) והניידת ביותר לעבודה עם כתובות.
מודול socket מספק גם דרך תואמת-CPython לציון כתובות באמצעות tuples, כמתואר להלן. ב-OpenMV Cam מודול socket מובנה; ניתן לתת כתובות מספריות ישירות בתבנית ה-tuple, אך שמות מתחם יש לפענח תחילה באמצעות getaddrinfo().
לסיכום:
השתמשו תמיד ב-
getaddrinfo()כדי לפענח שמות מארחים.כתובות tuple המתוארות להלן יכולות לשמש כקיצור לכתובות מספריות, להאקים מהירים ולשימוש אינטראקטיבי.
תבנית כתובת tuple עבור מודול socket:
IPv4: (ipv4_address, port), כאשר ipv4_address היא מחרוזת עם כתובת IPv4 מספרית בכתיב נקודות, למשל
"8.8.8.8", ו-port הוא מספר פורט שלם בטווח 1-65535. שמות מתחם אינם מתקבלים כ-ipv4_address; פענחו אותם תחילה באמצעותgetaddrinfo().IPv6: (ipv6_address, port, flowinfo, scopeid), כאשר ipv6_address היא מחרוזת עם כתובת IPv6 מספרית בכתיב נקודתיים, למשל
"2001:db8::1", ו-port הוא מספר פורט שלם בטווח 1-65535. flowinfo חייב להיות 0. scopeid הוא מזהה ההיקף של הממשק עבור כתובות link-local. שמות מתחם אינם מתקבלים כ-ipv6_address; פענחו אותם תחילה באמצעותgetaddrinfo().
פונקציות¶
- socket.getaddrinfo(host: str, port: int, af: int = 0, type: int = 0, proto: int = 0, flags: int = 0, /) List[Tuple]¶
מתרגם את ארגומנט המארח/הפורט לרצף של 5-tuples המכילים את כל הארגומנטים הדרושים ליצירת socket המחובר לאותו שירות. הארגומנטים af, type ו-proto (בעלי אותה משמעות כמו עבור הפונקציה
socket) יכולים לשמש לסינון סוגי הכתובות המוחזרות. אם פרמטר אינו מצוין או הוא אפס, ניתן להחזיר את כל צירופי הכתובות (מה שמחייב סינון בצד המשתמש).רשימת ה-5-tuples המתקבלת היא בעלת המבנה הבא:
(family, type, proto, canonname, sockaddr)הדוגמה הבאה מראה כיצד להתחבר ל-url נתון:
s = socket.socket() # This assumes that if "type" is not specified, an address for # SOCK_STREAM will be returned, which may be not true s.connect(socket.getaddrinfo('www.micropython.org', 80)[0][-1])
שימוש מומלץ בפרמטרי הסינון:
s = socket.socket() # Guaranteed to return an address which can be connect'ed to for # stream operation. s.connect(socket.getaddrinfo('www.micropython.org', 80, 0, SOCK_STREAM)[0][-1])
הבדל מ-CPython
CPython מעלה חריגת
socket.gaierror(תת-מחלקה שלOSError) במקרה של שגיאה בפונקציה זו. ב-MicroPython איןsocket.gaierrorוהיא מעלה OSError ישירות. שימו לב שמספרי השגיאה שלgetaddrinfo()מהווים מרחב שמות נפרד ועשויים שלא להתאים למספרי השגיאה ממודולerrno. כדי להבחין בשגיאותgetaddrinfo(), הן מיוצגות על ידי מספרים שליליים, בעוד ששגיאות מערכת סטנדרטיות הן מספרים חיוביים (ניתן לגשת למספרי השגיאה באמצעות המאפייןe.args[0]מאובייקט חריגה). השימוש בערכים שליליים הוא פרט זמני שעשוי להשתנות בעתיד.
קבועים¶
- socket.IPPROTO_IP: int¶
רמת פרוטוקול ה-IP. משמש כארגומנט level ל-
setsockopt()יחד עם אפשרויותIP_*.
- socket.IPPROTO_TCP: int¶
פרוטוקול ה-TCP. אינכם צריכים להעביר זאת ל-
socket(סוג ה-socketSOCK_STREAMבוחר אותו אוטומטית); השימוש האמיתי היחיד בו הוא כארגומנט level ל-setsockopt()יחד עם אפשרויותTCP_*.
- socket.SOL_SOCKET: int¶
רמת אפשרות ה-socket. משמש כארגומנט level ל-
setsockopt()יחד עם אפשרויותSO_*.
- socket.SO_SNDTIMEO: int¶
פסק זמן לשליחה, באלפיות שנייה, המועבר כארגומנט value ל-
setsockopt().
- socket.SO_RCVTIMEO: int¶
פסק זמן לקבלה, באלפיות שנייה, המועבר כארגומנט value ל-
setsockopt().
- socket.IP_ADD_MEMBERSHIP: int¶
הצטרפות לקבוצת multicast. אפשרות
setsockopt()ברמתIPPROTO_IP.
- socket.IP_DROP_MEMBERSHIP: int¶
עזיבת קבוצת multicast. אפשרות
setsockopt()ברמתIPPROTO_IP.
- socket.TCP_NODELAY: int¶
השבתת האלגוריתם של Nagle. אפשרות
setsockopt()ברמתIPPROTO_TCP.
- socket.MSG_PEEK: int¶
עבור
recv()/recvfrom(): מחזיר נתונים מבלי להסירם מתור הקלט.
- socket.MSG_DONTWAIT: int¶
עבור
recv()/recvfrom(): מבצע את הפעולה במצב ללא חסימה.
מחלקות¶
- class socket.socket(af: int = AF_INET, type: int = SOCK_STREAM, proto: int = IPPROTO_TCP, /)¶
יוצר socket חדש באמצעות משפחת הכתובות, סוג ה-socket ומספר הפרוטוקול הנתונים. ציון proto אינו נדרש ברוב המקרים (ואינו מומלץ); ארגומנט ה-type בוחר את הפרוטוקול הדרוש אוטומטית:
# Create STREAM TCP socket socket(AF_INET, SOCK_STREAM) # Create DGRAM UDP socket socket(AF_INET, SOCK_DGRAM)
- close() None¶
מסמן את ה-socket כסגור ומשחרר את כל המשאבים. ברגע שזה קורה, כל הפעולות העתידיות על אובייקט ה-socket ייכשלו. הקצה המרוחק יקבל חיווי EOF אם הפרוטוקול תומך בכך.
sockets נסגרים אוטומטית כאשר הם נאספים על ידי איסוף הזבל, אך מומלץ לסגור אותם במפורש באמצעות
close()מיד עם סיום העבודה איתם.
- listen(backlog: int = 2) None¶
מאפשר לשרת לקבל חיבורים. אם backlog מצוין, הוא חייב להיות לפחות 0 (אם הוא נמוך יותר, הוא ייקבע ל-0); והוא מציין את מספר החיבורים שלא התקבלו שהמערכת תאפשר לפני שתסרב לחיבורים חדשים. אם אינו מצוין, נבחר ערך סביר כברירת מחדל.
- accept() Tuple['socket', Tuple]¶
מקבל חיבור. ה-socket חייב להיות קשור לכתובת ולהאזין לחיבורים. ערך ההחזרה הוא זוג (conn, address) כאשר conn הוא אובייקט socket חדש שניתן להשתמש בו לשליחה ולקבלה של נתונים בחיבור, ו-address היא הכתובת הקשורה ל-socket בקצה השני של החיבור.
- send(bytes: bytes) int¶
שולח נתונים ל-socket. ה-socket חייב להיות מחובר ל-socket מרוחק. מחזיר את מספר הבייטים שנשלחו, שעשוי להיות קטן מאורך הנתונים (”short write“).
- sendall(bytes: bytes) None¶
שולח את כל הנתונים ל-socket. ה-socket חייב להיות מחובר ל-socket מרוחק. בניגוד ל-
send(), מתודה זו תנסה לשלוח את כל הנתונים, על ידי שליחת הנתונים מקטע אחר מקטע ברצף.התנהגות מתודה זו על sockets ללא חסימה אינה מוגדרת. עקב כך, ב-MicroPython, מומלץ להשתמש במתודה
write()במקום, אשר בעלת אותה מדיניות ”ללא short writes“ עבור sockets חוסמים, ותחזיר את מספר הבייטים שנשלחו עבור sockets ללא חסימה.
- recv(bufsize: int, flags: int = 0) bytes¶
מקבל נתונים מה-socket. ערך ההחזרה הוא אובייקט bytes המייצג את הנתונים שהתקבלו. הכמות המרבית של נתונים שתתקבל בבת אחת מצוינת על ידי bufsize.
הארגומנט האופציונלי flags הוא OR ביטווייז של דגלי הודעה (
MSG_PEEK,MSG_DONTWAIT), בעלי אותה משמעות כמו ב-CPython.
- sendto(bytes: bytes, address: Any) int¶
שולח נתונים ל-socket. ה-socket אינו אמור להיות מחובר ל-socket מרוחק, מכיוון שה-socket היעד מצוין על ידי address.
- recvfrom(bufsize: int, flags: int = 0) Tuple[bytes, Tuple]¶
מקבל נתונים מה-socket. ערך ההחזרה הוא זוג (bytes, address) כאשר bytes הוא אובייקט bytes המייצג את הנתונים שהתקבלו ו-address היא הכתובת של ה-socket השולח את הנתונים.
ראו את הפונקציה
recv()להסבר על הארגומנט האופציונלי flags.
- setsockopt(level: int, optname: int, value: int | bytes) None¶
מגדיר את הערך של אפשרות ה-socket הנתונה. הקבועים הסמליים הדרושים מוגדרים במודול socket (SO_* וכו«). ה-value יכול להיות מספר שלם או אובייקט דמוי bytes המייצג חוצץ (buffer).
- settimeout(value: float | None) None¶
מגדיר פסק זמן על פעולות socket חוסמות. ארגומנט הערך יכול להיות מספר נקודה צפה אי-שלילי המבטא שניות, או None. אם ניתן ערך שאינו אפס, פעולות socket עוקבות יעלו חריגת
OSErrorאם תקופת פסק הזמן חלפה לפני שהפעולה הושלמה. אם ניתן אפס, ה-socket מועבר למצב ללא חסימה. אם ניתן None, ה-socket מועבר למצב חוסם.חלופה ניידת וכללית היא להשתמש באובייקט
select.poll. זה מאפשר המתנה למספר אובייקטים בו-זמנית (ולא רק ל-sockets, אלא לאובייקטי stream כלליים התומכים ב-polling). דוגמה:# Instead of: s.settimeout(1.0) # time in seconds s.read(10) # may timeout # Use: poller = select.poll() poller.register(s, select.POLLIN) res = poller.poll(1000) # time in milliseconds if not res: # s is still not ready for input, i.e. operation timed out
הבדל מ-CPython
CPython מעלה חריגת
socket.timeoutבמקרה של פסק זמן, שהיא תת-מחלקה שלOSError. במקום זאת, MicroPython מעלה OSError ישירות. אם תשתמשו ב-except OSError:כדי לתפוס את החריגה, הקוד שלכם יעבוד הן ב-MicroPython והן ב-CPython.
- setblocking(flag: bool) None¶
מגדיר מצב חוסם או ללא חסימה של ה-socket: אם flag הוא false, ה-socket נקבע למצב ללא חסימה, אחרת למצב חוסם.
מתודה זו היא קיצור עבור קריאות
settimeout()מסוימות:sock.setblocking(True)שקול ל-sock.settimeout(None)sock.setblocking(False)שקול ל-sock.settimeout(0)
- makefile(mode: str = 'rb', buffering: int = 0, /) Any¶
מחזיר אובייקט קובץ המשויך ל-socket. הסוג המדויק המוחזר תלוי בארגומנטים שניתנו ל-makefile(). התמיכה מוגבלת למצבים בינאריים בלבד (»rb«, »wb«, ו-»rwb«). הארגומנטים של CPython: encoding, errors ו-newline אינם נתמכים.
הבדל מ-CPython
מכיוון ש-MicroPython אינו תומך בזרמים מאוחסנים בחוצץ (buffered), ערכי הפרמטר buffering מתעלמים מהם ומתייחסים אליהם כאילו היו 0 (ללא חוצץ).
הבדל מ-CPython
סגירת אובייקט הקובץ המוחזר על ידי makefile() תסגור גם את ה-socket המקורי.
- read(size: int | None = None) bytes¶
קורא עד size בייטים מה-socket. מחזיר אובייקט bytes. אם size אינו ניתן, הוא קורא את כל הנתונים הזמינים מה-socket עד EOF; ככזה, המתודה לא תחזור עד שה-socket ייסגר. פונקציה זו מנסה לקרוא כמה שיותר נתונים כמבוקש (ללא ”short reads“). ייתכן שזה לא יתאפשר עם socket ללא חסימה, ואז יוחזרו פחות נתונים.