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 משמש בשני המקרים; רק המתודות הנקראות לאחר מכן שונות. שלושת הדפים הבאים סוקרים את הדפוסים המעשיים:

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) שמקטע זה אינו מכסה.