תכנות Socket ב-C++

Tknwt Socket B C



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

הקמת מודל שרת-לקוח

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

1. צד שרת







הקוד של צד השרת של המודל ניתן להלן. בוא נראה מה קורה בקוד:



#include
#include
#include
#include

באמצעות מרחב שמות סטד ;

#define PORT 8080
#define MAX_BUF_SIZE 1024

int רָאשִׁי ( ) {
int ser_socket, cli_socket ;
struct sockaddr_in ser_address, cli_address ;
לְהַשְׁחִיר buf [ MAX_BUF_SIZE ] = { 0 } ;

אם ( ( ser_socket = שֶׁקַע ( AF_INET, SOCK_STREAM, 0 ) ) == - 1 ) {
טעות ( 'שגיאה ביצירת Socket' ) ;
יְצִיאָה ( EXIT_FAILURE ) ;
}

ser_address. חטא_משפחה = OF_INET ;
ser_address. sin_addr . s_addr = INADDR_ANY ;
ser_address. sin_port = htons ( נמל ) ;

אם ( לִקְשׁוֹר ( be_socket, ( struct sockaddr * ) & ser_address, מידה של ( ser_address ) ) == - 1 ) {
טעות ( 'כשל בכריכה' ) ;
יְצִיאָה ( EXIT_FAILURE ) ;
}

אם ( להקשיב ( be_socket, 3 ) == - 1 ) {
טעות ( 'לא הצליח להקשיב' ) ;
יְצִיאָה ( EXIT_FAILURE ) ;
}

cout << 'שרת מאזין ביציאה' << נמל << '... \n ' ;

socklen_t cli_address_len = מידה של ( cli_address ) ;
אם ( ( cli_socket = לְקַבֵּל ( be_socket, ( struct sockaddr * ) & cli_address, & cli_address_len ) ) == - 1 ) {
טעות ( 'נכשל לקבל' ) ;
יְצִיאָה ( EXIT_FAILURE ) ;
}

לקרוא ( cli_socket, buf, MAX_BUF_SIZE ) ;
cout << 'ההודעה של הלקוח היא:' << buf << endl ;

לִשְׁלוֹחַ ( cli_socket, 'הודעת השרת' , סטרלן ( 'הודעת השרת' ) , 0 ) ;

סגור ( cli_socket ) ;
סגור ( ser_socket ) ;

לַחֲזוֹר 0 ;
}

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



התוכנית מתחילה עם הכללת הספריות: 'iostream' להגדרות קלט/פלט סטנדרטיות, 'cstring' לפונקציות טיפול במחרוזות, 'unistd.h' כדי לספק גישה ל-API של מערכת ההפעלה POSIX, ו-'arpa/inet.h' ל לבצע את פעולות האינטרנט. ההצהרה '#define PORT 8080' פירושה שהיא מגדירה את מספר היציאה 8080 שבה השרת יקשיב. ה-'#define MAX_BUF_SIZE 1024' פירושו גודל המאגר המקסימלי עבור הנתונים הנכנסים שהוא 1024.





בפונקציה הראשית, שני משתנים מאותחלים, 'ser_socket' ו-'cli_socket', כדי לייצג גם את השרת וגם את הלקוח, בהתאמה. שלושת המשתנים האחרים שהם 'sockaddr_in', 'ser_address' ו-'cli_address' מסוג 'struct' מאותחלים כמבני כתובות עבור השרת והלקוח. לאחר מכן, מאתחל מאגר בשם 'buf' המאחסן את הנתונים המגיעים מהלקוח.

הפונקציה socket() במצב 'if' יוצרת שקע TCP חדש. AF_INET מציין IPv4, SOCK_STREAM מייצג את שקע TCP מכוון חיבור ואמין, הארגומנט האחרון שהוא 0 ניתן לבחירת פרוטוקול TCP המוגדר כברירת מחדל, INADDR_ANY מקבל את החיבורים בכל כתובת IP, וה-htons (PORT) ממיר את מספר היציאה מה- סדר בתים מארח לסדר בתים ברשת.



מכיוון שהכל מוגדר כהלכה, השלב הבא הוא להגדיר את השרת כ-lister בפורט הנתון ולקבל את החיבורים בכל ממשק רשת. השקע ניתן עם המידע ב- 'ser_address' בשיטת bind() . אנו מדפיסים שגיאה ומסיימים את התהליך אם הכריכה נכשלת. הפונקציה accept() פותחת שקע חדש לחיבור עם הלקוח, בעוד שהפונקציה listen() מורה לשרת לחכות לחיבורים נכנסים. אם הפונקציה accept() נכשלת, הודעת השגיאה מודפסת והפונקציה תצא.

לאחר מכן, השרת קורא את הודעת הלקוח עם הפונקציה read() לתוך המאגר 'buf' ואז מדפיס אותה למסוף. הפונקציה send() משמשת את השרת לשליחת הודעה בתגובה ללקוח. לבסוף, באמצעות close(), השרת סוגר את השקע של הלקוח, ומסיים את התוכנית כך שכל החיבורים ייסגרו כהלכה ואין סבירות לפריצת נתונים.

2. צד לקוח

כעת, בואו נראה מה קורה במודל הלקוח:

#include
#include
#include
#include

#define PORT 8080
#define SERVER_IP '127.0.0.1'

int רָאשִׁי ( ) {
int cli_socket ;
struct sockaddr_in ser_address ;
const לְהַשְׁחִיר * הוֹדָעָה = 'הלקוח שולח ברכות!' ;

אם ( ( cli_socket = שֶׁקַע ( AF_INET, SOCK_STREAM, 0 ) ) == - 1 ) {
טעות ( 'שגיאה ביצירת שקע' ) ;
יְצִיאָה ( EXIT_FAILURE ) ;
}

ser_address. חטא_משפחה = OF_INET ;
ser_address. sin_port = htons ( נמל ) ;

אם ( inet_pton ( AF_INET, SERVER_IP, & ser_address. sin_addr ) <= 0 ) {
טעות ( 'כתובת שגויה' ) ;
יְצִיאָה ( EXIT_FAILURE ) ;
}

אם ( לְחַבֵּר ( cli_socket, ( struct sockaddr * ) & ser_address, מידה של ( ser_address ) ) == - 1 ) {
טעות ( 'כשל בחיבור' ) ;
יְצִיאָה ( EXIT_FAILURE ) ;
}
לִשְׁלוֹחַ ( cli_socket, mesg, סטרלן ( הוֹדָעָה ) , 0 ) ;

לְהַשְׁחִיר buf [ 1024 ] = { 0 } ;
לקרוא ( cli_socket, buf, מידה של ( buf ) ) ;
סטד :: cout << 'תגובת השרת:' << buf << סטד :: endl ;

סגור ( cli_socket ) ;
לַחֲזוֹר 0 ;
}

תן לנו לראות כל שורת קוד כדי להבין איך התוכנית פועלת.

אותן ארבע ספריות - iostream, cstring, unistd.h ו-arpa/inet.h - כלולות גם בצד הלקוח. מספר יציאה מוגדר גם יחד עם כתובת ה-IP של המארח המקומי 127.0.0.1. ההודעה שיש להעביר לשרת ניתנת. הלקוח והשרת צריכים ליצור חיבור כשלב הבא:

ה-'if ((client_socket = socket(AF_INET, SOCK_STREAM, 0)) == -1);' יוצר שקע עבור IPv4 עם סוג זרם ופרוטוקול ברירת המחדל TCP. ה-perror() מדפיס את פרטי השגיאה אם ​​הפונקציה socket() לא מצליחה ליצור חיבור ויוצאת מהתוכנית.

ה-'server_address.sin_port = htons(PORT);' מגדיר את מספר היציאה לאחר המרה לסדר בתים ברשת. לאחר מכן, ניתנת כאן הודעת כשל נוספת שהיא 'כתובת שגויה' אשר מודפסת אם יש משהו לא בסדר בכתובת. על ידי איתור הכתובת ב-'ser_address', הלקוח יתחבר לשרת. אם החיבור נכשל, פרטי השגיאה מודפסים. הפונקציה send() תעביר את ההודעה לשרת, ותוודא שהיא לא מכילה שום דגל.

כדי לקבל ולאחסן תגובה מהשרת, מאתחל מאגר בשם 'buf' מסוג 'char'. הפונקציה read() קוראת את תגובת השרת לתוך המאגר. לבסוף, תגובת השרת מודפסת לקונסולה. לבסוף, החיבור נסגר באמצעות המשפט close() כדי לסיים את השקע. להלן הפלט של התוכנית:

סיכום

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