תקשורת ב-Linux ו- Unix מנגנון תקשורת ב-Linux סכמת שרת לקוח:...

24
בבבבבב ב-Linux ב-Unix בבבבבב בבבבבב ב-Linux :בבבב בבב בבבבclient/server
  • date post

    19-Dec-2015
  • Category

    Documents

  • view

    255
  • download

    10

Transcript of תקשורת ב-Linux ו- Unix מנגנון תקשורת ב-Linux סכמת שרת לקוח:...

Page 1: תקשורת ב-Linux ו- Unix מנגנון תקשורת ב-Linux סכמת שרת לקוח: client/server.

Linux-תקשורת בUnix-ו

מנגנון תקשורת ב-Linuxסכמת שרת לקוח:

client/server

Page 2: תקשורת ב-Linux ו- Unix מנגנון תקשורת ב-Linux סכמת שרת לקוח: client/server.

:Linux- – ניהול זיכרון ב11תרגול סקירה 2(c) 2003 ארז חדד

מודל השכבות

: חיבורים המאפשרים תקשורת בין מחשביםרשת תקשורתמאפשרים העברת נתונים ברשתפרוטוקולי תקשורת .פועלים בשכבות שונות, כשלכל שכבה תפקיד משלה אוסף פרוטוקולי התקשורת הנפוץ ביותר נקראTCP/IP

שכבות4מכיל

Application (telnet, ftp …)אפליקציות המשתמשות ברשת

Transport (TCP, UDP)(ולא מחשבים) תקשורת בין תהליכים

Internet (IP)(לא שכנות) ניתוב חבילות בין תחנות

Data Link העברת חבילה בין תחנות שכנות

Page 3: תקשורת ב-Linux ו- Unix מנגנון תקשורת ב-Linux סכמת שרת לקוח: client/server.

:Linux- – ניהול זיכרון ב11תרגול סקירה 3(c) 2003 ארז חדד

Networking API של LinuxLinux.תומכת במספר רב של ארכיטקטורות רשת נתמקד בתמיכה שלLinux בפרוטוקולי TCP/IP:

קריאות מערכת המאפשרות יצירת תקשורת עם תהליכיםמרוחקים.

מבני נתונים המשמשים את קריאות המערכת הנ"ל-כל קריאות המערכת שנראה משתמשות בsockets.

-תחילה נגדיר את הsocketואח"כ נחבר אותו לפורט המתאים ,

: עבור כל הקריאות צריך להוסיף#include <sys/types.h>#include <sys/socket.h>

Page 4: תקשורת ב-Linux ו- Unix מנגנון תקשורת ב-Linux סכמת שרת לקוח: client/server.

:Linux- – ניהול זיכרון ב11תרגול סקירה 4(c) 2003 ארז חדד

חדשsocketיצירת הממשק:int socket(int family, int type, int protocol)

פרמטרים:family) ארכיטקטורת הרשת לביצוע התקשורתAF_INET(

type .מודל התקשורת ברשתSOCK_STREAM עבור תקשורת connection oriented מבוססת ,

stream ואמינה (ממומשת ע"י TCP(

protocol מגדיר את פרוטוקול התקשורת של שכבת ה Transport . בוחר את פרוטוקול ברירת המחדל (0פרמטר TCP עבור

SOCK_STREAM(

המצביע descriptor במקרה של הצלחה, מחזיר ערך חזרה: החדש socketל--שייך לPDT של התהליך כמו descriptors אחרים המצביעים על קבצים

, ...pipesפתוחים,

Page 5: תקשורת ב-Linux ו- Unix מנגנון תקשורת ב-Linux סכמת שרת לקוח: client/server.

:Linux- – ניהול זיכרון ב11תרגול סקירה 5(c) 2003 ארז חדד

לפורטsocketקישור של הממשק:

int bind(int sockfd, struct sockaddr * my_addr, int addrlen)

פרמטרים:sockfd -הdescriptor-של ה socket.אותו מחברים

my_addr .כתובת אליה מקשרים של המחשב המקומיIPהכתובת מכילה את כתובת ה-

socket אליו יקושר ה-portואת מספר ה-addrlen אורך שלmy_addr .בבתים

במקרה של כישלון.1 במקרה של הצלחה, 0 ערך חזרה:

Page 6: תקשורת ב-Linux ו- Unix מנגנון תקשורת ב-Linux סכמת שרת לקוח: client/server.

:Linux- – ניהול זיכרון ב11תרגול סקירה 6(c) 2003 ארז חדד

הממשק: האזנה

הצהרת כוונה לקבל בקשות תקשורת והגדרת אורך תור מקסימלי של בקשות ממתינות.

int listen(int sockfd, int num)פרמטרים:

sockfd-מזהה של הsocket num מספר מקסימלי של בקשות התחברות ממתינות

במקרה של כישלון.1 במקרה של הצלחה, 0 ערך חזרה:

Page 7: תקשורת ב-Linux ו- Unix מנגנון תקשורת ב-Linux סכמת שרת לקוח: client/server.

:Linux- – ניהול זיכרון ב11תרגול סקירה 7(c) 2003 ארז חדד

הממשק: קבלת בקשות הנתון לבקשות תקשורת. אם יש בקשות הממתינות בתור:socketמחכה על ה-

מוציא בקשה מהתור יוצרsocket חדש ומקצה לו descriptor.חדש

int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen)

:פרמטריםsockfd-ה descriptor-של ה socketעליו מחכים לבקשות תקשורת

Addr .כתובת שולח בקשת תקשורת שהתקבלה, מוצב בתוך הקריאהaddrlen.אורך הכתובת בבתים

החדש שנוצר, socket של ה- descriptor במקרה של הצלחה ה-ערך חזרה:-.1אחרת

Page 8: תקשורת ב-Linux ו- Unix מנגנון תקשורת ב-Linux סכמת שרת לקוח: client/server.

:Linux- – ניהול זיכרון ב11תרגול סקירה 8(c) 2003 ארז חדד

הממשק: התחברותמנסה ליצור תקשורת עם תהליך שמקשיב על הכתובת

serv_addr מורכבת מכתובת) IP ומספר port(

int connect(int sockfd, const struct sockaddr* serv_addr, socklen_t addrlen)

פרמטרים:sockfd-הdescriptor של socket

serv_addrהכתובת עליה מקשיב התהליך איתו מנסים להתקשרaddrlen.אורך הכתובת בבתים

במקרה של כישלון.1 במקרה של הצלחה, 0 ערך חזרה:

Page 9: תקשורת ב-Linux ו- Unix מנגנון תקשורת ב-Linux סכמת שרת לקוח: client/server.

:Linux- – ניהול זיכרון ב11תרגול סקירה 9(c) 2003 ארז חדד

socketהממשק: כתיבה ל -אפשר לכתוב לsocket באמצעות קריאת write .כמו לקבצים ,-הdescriptor שמועבר הוא descriptor-של ה socket ,השולח

אליו מקשיב התהליך השני. socketוההודעה תועבר ל-

פעולה מיוחדת, עם דגלים לאפשרויות שליחה מיוחדות

int send(int sockfd,const void *msg, size_t len, int flags)

,ערך חזרה: במקרה של הצלחה, מספר הבתים שנשלחו-.1אחרת

Page 10: תקשורת ב-Linux ו- Unix מנגנון תקשורת ב-Linux סכמת שרת לקוח: client/server.

:Linux- – ניהול זיכרון ב11תרגול סקירה 10(c) 2003 ארז חדד

socketהממשק: קריאה מה

, כמו לקבצים. read באמצעות קריאת socketניתן לקרוא מה-

הקורא, socket של ה-descriptor שמועבר הוא descriptorה- אחר.socket) ל- connectedשחייב להיות מחובר (

פעולה מיוחדת, עם דגלים לאפשרויות קריאה מיוחדות

int recv(int sockfd, void *buf, size_t len, int flags)

במקרה של הצלחה, מספר הבתים שנקראו, אחרת ערך חזרה:1.-

Page 11: תקשורת ב-Linux ו- Unix מנגנון תקשורת ב-Linux סכמת שרת לקוח: client/server.

:Linux- – ניהול זיכרון ב11תרגול סקירה 11(c) 2003 ארז חדד

socketסגירת הממשק:

סגירת התקשורת עם המחשב המרוחק ושחרור .socket שהצביע על ה-descriptorה-

int close (int sockfd)

פרמטר:sockfd-הdescriptor -של ה socket.לסגירה

במקרה של 1 במקרה של הצלחה, 0 ערך חזרה:כישלון.

Page 12: תקשורת ב-Linux ו- Unix מנגנון תקשורת ב-Linux סכמת שרת לקוח: client/server.

:Linux- – ניהול זיכרון ב11תרגול סקירה 12(c) 2003 ארז חדד

client/serverסכמת שרת לקוח: ,מבקש שירות מתהליך אחר, הלקוחתהליך אחד ,

. השרת למשל, שרתיtelnet, web, ftp ..השרת מטפל בבקשות של מספר לקוחות בו זמנית

לדוגמה, שרתtelnet לבקשות 23 "מקשיב" על פורט התחברות מלקוחות (שזהותם לא ידועה מראש)

כשמתקבלת בקשת התחברות נוצרtelnet session בין השרת ללקוח שהתחבר.

-נשתמש בsockets: מאפשרים לאפליקציה להבדיל ביןtelnet sessions .שונים לכלsession מתאים זוג sockets.בשרת ובלקוח

Page 13: תקשורת ב-Linux ו- Unix מנגנון תקשורת ב-Linux סכמת שרת לקוח: client/server.

:Linux- – ניהול זיכרון ב11תרגול סקירה 13(c) 2003 ארז חדד

באופן לא connectionיצירת סימטרי

השרת יוצרsocketמחבר אותו לפורט עליו הוא מקשיב מחכה על הsocketלבקשות תקשורת נכנסות

הלקוח יוצרsocket מנסה להתחבר אל כתובתIPופורט של השרת

כאשרconnection :מוקם, התקשורת היא סימטרית socketשני הצדדים יכולים לשלוח הודעות אחד לשני דרך ה

כלTCP sessionשנוצר כך מוגדר באופן חד ערכי ע"י רביעיה )source IP, source Port, destination IP, destination Port(

Page 14: תקשורת ב-Linux ו- Unix מנגנון תקשורת ב-Linux סכמת שרת לקוח: client/server.

:Linux- – ניהול זיכרון ב11תרגול סקירה 14(c) 2003 ארז חדד

socketsמימוש של שרת-לקוח עם Client side:

sd=socket()

connect(sd, dst)

write(sd, …)

read(sd, …)

close(sd)

Server side:

sd=socket()

bind(sd, port)

listen(sd,…)

new_sd=accept(sd)

write(new_sd, …)

read(new_sd, …)

close(new_sd)

Page 15: תקשורת ב-Linux ו- Unix מנגנון תקשורת ב-Linux סכמת שרת לקוח: client/server.

:Linux- – ניהול זיכרון ב11תרגול סקירה 15(c) 2003 ארז חדד

: socketsמימוש שרת-לקוח עם הסברים

השרת חייב לקרוא לbind() כדי לחבר את ה sd שלו port מסוים (אחרת הוא יחכה לבקשות על portל

אקראי) בדרך כלל כמה לקוחות שולחים בקשות לתקשורת

בתוך kernelעם השרת. בקשות אלה נשמרות ע"י ה מגדירה את אורך התור.listenתור. כאמור

השרת מקבל כל פעם בקשה אחת ע"יaccept() כאשר הטיפול בבקשה הוא ארוך, כדאי אחרי

accept() לעשות fork() ולתת לבן לטפל בבקשה ולאב לקבל את הבקשות האחרות. אפשרות נוספת

היא טיפול בבקשות ע"י חוטים חדשים

Page 16: תקשורת ב-Linux ו- Unix מנגנון תקשורת ב-Linux סכמת שרת לקוח: client/server.

:Linux- – ניהול זיכרון ב11תרגול סקירה 16(c) 2003 ארז חדד

מציאת כתובת).hostname של מחשב ברשת לפי שם המחשב (IPמציאת כתובת

struct hostent * gethostbyname(const char *hostname);

פרמטרים:hostname שם המחשב –

ערך חזרה:struct hostent* .מצביע למבנה נתונים המתאר את המחשב המבוקש -

דוגמא:struct hostent *h =

gethostbyname(“t2.technion.ac.il”)h->h_addr יכיל את כתובת ה IP של t2

h->h_lenght אורך ה h->h_addr h->h_name יכיל את המחרוזת t2.technion.ac.il

Page 17: תקשורת ב-Linux ו- Unix מנגנון תקשורת ב-Linux סכמת שרת לקוח: client/server.

:Linux- – ניהול זיכרון ב11תרגול סקירה 17(c) 2003 ארז חדד

Endiansהחלפת במעבדים שונים, יש סדר שונה בין

LSB (least significant byte) . MSB (most significant byte)ו

כדי שנוכל להעביר אינפורמציה בין מחשבים שונים ברשת, ) ליצוג אחיד. int, short, longצריכים להעביר את המספרים (

הפונקציות הבאות:4בזה מטפלות u_long htonl(u_long); // host to network long (32 bits)u_short htons(u_short); // host to network short (16 bits)u_long ntohl(u_long); // network to host long (32 bits)u_short ntohs(u_short); // network to host short (16 bits)

Page 18: תקשורת ב-Linux ו- Unix מנגנון תקשורת ב-Linux סכמת שרת לקוח: client/server.

:Linux- – ניהול זיכרון ב11תרגול סקירה 18(c) 2003 ארז חדד

מבני נתונים לכתובותstruct sockaddr_in {

short int sin_family; //Address family, AF_xxxunsigned short int sin_port; // Port number struct in_addr sin_addr; // Internet address unsigned char sin_zero[8]; // for allignments

};

struct sockaddr { unsigned short sa_family; // address family, AF_xxx char sa_data[14]; // 14 bytes of protocol address

};

struct in_addr { unsigned long s_addr; //32-bit long,(4 bytes) IP address

}

Page 19: תקשורת ב-Linux ו- Unix מנגנון תקשורת ב-Linux סכמת שרת לקוח: client/server.

:Linux- – ניהול זיכרון ב11תרגול סקירה 19(c) 2003 ארז חדד

1קוד שרת #include <sys/types.h>#include <sys/socket.h>#include <netinet/in.h>void error(char *msg) { perror(msg); exit(1);}int main(int argc, char *argv[]) { int sockfd, newsockfd, portno, clilen; char buffer[256]; struct sockaddr_in serv_addr, cli_addr; int n;

if (argc < 2) { fprintf(stderr,"ERROR, no port provided\n"); exit(1); }

Page 20: תקשורת ב-Linux ו- Unix מנגנון תקשורת ב-Linux סכמת שרת לקוח: client/server.

:Linux- – ניהול זיכרון ב11תרגול סקירה 20(c) 2003 ארז חדד

2קוד שרת

sockfd = socket(AF_INET,SOCK_STREAM,0);if (sockfd < 0) error("ERROR opening socket");bzero((char *) &serv_addr, sizeof(serv_addr));portno = atoi(argv[1]);serv_addr.sin_family = AF_INET; serv_addr.sin_addr.s_addr = INADDR_ANY;serv_addr.sin_port = htons(portno);if (bind(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0)

error("ERROR on binding"); listen(sockfd,5); clilen = sizeof(cli_addr);

Page 21: תקשורת ב-Linux ו- Unix מנגנון תקשורת ב-Linux סכמת שרת לקוח: client/server.

:Linux- – ניהול זיכרון ב11תרגול סקירה 21(c) 2003 ארז חדד

3קוד שרת

newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, &clilen);

if (newsockfd < 0) error("ERROR on accept");

bzero(buffer,256);n = read(newsockfd, buffer, 255); if (n < 0)

error("ERROR reading from socket");printf("Here is the message: %s\n",buffer);n = write(newsockfd,"I got your message",18);if (n < 0)

error("ERROR writing to socket");close(newsockfd);close(sockfd); //or goto accept to wait for another clientsreturn 0; ?האם הקוד הנ"ל תמיד יעבוד נכון

Page 22: תקשורת ב-Linux ו- Unix מנגנון תקשורת ב-Linux סכמת שרת לקוח: client/server.

:Linux- – ניהול זיכרון ב11תרגול סקירה 22(c) 2003 ארז חדד

1קוד לקוח

#include <stdio.h>#include <sys/types.h>#include <sys/socket.h>#include <netinet/in.h>#include <netdb.h>

void error(char *msg) { perror(msg); exit(0);

}

int main(int argc, char *argv[]) { int sockfd, portno, n; struct sockaddr_in serv_addr; struct hostent *server; char buffer[256];

Page 23: תקשורת ב-Linux ו- Unix מנגנון תקשורת ב-Linux סכמת שרת לקוח: client/server.

:Linux- – ניהול זיכרון ב11תרגול סקירה 23(c) 2003 ארז חדד

2קוד לקוח if (argc < 3) { fprintf(stderr,"usage %s hostname port\n",

argv[0]); exit(0);}sockfd = socket(AF_INET, SOCK_STREAM, 0);if (sockfd < 0) error("ERROR opening socket");portno = atoi(argv[2]);server = gethostbyname(argv[1]);if (server == NULL) { fprintf(stderr,"ERROR, no such host\n"); exit(0);} bzero((char *) &serv_addr, sizeof(serv_addr)); serv_addr.sin_family = AF_INET;

Page 24: תקשורת ב-Linux ו- Unix מנגנון תקשורת ב-Linux סכמת שרת לקוח: client/server.

:Linux- – ניהול זיכרון ב11תרגול סקירה 24(c) 2003 ארז חדד

3קוד לקוח

bcopy((char *)server->h_addr, (char *) &serv_addr.sin_addr.s_addr, server->h_length);

serv_addr.sin_port = htons(portno); if (connect(sockfd,&serv_addr,sizeof(serv_addr)) < 0)(

error("ERROR connecting"); n = write(sockfd, ”HELLO THERE”, sizeof(“HELLO THERE”)); if (n < 0) error("ERROR writing to socket"); bzero(buffer,256); n = read(sockfd,buffer,255); if (n < 0) error("ERROR reading from socket"); printf("%s\n",buffer);

close(sockfd); return 0;}

האם הקוד הנ"ל תמיד יעבוד נכון?