Presentation is loading. Please wait.

Presentation is loading. Please wait.

תקשורת ומחשוב תרגול 3-5 סוקטים ב-C.

Similar presentations


Presentation on theme: "תקשורת ומחשוב תרגול 3-5 סוקטים ב-C."— Presentation transcript:

1 תקשורת ומחשוב תרגול 3-5 סוקטים ב-C

2 מודל Client-Server במודל זה השרת תמיד מחובר וממתין לבקשות של לקוחות
שרת: תמיד מחובר, בעל כתובת IP ידועה, לעתים יש צורך במספר שרתים לתמיכה בכמות בקשות גדולה. השרת ממתין לבקשה מהלקוח ולרוב אינו יכול ליזום תקשורת באופן עצמאי. לקוח: מתקשר עם שרת, יכול להיות מחובר פרקי זמן, יכול להיות עם כתובת IP משתנה, במודל זה הלקוחות אינם מתקשרים ישירות זה עם זה. תהליך (Process) –מופע של תוכנית שמנוהל על ידי מערכת הפעלה (עצמאות מלאה בין תהליכים). שני תהליכים באותו מחשב מתקשרים דרך מערכת ההפעלה. בין מחשבים שונים, תהליכים מתקשרים דרך הרשת.

3 Ports ,IP בד"כ במחשב פועלים מספר סוגי יישומים בו-זמנית (בעזרת מערכת הפעלה). כיצד מחשב יודע לסווג את הנתונים המתקבלים, ליישומים השונים הפועלים בו-זמנית? הפתרון הינו Logical Port (יקרא port) באורך 16 סיביות 16 סיביות יש אפשרות למקסימום 2^16=65536 תהליכים במחשב מסוים). מספרי port בתחום שמורים עבור שירותים מוסמכים ונקראים . well-know ports IP Address – כתובת של 32 ביט המאפשרת לזהות מחשב ברשת.

4 Socket כדי שתהליך יוכל לקבל/לשולח מידע לרשת/מהרשת חייבים לה "צינור" הנקרא Socket שילוב של כתובת IP עם מספר Port מגדיר כתובת שקע (Socket Address) זוג כתובות השקע מגדיר קשר בין שני קצות הקשר (בין מחשבים, בין יישומים וכו'). במילים אחרות, בתוך host מסוים, ה-Socket הוא ממשק המתווך בין רמת ה- Applicationורמת ה-Transport. דוגמא לכך שלשכבת ה-Application קיימת השפעה על שכבת ה- Transport בחירת הפרוטוקול בשכבת התעבורה

5 רמת Transport כל אפליקציה דורשת שירות שונה מרמת ה-Transport :
Connection less – שירות שמתאים לאפליקציות שמאפשרות איבוד מידע מועט (אפליקציות של אודיו) וצריכות מהירות - Connection orientedשירות שמתאים לאפליקציות שאינן יכולות להתמודד עם איבוד מידע (למשל, העברת קבצים).

6 TCP vs UDP אפליקציות שונות מבקשות שירות שונה מרמת ה- Transport:
יתרונות – הפרוטוקול מספק תעבורה אמינה: החבילות מגיעות שלמות, מסודרות לשכבת האפליקציה הפרוטוקול דורש הקמת קשר מסודר בין מחשבים, משתמש במנגנוני בקרת זרימה ובקרת גודש (עומס) חסרונות – נשלח הרבה DATA נוסף, איטי יחסית דוגמא - שימוש ביישומי HTTP, FTP, Telnet תקשורת UDP יתרונות – החבילות מגיעות מהר, תקורה נמוכה (overhead) חסרונות – העברת מידע לא אמינה, חבילות יכולות להגיע פגומות או אפילו לא להגיע ,אין סדר ברמת האפליקציה דוגמא - DNS

7 Platform and Compiler Linux PC using Gnu's gcc compiler:
Linux Ubuntu – עבודה בענן - Winsock Programmer's FAQ - עבודה עם ספריה Winsock 2.х erop

8 יצירת Socket בשפת - C שלבים ליצירת Socket בשפת C:
ספריות נדרשות: בכל המשך התהליך יצירת socket descriptor ע"י הפונקציה : הסבר: af – פרוטורול (עבור IPv4 הערך הוא: AF_INET), type- סוג ה-socket (עבור TCP: SOCK_STREAM, עבור UDP: SOCK_DGRAM) protocol– פרוטוקול שכבת תעבורה: עבור TCP: SOCK_STREAM, עבור UDP: SOCK_DGRAM. ערך 0- יתן את ברירת המחדל: בהתאם לסוג ה socket. במידה ולא הוקם socket הפונקציה תחזיר את הערך -1 (INVALID_SOCKET). #include <sys/types.h> #include <sys/socket.h> #include <string.h> #include <arpa/inet.h> int socket(int af, int type, int protocol);

9 יצירת Socket בשפת - C דוגמה:
בדוגמה יצרנו socket בפרוטוקול IPv4 עם SOCK_STREAM המאפשר לנו לקיים תקשורת אמינה ועם ערך 0, ברירת המחדל. int sock = socket(AF_INET, SOCK_STREAM, 0);

10 בשאר השלבים קיים הבדל בין השרת ללקוח
יצירת Socket בשפת - C בשאר השלבים קיים הבדל בין השרת ללקוח

11 יצירת Socket בשפת - C לקוח

12 יצירת Socket בשפת - C הקמת חיבור עם שרת (במקרה של פרוטוקול TCP, פרוטוקול UDP עובד ללא הקמת חיבור) ע"י קריאת פונקציה: הסבר: sockfd – socket descriptor אשר מוחזר על ידי הפונקציה ()socket (שלב קודם) serv_addr - מצביע למבנה sockaddr (הסבר בשקף הבא) המכיל כתובת ופורט של שרת אליו מתחברים addrlen – גודל מבנה sockaddr בביתים. גם כאן, אם החיבור לא הוקם, הפונקציה מחזירה ערך -1. int connect(int sockfd, struct sockaddr *serv_addr, int addrlen);

13 יצירת Socket בשפת - C מבנה sockaddr מכיל מידע על ה- IP של ה- socket עבור סוגים שונים של סוקטים sa_family יכול להיות AF_INET (IPv4) or AF_INET6 (IPv6) sa_data מכיל כתובת ופורט של יעד struct sockaddr { unsigned short sa_family; // address family, AF_xxx char sa_data[14]; // 14 bytes of protocol address };

14 יצירת Socket בשפת - C מבנה ("in" for "Internet") sockaddr_in – עבור IPv4. sin_zero צריך לאפס לפני כל שימוש ע"י פונקציה memset(). (שקף הבא) sin_family (ערכו AF_INET) תואם ל-sa_family של מבנה sockaddr. sin_port צריך להמיר לייצוגNetwork Byte Order באמצעות פונקציה htons(). sin_addr – צריך להמיר IP כתובת בייצוג בינארי (IPv4) או דצימאלי (IPv6) לייצוג רשת ע" פונקציה inet_pton(). ניתן להמיר את המצביע למבנה sockaddr_in למצביע למבנה sockaddr. // (IPv4 only! for IPv6- please see struct sockaddr_in6 ) struct sockaddr_in { short int sin_family; // Address family, AF_INET unsigned short int sin_port; // Port number struct in_addr sin_addr; // Internet address unsigned char sin_zero[8]; // Same size as struct sockaddr };

15 יצירת Socket בשפת - C הפונקציה memset :
מוחקת n תווים ראשונים של מחרוזת str אשר המצביע אליה מתקבל כפרמטר, ובמקומם רושמת c. לדוגמה: בדוגמה יצרנו sockaddr_in בשם serverAddress מחקנו את n התווים הראשונים ב- serverAddress void memset(void *str,int c, size_t n) struct sockaddr_in serverAddress; memset(&serverAddress,0, sizeof(serverAddress));

16 יצירת Socket בשפת - C Byte Order - היות ואין אחידות אצל מייצרי מעבדים בסדר הופעה ביתים הכי משמעותים ופחות משמעותים, אז נקבע שברשת סדר הופעה ביתים יהיה כך שבית הכי משפעותי מועבר ראשון (Network Byte Order או Big- Endian). במחשבים ביתים נשמרים ב-Host Byte Order. להלן פונקציות להמרה: לדוגמה: htons() // host to network short htonl() // host to network long ntohs() // network to host short ntohl() // network to host long serverAddress.sin_port = htons(SERVER_PORT); // short, network byte order

17 יצירת Socket בשפת - C המרת הכתובת לייצוג רשת/בינארי.
נעשה על ידי הפונקציה inet_pton(). משתמשים במבנה sockaddr_in וכתובת IPv4 או IPv6 לדוגמה: עבור כתובת IPv וכתובת IPv6 2001:db8:63b3:1::3490 הפונקציה ממירה את הכתובות לייצוג בינארי הפונקציה מחזירה -1 אם יש שגיאה או 0 אם ההמרה לא עברה בהצלחה. יש לוודא שערך המוחזר ע"י פונקציה inet_pton גדול מ-0. struct sockaddr_in sa; // IPv4 struct sockaddr_in6 sa6; // IPv6 inet_pton(AF_INET, " ", &(sa.sin_addr)); // IPv4 inet_pton(AF_INET6, "2001:db8:63b3:1::3490", &(sa6.sin6_addr)); // IPv6

18 יצירת Socket בשפת - C המרת הכתובת מייצוג רשת/בינארי
נעשה על ידי הפונקציה inet_ntop() אם משתמשים במבנים:sockaddr_in/ in_addr /in6_addr לדוגמה: עבור כתובת IPv וכתובת IPv6 2001:db8:63b3:1::3490 נשתמש בפונקציהinet_ntop() . לדוגמא: // IPv4: char ip4[INET_ADDRSTRLEN]; // space to hold the IPv4 string struct sockaddr_in sa; // pretend this is loaded with something inet_ntop(AF_INET, &(sa.sin_addr), ip4, INET_ADDRSTRLEN); printf("The IPv4 address is: %s\n", ip4); // IPv6: char ip6[INET6_ADDRSTRLEN]; // space to hold the IPv6 string struct sockaddr_in6 sa6; // pretend this is loaded with something inet_ntop(AF_INET6, &(sa6.sin6_addr), ip6, INET6_ADDRSTRLEN); printf("The address is: %s\n", ip6);

19 יצירת Socket בשפת - C שרת

20 יצירת Socket בשפת - C קישור כתובת ופורט עם סוקט ע"י פונקציה הסבר:
Sockfd-socket descriptor אשר מוחזר על "י פונקציה socket (השלב לפני חלוקה לשרת לקוח) my_addr- מצביע למבנה sockaddr המכיל כתובת ופורט של שרת אליו מתחברים(קיים הסבר בחלק קוד של הלקוח) namelen – גודל מבנה sockaddrבביתים. הפונקציה מחזירה ערך -1 אם יש שגיאה. אחרת, אפס. int bind(int sockfd, struct sockaddr *my_addr, int addrlen);

21 “Address already in use”
יצירת Socket בשפת - C לפעמים מנסים להפעיל שרת אך קישור bind נופל עם הודעה הבאה: “Address already in use” הבעיה נובעת מכך שביט קטן של סוקט שהיה מחובר עדיין בשימוש וזה טופס פורט. על מנת לאפשר שימוש חוזר של פורט, ניתן להוסיף את הקוד הבא: int yes=1; If (setsockopt(listener, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof yes) == -1){ perror("setsockopt"); exit(1); }

22 יצירת Socket בשפת - C אחרי פעולת bind השרת עובר למצב המתנה (מדובר על TCP בלבד) ע"י קריאת פונקציה הסבר: sockfd– socket descriptor אשר מוחזר על "י פונקציה socket backlog – גודל מקסימלי של תור הבקשות לחיבור. תור הבקשות לחיבור מוגבל ע"י כמות החיבורים שניתן להקים. הפונקציה מחזירה ערך -1 אם יש שגיאה. אחרת, 0. int listen(int sockfd, int backlog);

23 יצירת Socket בשפת - C הוצאת בקשה לחיבור מתוך תור הבקשות (מדובר על TCP בלבד) ע"י קריאת פונקציה: הפונקציה מחזירה socket descriptor של סוקט חדש שנוצר, ומכניסה למבנה sockaddr מידע אודות הלקוח שמתחבר (IP ו- Port) addrlen – משתנה שלם מקומי אשר מגדיר גודל מבנה sockaddr. הפונקציה מחזירה ערך -1 אם יש שגיאה. אחרת, 0. int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);

24 העברת מידע בין שרת ולקוח
TCP

25 העברת מידע בין שרת ולקוח
שליחת מידע: לפי פרוטוקול TCP (for communicating over stream sockets or connected datagram sockets( ע"י פונקציה: sockfd - socket descriptor דרכו שולחים מידע msg – מצביע למידע אשר שולחים len – גודל המידע בביתים flags – ערך שלו 0. הפונקציה מחזירה את כמות הביתים שנשלחה בפועל. כמות היכולה להיות פחות ממה שרצינו לשלוח. יש לוודא כמה נשלח בפועל ולהשלים את מה שחוסר. הפונקציה מחזירה ערך -1 אם יש שגיאה. int send(int sockfd, const void *msg, int len, int flags);

26 העברת מידע בין שרת ולקוח
שליחת מידע: דוגמא לפרוטוקול TCP: char *msg = “Haim was here!"; int len, bytes_sent; . . . len = strlen(msg); bytes_sent = send(sockfd, msg, len, 0);

27 העברת מידע בין שרת ולקוח
קבלת מידע: לפי פרוטוקול TCP ע"י פונקציה sockfd - socket descriptor דרכו קוראים מידע buf – מצביע לבאפר אשר קוראים בתוכו len – גודל מקסימלי של באפר בביתים flags – ערך שלו 0. הפונקציה מחזירה כמות הביתים שנקראו בתוך הבאפר. אם הפונקציה מחזירה ערך -1 אז יש שגיאה. אם פונקציה מחזירה 0 זה משקף כי חיבור נסגר. int recv(int sockfd, void *buf, int len, int flags);

28 העברת מידע בין שרת ולקוח
UDP

29 העברת מידע בין שרת ולקוח
שליחת מידע: לפי פרוטוקול UDP (unconnected datagram sockets) ע"י פונקציה: sockfd - socket descriptor דרכו שולחים מידע msg – מצביע למידע אשר שולחים len – גודל המידע בביתים flags – ערך שלו 0 to – מצביע למבנה sockaddr המכיל IP ו-Port של יעד tolen – גודל המבנה sockaddr. הפונקציה מחזירה את כמות הביתים שנשלחה בפועל. כמות היכולה להיות פחות ממה שרצינו לשלוח. יש לוודא כמה נשלח בפועל ולהשלים את מה שחוסר. הפונקציה מחזירה ערך -1 אם יש שגיאה. int sendto(int sockfd, const void *msg, int len, unsigned int flags, const struct sockaddr *to, socklen_t tolen);

30 העברת מידע בין שרת ולקוח
קבלת מידע: לפי פרוטוקול UDP ע"י פונקציה sockfd - socket descriptor דרכו קוראים מידע buf – מצביע לבאפר אשר קוראים בתוכו len – גודל מקסימלי של באפר בביתים flags – ערך שלו 0 from – מצביע למבנה המכיל IP ו-Port של השולח fromlen –מצביע למשתנה מקומי אשר יכיל גודל המבנה sockaddr . הפונקציה מחזירה את כמות הביתים שהתקבלו. אם הפונקציה מחזירה ערך -1 אז יש שגיאה. אם פונקציה מחזירה 0 זה משקף כי חיבור נסגר. int recvfrom(int sockfd, void *buf, int len, unsigned int flags, struct sockaddr *from, int *fromlen);

31 סגירת חיבור וסוקט

32 סגירת חיבור וסוקט int close(int sockfd);
נעשה ע"י הפונקציה: sockfd - socket file descriptor או ע"י שילוב שתי פונקציות: ערך של ארגומנט how קובע אופן סגירת חיבור: (SD_RECEIVE) 0 – סגירת חיבור לקבלת מידע (SD_SEND) 1– סגירת חיבור לשליחת מידע (SD_BOTH) 2– סגירת שני כיוונים – דומה לפונקציה close(). הפונקציה מחזירה 0 אם הפעולה עברה בהצלחה, אחרת, -1.  והפונקציה: int close(int sockfd); int shutdown(int sockfd, int how); int close(sockfd);

33 חומר רלוונטי נוסף

34 חומר רלוונטי נוסף מבנה ("in" for "Internet") sockaddr_in6 – עבור IPv6.
// (IPv6 only--see struct sockaddr_in and struct in_addr for IPv4) struct sockaddr_in6 { u_int16_t sin6_family; // address family, AF_INET6 u_int16_t sin6_port; // port number, Network Byte Order u_int32_t sin6_flowinfo; // IPv6 flow information struct in6_addr sin6_addr; // IPv6 address u_int32_t sin6_scope_id; // Scope ID }; struct in6_addr { unsigned char s6_addr[16]; // IPv6 address

35 חומר רלוונטי נוסף פונקציה getaddrinfo
res - pointer to a linked-list of results node - the host name to connect to, or an IP address service - or the name of a particular service port number hints - points to a struct addrinfo that was filled out with relevant information אם יש שגיאה, הפונקציה מחזירה ערך שונה מ-0. #include <sys/types.h> #include <sys/socket.h> #include <netdb.h> int getaddrinfo ( const char *node, // e.g. or IP const char *service, // e.g. "http" or port number const struct addrinfo *hints, struct addrinfo **res);

36 חומר רלוונטי נוסף דוגמא לשימוש בפונקציה getaddrinfo בתוכנת שרת:
int status; struct addrinfo hints; struct addrinfo *servinfo; // will point to the results memset(&hints, 0, sizeof hints); // make sure the struct is empty hints.ai_family = AF_UNSPEC; // don't care IPv4 or IPv6 hints.ai_socktype = SOCK_STREAM; // TCP stream sockets hints.ai_flags = AI_PASSIVE; // fill in my IP for me if ((status = getaddrinfo(NULL, "3490", &hints, &servinfo)) != 0) { fprintf(stderr, "getaddrinfo error: %s\n", gai_strerror(status)); exit(1); } // servinfo now points to a linked list of 1 or more struct addrinfos // ... do everything until you don't need servinfo anymore .... freeaddrinfo(servinfo); // free the linked-list

37 חומר רלוונטי נוסף דוגמא לשימוש בפונקציה getaddrinfo בתוכנת לקוח:
int status; struct addrinfo hints; struct addrinfo *servinfo; // will point to the results memset(&hints, 0, sizeof hints); // make sure the struct is empty hints.ai_family = AF_UNSPEC; // don't care IPv4 or IPv6 hints.ai_socktype = SOCK_STREAM; // TCP stream sockets // get ready to connect status = getaddrinfo(" "3490", &hints, &servinfo); // servinfo now points to a linked list of 1 or more struct addrinfos etc.

38 חומר רלוונטי נוסף הפונקציה getpeername
הפונקציה מחזירה כתובת של מחשב קצה ב-connected stream socket. במקרה של שגיאה תחזיר -1. sockfd - descriptor of the connected stream socket addr – מצביע למבנה sockaddr (או sockaddr_in) אשר מכיל מידע אודות מחשב קצה בחיבור addrlen – מצביע למספר שלם שמשקף גודל המבנה. לאחר שיש כתובת ניתן לקרוא לפונקציות הבאות לקבלת מידע נוסף: net_ntop() getnameinfo() gethostbyaddr() int getpeername(int sockfd, struct sockaddr *addr, int *addrlen);

39 חומר רלוונטי נוסף פונקציה gethostname
מחזירה שם המחשב עליו מריצים תוכנה (0) במקרה של שגיאה תחזיר -1. hostname-מצביע למערך תווים אשר יכיל שם מחשב קצה(host) size– גודל מערך hostname בביתים . לאחר מכן ניתן לקרוא לפונקציהgethostbyname לקבלת כתובת IP של המחשב. #include <unistd.h> int gethostname(char *hostname, size_t size);

40 חומר רלוונטי נוסף כמה מבנים (structs) שבשימוש ב-sockets interface:
struct addrinfo { int ai_flags; // AI_PASSIVE, AI_CANONNAME, etc. int ai_family; // AF_INET, AF_INET6, AF_UNSPEC int ai_socktype; // SOCK_STREAM, SOCK_DGRAM int ai_protocol; // use 0 for "any" size_t ai_addrlen; // size of ai_addr in bytes struct sockaddr *ai_addr; // struct sockaddr_in or _in6 char *ai_canonname; // full canonical hostname struct addrinfo *ai_next; // linked list, next node };

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

42 חומר למידה glepage/bgnet.html


Download ppt "תקשורת ומחשוב תרגול 3-5 סוקטים ב-C."

Similar presentations


Ads by Google