Skip to content

Latest commit

 

History

History
197 lines (150 loc) · 22.8 KB

File metadata and controls

197 lines (150 loc) · 22.8 KB

1. רשתות תקשורת

1.1. מבוא ופרוטוקולי תקשורת

1.1.1. מהו פרוטוקול תקשורת?

  • הגדרה: פרוטוקול תקשורת ברשת הוא סט של חוקים המגדירים את הפורמט, הסדר והפעולות שיש לבצע בעת שליחה וקבלה של הודעות. כל פעילות התקשורת ברשת נשלטת על ידי פרוטוקולים.

1.1.2. בניית השכבות (מודל TCP/IP)

  • מודל השכבות (TCP/IP): פרוטוקולי הרשת מאורגנים במחסנית המורכבת משכבות. לכל שכבה תפקיד מוגדר:
  1. השכבה הפיזית (L1): מטפלת בהעברת הביטים הפיזיים עצמם על גבי מדיה פיזית כמו כבלים או אותות אלחוטיים (חומרה).
  2. שכבת הקישור (L2): מנהלת את התקשורת הלוקאלית (LAN) בין רכיבים פיזיים סמוכים (לדוגמה: Ethernet).
  3. שכבת הרשת (L3): אחראית על זיהוי ומיפוי כתובות לוקאליות וגלובליות, ניתוב בין רשתות (IP).
  4. שכבת התעבורה (L4): אחראית על תקשורת קצה-לקצה בין תהליכים (לדוגמה: TCP, UDP).
  5. שכבת האפליקציה (L5): מוגדרת על ידי היישום עצמו (לדוגמה: HTTP ו-SMTP המשמשים לגלישה ודוא"ל).

1.1.3. חלוקת אחריות במימוש השכבות

  • שכבת האפליקציה ממומשת ברמת קוד המשתמש.
  • שכבות התעבורה (L4), הרשת (L3) והקישור (L2) ממומשות לרוב על ידי מערכת ההפעלה. עם זאת, קיימים מקרי קצה בתעשייה שבהם נעדיף להעביר את האחריות למקומות אחרים כדי לשפר ביצועים. למשל, סביבת DPDK מאפשרת לממש שירותי L4 ב-User-level, בעוד ש-RDMA מאפשר מימוש ישיר בחומרת כרטיס הרשת עצמו (NIC).
  • השכבה הפיזית (L1) ממומשת על ידי חומרת כרטיס הרשת.

1.1.4. אנקפסולציה

  • אנקפסולציה: תהליך בו כל שכבה (החל מהאפליקציה ומטה) מקבלת מידע (Payload) מהשכבה שמעליה, עוטפת אותו עם כותרת (Header) משלה, ומעבירה אותו לשכבה מתחת. כך, הודעת משתמש הופכת ל-Segment (ב-L4), אשר הופך ל-Packet (ב-L3), אשר הופך ל-Frame (ב-L2).
  • בצד המקבל מתבצע תהליך הפוך של "קילוף" הכותרות (De-encapsulation) והעברת המידע חזרה מעלה לשכבת האפליקציה.

1.2. שכבת התעבורה (L4) ואמינות הנתונים

1.2.1. אתגרים

  • אובדן וחוסר סדר ברשת: רשתות הן סביבות שבהן נתונים עשויים ללכת לאיבוד בשל בעיות חשמליות, כבלים שנחתכו, או לחלופין, היגמרות זמנית של מקום בחוצצים (Buffers) בהתקני הרשת - תופעה הידועה גם כבעיית ה-Incast. בנוסף, הרשת עלולה לבלבל את סדר הגעת ההודעות מכיוון שקיימים מסלולים שונים בין המקור ליעד.

1.2.2. השוואת פרוטוקולי תעבורה: TCP מול UDP

  • רוב תעבורת האינטרנט מסתמכת על שני פרוטוקולי תעבורה מרכזיים שממומשים על ידי מערכת ההפעלה, המספקים גישות שונות לטיפול באתגרי הרשת:
מאפיין TCP (Transmission Control Protocol) UDP (User Datagram Protocol)
רמת אמינות ה-"פרוטוקול שאכפת לו". מבטיח שכל הבתים יגיעו ליעד, ולפי הסדר הנדרש. ה-"פרוטוקול שלא אכפת לו". שירות Best Effort ללא הבטחת הגעה או סדר. אך מספק הגנה משגיאות (Checksum / CRC) על מנת לבדוק אם נתונים הושחתו בדרך.
צורת עבודה Connection-oriented - דורש משא ומתן להקמת Session מראש בטרם שליחת הנתונים. Connectionless - כל מנה נשלחת ומטופלת באופן עצמאי ללא משא ומתן מקדים.
אבסטרקציית נתונים מספק אבסטרקציה של זרם בתים רציף (Stream of bytes). מספק אבסטרקציה של מנות עצמאיות (Datagrams) בגודל מוגדר.
בקרות זרימה ועומסים Congestion Control: שינוי קצב השליחה בהתאם לזיהוי עומסים ברשת. בקרת עומסים ב-TCP מתאפיינת בהתנהגות של "שיני מסור" (Sawtooth), שנוצרת מכיוון שהפרוטוקול מזהה עומס על ידי אובדן של מנות בדרך (Drops) וחותך את קצב השליחה. קיימים אלגוריתמים שונים המנהלים את הקצב הזה, כגון Reno, Cubic, והאלגוריתם BBR שהוצע על ידי גוגל ב-2016.

Flow Control: המקבל מפרסם (Advertise) את גודל החוצץ שלו כדי שהשולח לא יציף אותו מהר מדי.
פשוט יותר, שיהוי (Latency) נמוך, נטול בקרת עומסים, ולכן יכול "להפגיז" נתונים. מתאים לשירותים כמו VoIP.

1.2.3. כיצד TCP מבטיח אמינות?

  • איך TCP מממש אמינות בפועל?
    • ACKs (Acknowledgements): הרעיון הבסיסי הוא שהצד המקבל שולח אישור לשולח על כל הודעה שהתקבלה. קבלת ה-ACK מבטיחה לשולח שההודעה הגיעה ליעדה.
    • Timeout: אם הודעה הולכת לאיבוד בדרך, השולח לא ימתין ל-ACK לנצח. השולח קובע פסק זמן, Timeout. אם לא התקבל אישור עד תום הזמן, הוא מניח שההודעה אבדה ושולח אותה שוב. לכן חובה על השולח לשמור עותק של ההודעה עד לקבלת האישור.
    • מספר סידורי (Sequence Number): מה קורה אם ההודעה הגיעה, אך ה-ACK הוא זה שאבד בדרך? השולח ישלח את ההודעה שוב, והמקבל יקבל הודעה כפולה. כדי למנוע ביצוע פעולות כפולות (כמו העברה בנקאית פעמיים), כל הודעה מקבלת מספר ייחודי עוקב, כך שהמקבל יודע לזהות ולזרוק הודעות כפולות.

1.2.4. התאמות TCP ברשתות שונות

  • התאמות של TCP לסביבות שונות: קיימות גרסאות של TCP שאינן הדיפולטיביות, אשר מותאמות במיוחד לחוות שרתים (LAN - Data Centers) שבהן ההשהיה (Latency) נמדדת במיקרו-שניות, לעומת רשתות רחבות (WAN) שבהן ההשהיה נמדדת במילי-שניות.

1.3. שכבת הרשת (L3) - פרוטוקול IP

1.3.1. שמות דומיין מול כתובות מחשב

  • שמות דומיין (Domain Names): שמות קריאים לבני אדם המיועדים לזהות שרתים (לדוגמה www.cs.technion.ac.il או www.google.com). שם דומיין אחד יכול להתמפות למספר רב של מכונות שונות, ובכיוון ההפוך (בעזרת שרת DNS המבצע Load Balancing), גם מכונה פיזית אחת (Host) יכולה להחזיק במספר כתובות IP שונות.

1.3.2. כתובות IP וגרסאות

  • כתובות IP: מחשבים אינם מעבירים מידע באמצעות שמות דומיין, אלא בעזרת כתובת IP.
    • IPv4 הוא בגודל 32 ביט. הכתובת מיוצגת לרוב כ-4 אוקטטות (בתים) דצימליות המופרדות בנקודות (Dot-decimal, למשל 132.68.32.1).
    • IPv6 הוא ההרחבה שנוצרה ל-128 ביט.
    • לרוב, כדי שמתכנתים לא יצטרכו לדאוג באיזו גרסת IP המכונה משתמשת (או להקצות זיכרון בגדלים שונים למבנה הנתונים), הם משתמשים בפונקציה getaddrinfo עם הדגל AF_UNSPEC.

1.3.3. סיכום תפקידים בסיסי IP מול תעבורה

  • סיכום אבסטרקציות: פרוטוקול IP (L3) נועד לזהות את ה-Hosts ברשת העולמית, בעוד שפרוטוקולי TCP/UDP (L4) משמשים כדי לזהות ערוצי תקשורת בודדים של התהליכים (Processes) בתוך אותה מכונה.

1.4. Sockets, Ports ומודל שרת-לקוח

1.4.1. שקעים (Sockets) ופורטים (Ports)

  • Sockets: יישומים (תהליכים) מדברים ביניהם על פני הרשת באמצעות Sockets, המהווים נקודות קצה לתקשורת. קריאה וכתיבה ל-File Descriptor של שקע מיתרגמים בפועל לקבלה ושליחה של נתונים.
  • Ports (פורטים): מכיוון שכתובת ה-IP מזהה רק את המכונה ויכולים לרוץ בה מספר תהליכים, נוסף מזהה בשם Port (מספר שלם בגודל 16 ביט). הפורט מאפשר לייחד כל שקע תקשורת.
  • סוגי פורטים:
    • Well-known (מוכרים): ערכים סטנדרטיים מוגדרים מראש (למשל, תקשורת HTTP מנותבת באופן דיפולטי לפורט 80). פורטים קטנים מ-1024 שמורים לתהליכים פריבילגיים.
    • Ephemeral (ארעיים): מוקצים דינמית על ידי מערכת ההפעלה, בדרך כלל עבור צד הלקוח.
  • זיהוי חד-ערכי (5-Tuple): Session תקשורתי מזוהה בצורה מוחלטת באמצעות 5 משתנים: IP מקור, Port מקור, IP יעד, Port יעד, וסוג פרוטוקול תעבורה (UDP/TCP).

1.4.2. תקשורת שרת-לקוח ב-TCP

  • מודל שרת-לקוח ב-TCP ומעגל חיי ה-Socket:
    • שרת: תהליך פסיבי הפועל ברקע, ממתין לבקשות, ומאזין בכתובת IP ופורט ידועים מראש.
      • רצף קריאות השרת: socket $\leftarrow$ שיוך הפורט ב-bind $\leftarrow$ האזנה ב-listen $\leftarrow$ לולאה עם קבלת חיבור ב-accept (המייצרת socket ייעודי, clifd) $\leftarrow$ ביצוע read/write מול הלקוח.
    • לקוח: תהליך אקטיבי המתחבר לשרת באופן יזום.
      • רצף קריאות הלקוח: socket $\leftarrow$ התחברות ליעד ב-connect $\leftarrow$ ביצוע write/read מול השרת.
    • ייסוד חיבור: תהליך ה-connect אל ה-accept כולל לחיצת יד משולשת (3-Way Handshake) כדי להבטיח הקמת חיבור (וגם סגירת חיבור) בצורה מסונכרנת.

1.4.3. ארכיטקטורת שרתים מקביליים

  • פתרון לבעיית ה-Convoy Effect והתמודדות עם ריבוי לקוחות (שרת מקבילי): כאשר שרת קורא וכותב באופן סדרתי, לקוח איטי עלול לעכב את שאר הלקוחות. קיימות שתי גישות מרכזיות לבניית שרתים המטפלים באלפי לקוחות:
    • גישה 1 - חוט (Thread) לכל לקוח:
      • יתרונות: תכנות פשוט, וניצול יעיל של מעבדים מרובי ליבות.
      • חסרונות: צריכת זיכרון רבה (כמה MB לכל חוט), ותקורה כבדה של החלפות הקשר (Context Switches) בין אלפי חוטים.
    • גישה 2 - תכנות מונחה אירועים (Event-Driven) באמצעות select: שרת המבוסס על לולאת אירועים הממתינה ללקוחות ומטפלת בהם באופן רציף.

1.4.4. קריאת המערכת select

פעולה: המתנה עד שאחד ה-FDs באחת הקבוצות readfds או writefds מוכן לקריאה או לכתיבה (בהתאמה), או עד אשר חלף פרק הזמן המצוין ב-timeout.

  • אם קיים FD מוכן לקריאה, אז פעולת read עליו תחזור מיד ולא תחסום את התהליך.
  • אם קיים FD מוכן לכתיבה, אז פעולת write עליו תחזור מיד ולא תחסום את התהליך.

ערך חזרה: מספר ה-FDs המוכנים בכל הקבוצות. בנוסף, הקבוצות שהועברו כארגומנטים יעודכנו כך שיצביעו על ה-FDs המוכנים.

ניהול fd_set: כדי לתפעל את סט ה-FDs, משתמשים במאקרוס כפי שמוצג בקוד:

  • FD_ZERO(&readFDs): לאיפוס ואתחול.
  • FD_SET(fd, &readFDs): להוספת FD ספציפי לסט.
  • FD_ISSET(fd, &readFDs): לבדיקה איזה מה-FDs עורר את הפונקציה לאחר חזרתה.

דוגמת קוד:

int main(void) {
  // the server listens to a port
  // and then accepts a bunch of sockets (not shown)
  
  while (1) {
    // initialize the fd_set to all zero
    fd_set readFDs;
    FD_ZERO(&readFDs);

    // set the bits for the descriptors this server
    // is interested in (all from min to max)
    for (int fd = minFD; fd < maxFD; fd++)
      FD_SET(fd, &readFDs);

    // do the select
    int rc = select(maxFD, &readFDs, NULL, NULL, NULL);

    // check which have data using FD_ISSET
    for (int fd = minFD; fd < maxFD; fd++)
      if (FD_ISSET(fd, &readFDs))
        handle_request(fd); // פונקצית הטיפול בלקוח, נניח כי היא ממומשת בקובץ אחר
  }
}

חסרונות השימוש ב-select:

  • דוגמת הקוד משתמשת בחוט אחד ולכן לא יכולה לנצל מעבדים מרובי ליבות. מימושים חכמים יותר יפזרו את הבקשות בין חוטים שונים של אותו מאגר (thread pool).
  • אם הטיפול בבקשה – הווה אומר הפונקציה handle_request – קורא לפעולה חוסמת (לדוגמה פתיחת קובץ מהדיסק) אז השרת כולו עלול להיחסם.
  • המימוש של fd_set מוגבל לקבוצות בגודל מקסימלי של 1024 File Descriptors.

1.4.5. פונקציות API ברשת ודקויות מימוש

  • דקויות בקוד ופונקציות API ברשת:
    • הבדלי פונקציות שליחה וקבלה: מעבר ל-read ו-write הבסיסיות, ב-TCP עובדים לרוב עם send ו-recv המאפשרות להעביר דגלים מיוחדים. בנוסף, קיימות גרסאות Scatter-Gather הנקראות sendmsg ו-recvmsg. מכיוון ש-UDP הוא Connectionless, חובה לציין בכל פעולה מחדש את היעד, ולכן משתמשים ב-sendto ו-recvfrom. בהגדרת השרת מציינים את כתובת ה-IP כ-INADDR_ANY כדי להאזין בכל ממשקי הרשת של המכונה.
    • מידע על נקודות הקצה: כדי לדעת מהי זהות הלקוח או השרת המחובר ל-Socket מסוים (ה-IP והפורט), נשתמש בפונקציות getpeername ו-getnameinfo (מומלץ במקום gethostbyname המיושנת).
    • דקויות getaddrinfo: כדי לתרגם שמות מחשב לכתובות IP בצורת פולימורפית התומכת ב-IPv4 ו-IPv6 ומתמודדת עם Endianness "מאחורי הקלעים". שימו לב להבדל באתחול מבנה ה-hints:
      • בצד השרת: מעבירים לפרמטר node את הערך NULL, וב-hints.ai_flags מעבירים את הערך AI_PASSIVE.
      • בצד הלקוח: בפרמטר ה-node רושמים את שם השרת, ה-flags מאותחל ל-0.
    • Endianness ותרגום כתובות: מכונות שונות שומרות נתונים בסדרי בתים שונים (Big Endian מול Little Endian). כדי ליישר קו לרשת משתמשים בפונקציות המרה כגון htons.

1.5. שכבת הקישור (L2) ורשתות מקומיות (LAN)

1.5.1. מבנה ה-LAN ותקן ה-Ethernet

  • LAN (Local Area Network): רשת המחברת מחשבים בטווח קרוב (בית, חדר שרתים, משרד) באמצעות חוטים או אלחוטית, בעזרת ציוד מיתוג (Switches), כרטיסי רשת (NICs) ונקודות גישה (APs).
  • Ethernet (תקן IEEE 802.3): פרוטוקול התקשורת הדומיננטי ל-LAN, המשלב רכיבי L1 (הגדרת ביטים פיזיים ומדיה כגון סיבים) ו-L2.
  • מאפייני תקשורת: העברת המידע נעשית בעזרת יחידות הנקראות מנות (Frames) בשיטה Connectionless ולא אמינה (Lossy).

1.5.2. כתובות MAC ומבנה המסגרת (Frame)

  • מבנה ה-Ethernet Frame: המנה מורכבת מכותרת (Header) הכוללת את כתובת יעד ומקור ה-MAC, ממידע (Payload), ומ"סוגר" (Trailer) המכיל בדיקת יתירות מחזורית (CRC) שנועדה לוודא את אמינות התוכן. אם מנת ה-Ethernet מגיעה ליעד ונכשלת בבדיקת ה-CRC, היא נזרקת (Dropped) באופן מיידי וללא התראה למקור.
  • כתובת MAC (Media Access Control): כל רכיב חומרה של Ethernet מזוהה באמצעות כתובת ייחודית בת 48 ביט (6 בתים) הצרובה בו (ROM). כתובת זו משמשת את מתגי ה-LAN כדי לדעת לאן לנתב את המנות בתוך הרשת המקומית.

1.6. ראוטרים ומבנה האינטרנט

1.6.1. הצורך בראוטרים

  • האתגר בחיבור רשתות: מתגים ב-LAN "מדברים" רק בשפת ה-L1/L2 (לרוב Ethernet). אך כדי לחבר בין מחשב ברשת אחת למחשב ברשת אחרת (היכולה להיות ביבשת אחרת או מבוססת פרוטוקול L2 שונה לחלוטין), צריך גורם מגשר.
  • הראוטר (נתב): רכיב חומרה הנמצא בגבול בין שתי רשתות או יותר, ומסוגל לקרוא ולדבר בשפות ה-L1/L2 של כל אחת מהן. הנתב "מקלף" את כותרות ה-L2 המקוריות של המנה (Packet), מחלץ את מנת ה-IP, ואורז אותה מחדש (Re-encapsulate) לתוך מעטפת L2 המותאמת לרשת הבאה בתור.

1.6.2. מבנה האינטרנט

  • מקור המונח Internet: האינטרנט איננו רשת אחת, אלא "Inter-network" - רשת עולמית המורכבת מהרבה תת-רשתות נפרדות. תת-הרשתות מיוצגות כצמתים (Vertices) בגרף עצום, בעוד שהראוטרים משמשים כקשתות (Edges) המחברות ביניהן באמצעות שכבת ה-IP האוניברסלית.

  • ארכיטקטורת שעון חול (Hourglass): פרוטוקול ה-IP פועל כ"מותניים צרות" - שכבה יחידה שמרכזת הכל. מעליו רצים מגוון פרוטוקולי L4/L5, ומתחתיו קיימות מגוון טכנולוגיות רשת שונות. הודות לכך שכל רשת תומכת IP, האפליקציות חסינות לסוג הרשת שמתחתן.

1.6.3. מגבלות אורך ופיצול (Fragmentation)

  • פרגמנטציה ופיצול (Fragmentation): פרוטוקול L2 מגדיר גודל מקסימלי לנתונים בודדים הנקרא MTU (ב-Ethernet עד 1500 בתים). מכיוון שמנת IP יכולה לשקול עד 64KB, היא עלולה להיות גדולה מדי לרשת הפיזית. לכן מנות גדולות עוברות פרגמנטציה (פיצול למנות קטנות שיכילו את ה-Headers הנדרשים) במקור, ומורכבות מחדש בנקודת היעד הסופית. כיום, כרטיסי רשת (NICs) יודעים לבצע את הפיצול וההרכבה מחדש בעצמם כדי להוריד עומס מהמעבד באמצעות יכולות הנקראות TSO (TCP Segmentation Offload) בצד השולח, ו-LRO (Large Receive Offload) בצד המקבל.

1.7. IP ל-LAN ושירותים תומכים נפוצים

1.7.1. חלוקת תת-רשתות (Subnets)

  • כתובת הרשת ו-Subnets: כתובת IP (לדוגמה 132.68.32.1) מתחלקת תמיד לשני תפקידים: הביטים הגבוהים מציינים את הרשת (Subnet part), והביטים הנמוכים מזהים את המחשב הבודד (Host part). חלוקה זו נקבעת על פי ה-Subnet Mask.
    • לרוב הייצוג נעשה בפורמט CIDR (כמו ב-/24), המסמן כמה ביטים הוקצו לזהות הרשת מתוך הכתובת.
    • כל הצמתים בתוך אותו Subnet יכולים להגיע אחד לשני ישירות דרך מתגים ללא התערבות ראוטר.

1.7.2. פרוטוקולי תרגום, ניהול והקצאה

  • ARP (Address Resolution Protocol - IP ל-MAC): כאשר מחשב רוצה לתקשר עם IP אחר בתוך ה-LAN שלו, הוא חייב לדעת את כתובת ה-MAC הפיזית של היעד. לשם כך, הוא שולח מנת שאילתה ב-Broadcast לכתובת ההפצה FF:FF:FF:FF:FF:FF שתגיע לכלל המכשירים ברשת. המכשיר לו שייכת ה-IP יזהה אותה ויחזיר את ה-MAC שלו.
  • NAT (Network Address Translation): ראוטרים ביתיים מספקים חיבור למספר רב של מכשירים בבית למרות שספק האינטרנט (ISP) מקצה להם כתובת IP חוקית פומבית אחת בלבד. תקן ה-IP מקצה טווחי "כתובות פרטיות" (כגון 192.168.0.0 או 10.0.0.0) שהראוטר מחלק פנימית. הראוטר ממיר ומשחק (Jiggles) עם כתובות ה-IP והפורטים של התקשורת היוצאת והנכנסת כדי לתאם בין העולם החיצוני לכתובת הפנימית האמיתית.
  • DHCP (Dynamic Host Configuration Protocol): כאשר מכשיר חדש מצטרף לרשת, פרוטוקול אפליקציה זה מחלק לו אוטומטית כתובת IP לשימוש. השרת (לרוב בתוך הראוטר) משיב ומספק בנוסף ל-IP גם את ה-Subnet Mask, ה-Gateway (הראוטר הראשון ליציאה החוצה), ואת שם וכתובת שרת ה-DNS.
    • האנקפסולציה ב-DHCP: התקשורת מתבצעת כבקשת Broadcast. הבקשה המקורית של האפליקציה (L5) עטופה ב-UDP (לכדי L4 Segment), שעטופה ב-IP (לכדי L3 Packet), שעטופה ב-Ethernet Frame (רמת L2) עם כתובת יעד Broadcast של ה-MAC (כלומר FF:FF:FF:FF:FF:FF) כדי שתגיע לכל הציוד ב-LAN המקומי.