למה להשתמש בפרוטוקולים ברשת?

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

בנוסף, יכולת ה- C של פלטפורמות - משרתי לינוקס ועד microcontrollers - עושה את זה lingua פרנקה של תשתיות רשת.רוב מערכת ההפעלה kernels, מחסניות רשת, ופרוטוקולים הם עצמם כתובים ב- C, כך למידה לפתח פרוטוקולים ב- C נותן לך תובנה כיצד הרשת עובדת למעשה.עבור סיבות אלה, C אינה רק חפץ היסטורי; היא משמשת באופן פעיל בפרוטוקול מודרני, כגון פרוטוקולים מתקדמים, כגון פרוטוקולים של תקשורת או תכנות.

הגדרת הסביבה שלך

כדי לבנות ולבדוק קוד רשתות רשת ברמה נמוכה ב C, אתה צריך סביבת פיתוח הכוללת מדרדר אמין, פענוח כלים, ודרך לבחון התנהגות ברשת ללא הפרעה של מערכות ייצור.

  • (FLT:0)Compiler:FLT:1 GCC (גנו Compiler Collection) ו- Clang הם שתי האפשרויות הנפוצות ביותר. Both תומך בתקני C11 ו- C17, לספק אזהרות נרחבות, וכוללים אופטימיזציה שיכולים לשפר באופן משמעותי באמצעות מחשב.
  • (FLT:0Editor או IDE:FLT:1teau Studio Code with the C/C++ הרחבה, JetBrains CLion, או עורך טקסט פשוט כמו Vim או Emacs. for debugging, לשלב את GDB או LLDB.
  • (הופנה מהדף LT:0) ,(Testing Infrastructure: (FLT:1) ניתן לבדוק ממשקי רשת פיזיים, אך לעתים קרובות נוח יותר להשתמש בממשקים וירטואליים (למשל TUN/TAP על לינוקס) או ללאה (ראה:0) כלים כמו FLT:1, FLT:2, ו-FLT:3 לעזור לבדוק את התנועה או מכולות וירטואליות (Do) ללא מנגנונים לבודדים (Do) ללא מקיפים את הסביבה שלך).
  • (ב) ויקרא: ויקרא י"ד): "וַיְּהִיא אִתָּבְתָּבְתָּבְתָּבְתָּבְתָּבְתָּתוֹ" (בראשית כ"ד).

ברגע שהסביבה שלך מוכנה, אתה יכול להתחיל עם סלע של תכנות רשת: שקעים.

המונחים: Socket Programming

תכנות Socket הוא הפשטות הליבה של תקשורת ברשת C. A socket מייצג נקודת קצה של קישור תקשורת דו-כיווני. API שקעים מספק פונקציות ליצירת, לקשור, להקשיב, לקבל ולקבל נתונים.

יצירת שקע

מערכת ה-FLT:4 יוצרת שקע חדש וחוזרת על קובץ.

  • (ב) ויקרא י"ד: (ב) ,5 ,5 ,5 ,5 ,FLT:6 עבור IPv6,FLT 7 עבור חבילות גלם על לינוקס).
  • (ב) ויקרא י"ד: "ה' אלקים" (ב"א)
  • (ב) ,0)protocolveFLT:1 - בדרך כלל 0 כדי לאפשר למערכת לבחור את הפרוטוקול המתאים, או ערך IPPROTO ספציפי.
int sock = socket(AF_INET, SOCK_STREAM, 0); // TCP socket
if (sock < 0) {
 perror("socket");
 exit(1);
}

תמיד לבדוק את ערך ההחזר; פעולות רשת רבות נכשלות עקב מגבלות משאבים או הרשאות (השקעים של גילוח דורשים לעתים קרובות שורש).

הקשבה והקשבה

(ב) ל[[המאה ה-20]], יש ל[[1924]], [[1924]], [[1924]], [[1924]], [[1924]], [[1924]]]]]], [[1924]]]]]], [[1924]]]]]]]], [[1924]]]]]]]], [[1924]]]]]]]], [[1924]]]]]]]]]], [[1924]]]]]]]]]]]], [[1924]], [[1924]]]], [[1924]]]]]]]]]], [[1924]]]]]]]]]]]]]], [[1924]]]]

struct sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = INADDR_ANY; // listen on all interfaces
addr.sin_port = htons(8080);

if (bind(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
 perror("bind");
 close(sock);
 exit(1);
}

if (listen(sock, 5) < 0) {
 perror("listen");
 close(sock);
 exit(1);
}
printf("Listening on port 8080\n");

(הופנה מהדף [[1924]], [[1924]]]], [[1924]]]]]], [[1924]]]], [[1924]]]]]], [[1924]]]]]], [[1924]]]]]], [[1924]]]]]]]], [[1924]]]]]]

קבלת חיבורים ועברת נתונים

(ב) ל-TCP, השרת קורא ל-FLT:19 להוציא את החיבור הראשון מהתור המתנשא (FLT:20) מחזיר קובץ קידוד חדש עבור הלקוח המחובר.

int client_fd = accept(sock, NULL, NULL);
if (client_fd < 0) {
 perror("accept");
 continue;
}

char buffer[1024];
int n = recv(client_fd, buffer, sizeof(buffer), 0);
if (n > 0) {
 // process message
}
close(client_fd);

עבור UDP (נתונים של ⁇ ), אתה לא מקבל קשרים במקום, אתה משתמש ב-FLT:26 ו-FLT:27 כדי להחליף נתונים ישירות.

טעות ובלוק לעומת אי-בלוק

(ה) פעולות רשת יכולות להיכשל מסיבות רבות: רשת ללא יכולת, איפוס חיבור, זמן או תשישות משאבים (תמיד לבדוק את ערכי ההחזר והשימוש ב-FLT:28 או FLT:29 כדי ליצור שגיאות משמעותיות.על ידי ברירת מחדל, שקעים חוסמים - שיחות כמו זרמים זמניים:30, שימוש קבוע במנגנוני הפעלה (FLT:31), ו-FLT:32 יפתרו עד להשלמת פעולות עבור ביצועים גבוהים, לעתים קרובות, כגון מנגנונים קבועים (FLT) כדי שימוש ב-FLT:31-FLT) כדי שימוש ב-T) כדי שימוש ב-FLT:31, 000 פעמים רבות (מתקני שימוש במנגנונים קריטיים (מתקני שימוש ב-FLT) כדי שימוש ב-FLT:31 ו-FLT) כדי שימוש ב-T).

למדריך מעמיק, להתייעץ עם מדריך של FLT:0Beej לרשת תכנות תכנות תכנות 1FreaLT, אשר נשאר אחד המשאבים הטובים ביותר עבור תכנות C socket.

עבודה עם פרוטוקולים שונים

בחירת בין TCP ו UDP (או אחרים) תלויה בדרישות האמינות וההירות של הפרוטוקול שלך.הפרוטוקול המותאם אישית שלך עשוי להיבנות על גבי למעלה, או שאתה יכול להחליט להשתמש בשקעים גולמיים כדי לעקוף את שכבת ההובלה כולה.

TCP (Stream-Oriented, Reliable)

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

UDP (Datagram-Oriented, Unreliable)

UDP sends independent datagrams with no guarantee of delivery or ordering. It has lower overhead and minimal latency. Use UDP when your protocol can tolerate packet loss or when real-time performance is critical (e.g., VoIP, gaming, DNS). Because UDP preserves message boundaries, framing is simpler, but you may need to implement your own reliability and sequencing atop it (e.g., using sequence numbers and acknowledgments).

Raw Sockets

שקעים רול מאפשרים לך לשלוח ולקבל חבילות IP (או אפילו מסגרות Ethernet) ללא שכבת ההובלה של הקרנל.זה מאפשר לך לבנות TCP משלך, UDP, או ראשי תיבות מותאמים אישית. רול הם חזקים אבל דורשים זכויות גבוהות וטיפול זהיר.הם משמשים עבור כלים אבחון (ping, track), פרוטוקולים מותאמים אישית, ומחקר אבטחה.

עיצוב פרוטוקול מותאם אישית

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

הודעה מפורשת

פרמינג הוא איך אתה מוצא את הגבולות של הודעה בתוך זרם (TCP) או על פני נתונים (UDP).

  • (ב) ⁇ :0) , קדמה: ⁇ 1 , כל הודעה עם אינטגרטור בגודל קבוע המציין את אורך המטענים.
  • (ב) ,0) ,Delliters: 1FLT (הפסקה של הודעה עם רצף מיוחד של חתלתול (למשל, CRLF ב HTTP) ניתן להיות ערניים אם הנתונים מכילים את הדלמסטר אלא אם כן אתה בורח ממנו.
  • (ב) פשטות:0) הודעות בגודל של תהילים: FLT1 פשוט ביותר, אך רק עובד אם כל ההודעות הן בגודל זהה.

דוגמה למבנה ראש ארוך-עתידי:

#include <stdint.h>

#pragma pack(push, 1)
struct protocol_header {
 uint8_t version; // 1 byte
 uint8_t msg_type; // 1 byte
 uint16_t payload_len; // 2 bytes, network byte order
 // payload follows
};
#pragma pack(pop)

(ה) , (ה) , ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇

ידה של אינסוף

סדר רשתי הוא גדול endian.פרוטוקול שלך חייב לציין במפורש את ההזמנה לכל שדות רב-ביאטים. השתמש ב-FLT:38 (host to network short), FLT:39 (host to network long), FLT:40, , ⁇ :41 עבור המרה.

זיהוי שגיאות ובדיקה

כדי לזהות שחיתות, להוסיף בדיקת צ'ק או CRC (Cyclic Redundancy Check) ל-Finantexer פרוטוקול שלך. a פשוט תוסף (כמו Internet Checksum המשמש IP ו-TCP) קל לחשב, אבל CRC32 מספק זיהוי חזק יותר.You יכול לכלול גם מנהל אופציונלי עבור נתונים ברמת היישום.אם הפרוטוקול שלך פועל על פני UDP, שקול יישום aum כי בדיקות אופציונליות או אופציונליות לא מספיקות.

מכונות המדינה

פרוטוקול מגדיר רצף של מדינות (למשל, זהות, CONNECTED, WAIING ACK, CLOSING) ליישם את המכונה המדינה כהצהרת מתג או שולחן עבודה.כל הודעה נכנסת מעבר למדינה. שמור על מכונת המדינה לקבוען ולטפל הודעות בלתי צפויות (למשל, לשלוח טעות וסגורה לפרוטוקולים מורכבים, לשקול שימוש בכלי כמו Ragel או ליצור יישום של מכונות פשוטות, אך ורק עבור פרויקטים פשוטים.

רשת מתקדמת עם Raw Sockets

שקעים רול נותנים לך גישה ישירה לשכבה IP או אפילו שכבת הקישור (FLT:42 על לינוקס) זה חיוני כאשר אתה צריך ליישם פרוטוקול תחבורה מאפס, לתמרן כותרות IP (למשל, כתובת המקור spoofing לבדיקה), או לבנות כלי אבחון ברשת.

יצירת רול Socket

int rawsock = socket(AF_INET, SOCK_RAW, IPPROTO_TCP); // raw IP packets with TCP protocol
// or
int rawsock = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL)); // all Ethernet frames

בדרך כלל, הגרלות רול דורשות פריווילגיות שורש על לינוקס, אתה יכול גם להשתמש ב-:44 עם התפלגות FLT:45 לספר לגרעין שאתה תספק את מנהל ה- IP בעצמך.

בניית ראשים

כאשר משתמשים בשקעים גולמיים, אתה אחראי לבניית כותרות IP תקפים, ראשי תחבורה, ותשלום.לדוגמה, לשלוח קטע TCP מותאם אישית, עליך להגדיר באופן ידני את המקור ואת היעד IP, מקור TCP ונמלי היעד, מספר רצף, דגלים, גודל החלון, ולקבוע את ה- TCPum על פני פסאודו-ראש.

(הדברים של רול) משמשים גם עבור זריקת החבילה והרשת המנוכרת, הם נותנים לך שליטה מוחלטת, אך דורשים הבנה עמוקה של ערימה הפרוטוקול.פר ל- RFC הרלוונטיים - LIFLT:0RFC 793 (T)FLT:1 ו-FLT:2RFC 768 (UD)FLT 3 - עבור פורמטים ראשיים, ייעוץ 802.3.

בדיקות ווויכוח

פיתוח פרוטוקול רשת הוא קשה לשמצה להתבולג בגלל האינטראקציה בין מכונות מרובות לבין ערימה הקרנל. גישה שיטתית לבדיקת היא חיונית.

שימוש ב-Wishashark

(FLT:0) WiresharkofLT 1:1 לוכד חבילות ברמת הממשק וקודש אותם על פי פרוטוקולים ידועים רבים. עבור פרוטוקולים מותאמים אישית, אתה יכול לכתוב מפיץ Wireshark בלוה או C כדי ליישב את הפרוטוקול שלך באופן אוטומטי. לחלופין, השתמש בתכונה "עקב TCP" של Wireshark כדי להציג את הגלם החלקו.

דיון עם GDB

(ג'ון) יכול לצרף תהליך שרת פועל, להגדיר נקודות ב-FLT:47 או FLT:48 קורא, ולבדוק את buffers. השתמש ב- parpoints מותנים כדי לפרוץ רק כאשר מספר רצף מסוים או סוג הודעה נתקל.

בדיקה אחרונה ב-Mocking

עבור פרוטוקול לוגיקה (מכונות מדינה, הודעות מסכיינות, חישוב צ'ק), לכתוב בדיקות יחידה שאינן דורשות ממשקי רשת בפועל. השתמש שקע לולאה או להעביר נתונים באמצעות זוג של תיאורי קבצים (ראה FLT:52) כדי לדמות תקשורת בין שני נקודות קצה.לדוגמה, באפשרותך לבדוק כי שליחת הודעה תקפה גורמת לשינוי המדינה הנכון וכי גורם דחיית כלים כגון LT.

שיקולים

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

גודל Buffer

(ב) ניתן להתאים את ה-FLT:54 (FreaLT:55, ⁇ FLT:56), דחפורים גדולים יותר להפחית את מספר שיחות המערכת ויכולים לשפר את השימוש בזיכרון.

I/O ו- Multiplexing

עבור שרתים העוסקים אלפי קשרים, לעולם לא ליצור חוט לחיבור.במקום, להשתמש ב- I/O על לינוקס,FLT:58 הוא מנגנון ריבוי היעיל ביותר; ב- BSD/macOS, ב-FLT (הגישה היא לרשום את כל ה-Secet file descriptors עם לולאת האירוע ולעבד רק אלה מוכנים לקריאה או כתיבת המערכת של פרוטוקולים מותאם באופן טבעי למודל זה:

הימנעות מחשיפה וטעימה

אם יישום הפרוטוקול שלך חייב להתמודד עם מספר ליבות CPU, להיזהר עם מבני נתונים משותפים. השתמש ב-buffors כדי למנוע מנעולים גלובליים.עבור קבלה ומשלוח, לשקול באמצעות מברשות טבעת ( תורים ללא תשלום) כדי להעביר נתונים בין לולאה האירוע לבין חוטי עבודה.

שיקולים ביטחוניים

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

המונחים:

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

להימנע מ-Buff Overflows

שימוש בפונקציות הקשורות ל-FLT:62 ו-FLT:63 (או יותר טוב:64) עם בדיקות אורך מפורשות (עבור דמי תשלום באורך משתנה), להקצות זיכרון באופן דינמי, אך תמיד מכסה את הגודל המקסימלי כדי למנוע ממצה משאבים.

המונחים: ccitation

אם הפרוטוקול שלך חייב להתמודד עם נתונים רגישים, לשקול שילוב של TLS (באמצעות ספריות כמו OpenSSL או LibreSSL) ולא להמציא את ההצפנה שלך.אם אתה צריך ליישם הצפנה אישית או אימות, להסתמך על פרימיטיביים ידועים (AES-GCM, SHA-256) ולייעץ מומחה אבטחה.הימנע מ-Homebre XOR ciphers או תוכניות חלשות.

מסקנה

פיתוח פרוטוקולים ברשת נמוכה ברמת C נותן לך שליטה ללא תחרות על כל הילוך על חוט. על ידי מאסטרינג תכנות שקע, הבנה פרוטוקולי תחבורה, עיצוב פורמטים הודעה חזקים עם אנדואנטים נאותה ובדיקות, ושימוש sockets גלם מוכח כאשר יש צורך, אתה יכול לבנות פרוטוקולים יעילים ואמינה.