9.11. אובייקטי Socket¶
ממשק ה-Python לשכבת התעבורה הוא המחלקה socket.socket. socket מייצג נקודת קצה אחת של שיחת רשת – כתובת, פורט, והפרוטוקול (UDP או TCP) שעליו רצה השיחה. פרקי שליטת החומרה פתחו מופעי UART כדי לדבר על חוט; מקטע זה פותח מופעי socket כדי לדבר על הרשת. הצורה זהה; השירות הבסיסי פשוט הרבה יותר מסוגל.
9.11.1. יצירת socket¶
שלושה ארגומנטים מתארים socket: באיזו משפחת כתובות הוא מדבר, איזה סוג socket הוא מציע, ובאיזה פרוטוקול הוא משתמש. ברירות המחדל מכסות את המקרים ששאר המקטע הזה משתמש בהם:
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # IPv4 TCP
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) # IPv4 UDP
שני הקבועים שהיישום בוחר ביניהם כמעט בכל מקרה:
AF_INET– כתובות IPv4 (IP מספרי בתוספת פורט). הבחירה הנפוצה ביותר.AF_INET6הוא המקביל ל-IPv6.SOCK_STREAM– חיבור TCP, זרם הבתים האמין.SOCK_DGRAMהוא המקביל ל-UDP.
הארגומנט השלישי (ה-פרוטוקול) נשאר על אפס, מה שבוחר את ברירת המחדל הנכונה בהתבסס על שני הראשונים. הבנאי המלא מתועד ב-socket — מודול socket.
9.11.2. כתובות על socket¶
כתובת socket היא tuple של (host, port)
("192.168.1.50", 80)
("0.0.0.0", 8000)
ה-host הוא כתובת ה-IP כמחרוזת. ה-port הוא המספר השלם בן 16 הביטים המכוסה ב-פורטים.
כמה מחרוזות host מיוחדות כדאי להכיר:
"0.0.0.0"משמעו ”כל ממשק IPv4 על ההתקן הזה“. שרת המאוגד לכתובת זו מקבל חיבורים על כל כתובת שהמצלמה מחזיקה."127.0.0.1"הוא localhost – תעבורה אליו לעולם אינה עוזבת את ההתקן. שימושי לבדיקות."255.255.255.255"היא כתובת השידור (broadcast) המקומית. datagram של UDP הנשלח אליה מגיע לכל התקן בסגמנט המקומי.
שמות מתחם כמו "example.com" אינם מחרוזות host תקפות בכתובת socket. יש לפתור אותם תחילה ל-IP; שמות ו-DNS מכסה את הקריאה getaddrinfo() שעושה זאת.
9.11.3. שני התפקידים¶
מחזור החיים של socket תלוי באיזה צד של השיחה הוא נמצא. socket של לקוח קורא ל-connect() (או, עבור UDP, פשוט ל-sendto()) כדי לדבר עם שרת ידוע. socket של שרת קורא ל-bind() כדי לתפוס פורט, ואז או ל-listen() ו-accept() (עבור TCP) או ל-recvfrom() (עבור UDP) כדי לקבל תעבורה נכנסת.
אותו בנאי socket משמש בשני המקרים; רק המתודות הנקראות לאחר מכן שונות. שלושת הדפים הבאים סוקרים את הדפוסים המעשיים:
שקעי UDP – שליחה וקבלה של datagrams.
שקעי TCP – לקוח ושרת TCP.
Sockets עם asyncio – כל האמור לעיל, אך בתוך לולאת אירועים של
asyncio.
9.11.4. סגירת socket¶
כל socket מחזיק חלק קטן ממצב מערכת ההפעלה (שריון פורט, חוצצים, מצב ה-TCP של החיבור). כאשר היישום סיים איתו, close() משחרר את אותו מצב. socket שנשכח הוא דליפה איטית שמצטברת; בלולאה שפותחת חיבורים, החמצת close תמצה בסופו של דבר את מאגר ה-sockets הזמינים של המצלמה.
הדפוס הנקי ביותר הוא הצהרת with
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.connect(addr)
s.send(b"GET / HTTP/1.0\r\n\r\n")
...
# socket is closed automatically here, even on error
Sockets מממשים את פרוטוקול מנהל ההקשר (context-manager) המכוסה בסקירת ה-Python, כך שבלוק ה-with מבטיח ש-close() ייקרא ללא קשר לשאלה אם הבלוק יצא באופן תקין או על ידי העלאת חריגה.
9.11.5. התיעוד של socket¶
דף זה והדפים הבאים סוקרים את ה-API בצורה תיאורית. עבור התיעוד המלא ברמת הארגומנט של כל מתודה, כל דגל וכל קבוע שהמודול חושף, ראה socket — מודול socket. התיעוד הוא גם המקום לחפש בו את הפעולות הפחות נפוצות (אפשרויות socket, חברות בקבוצת multicast, מזהי scope של IPv6) שמקטע זה אינו מכסה.