Η παρουσίαση φορτώνεται. Παρακαλείστε να περιμένετε

Η παρουσίαση φορτώνεται. Παρακαλείστε να περιμένετε

University of Cyprus Department of Computer Science Presenter : Yiannos Mylonas EPL475: Advanced Networks TCP/IP Socket Programming in C.

Παρόμοιες παρουσιάσεις


Παρουσίαση με θέμα: "University of Cyprus Department of Computer Science Presenter : Yiannos Mylonas EPL475: Advanced Networks TCP/IP Socket Programming in C."— Μεταγράφημα παρουσίασης:

1 University of Cyprus Department of Computer Science Presenter : Yiannos Mylonas EPL475: Advanced Networks TCP/IP Socket Programming in C

2 Identifying the ultimate destination IP addresses identify hosts Host has many applications Ports (16-bit identifier) 194.42.16.25 Port 80 25 23 Application WWW E-mail Telnet Ports

3 Socket How does one speak TCP/IP? Sockets provides interface to TCP/IP Generic interface for many protocols

4 Socket Types

5 TCP επικοινωνία client/server Δημιουργία Υποδοχής Συσχέτιση Υποδοχής με διεύθυνση Ακούει για εισερχόμενες αιτήσεις Αποδέχεται αίτημα σύνδεσης Διαβάζει από τη σύνδεση Γράφει στη σύνδεση Δημιουργία Υποδοχής Διαβάζει από τη σύνδεση Γράφει στη σύνδεση Υποβολή αιτήματος σύνδεσης Εξυπηρετητής Πελάτης

6 Επικοινωνία μεταξύ διεργασιών Πεδία υποδοχών –PF_INET Πεδίο Internet Επικοινωνία και σε διαφορετικούς υπολογιστές Διεύθυνση: Internet διεύθυνση και αριθμός θύρας –PF_UNIX Πεδίο Unix Επικοινωνία στον ίδιο υπολογιστή Διεύθυνση: Κόμβος στο σύστημα αρχείων Είδη υποδοχών –SOCK_STREAM Υποδοχές ροής (TCP) –SOCK_DGRAM Τηλεγραφικές υποδοχές (UDP) TCPUDP Απαίτηση σύνδεσηςNAIOXI ΑξιοπιστίαNAIOXI Όρια μηνυμάτωνOXINAI Διαδοχικότητα μηνυμάτωνNAIOXI

7 Διαχείριση υποδοχών Όλες οι κλήσεις του συστήματος που ακολουθούν και χρησιμοποιούνται για διαχείριση υποδοχών απαιτούν –#include –Επιστρέφουν -1 σε περίπτωση αποτυχίας

8 TCP επικοινωνία client/server Δημιουργία Υποδοχής Συσχέτιση Υποδοχής με διεύθυνση Ακούει για εισερχόμενες αιτήσεις Αποδέχεται αίτημα σύνδεσης Διαβάζει από τη σύνδεση Γράφει στη σύνδεση Δημιουργία Υποδοχής Διαβάζει από τη σύνδεση Γράφει στη σύνδεση Υποβολή αιτήματος σύνδεσης Εξυπηρετητής Πελάτης

9 Διαχείριση υποδοχών Κλήση συστήματος socket –Δημιουργεί μια νέα υποδοχή του τύπου type (π.χ. SOCK_STREAM) στο πεδίο domain (π.χ. AF_INET) χρησιμοποιώντας το πρωτόκολλο protocol (π.χ. IPPROTO_TCP, IPPROTO_UDP) και επιστρέφει τον περιγραφέα αρχείου που αντιστοιχεί σε αυτήν. Το domain πρέπει να είναι PF_INET ή PF_UNIX To type πρέπει να είναι SOCK_STREAM ή SOCK_DGRAM Σαν protocol, δίνουμε το default (0)

10 TCP/IP Sockets FamilyType Protocol TCP PF_INET SOCK_STREAMIPPROTO_TCP UDPSOCK_DGRAMIPPROTO_UDP mySock = socket(family, type, protocol); TCP/IP-specific sockets Socket reference –File (socket) descriptor in UNIX –Socket handle in WinSock

11 Δομή Διεύθυνσης Υποδοχής Μια δομή διεύθυνσης προσδιορίζει μια υποδοχή σε μια συγκεκριμένη οικογένεια πεδίων υποδοχών. –Η TCP/IP σουίτα απαιτεί μια IP διεύθυνση και ένα αριθμό θύρας για κάθε διεύθυνση υποδοχής. Η μορφή της διεύθυνσης είναι συγκεκριμένη για κάθε πεδίο (π.χ. πεδίο Ίντερνετ IPv4, πεδίο Ίντερνετ IPv6, πεδίο UNIX). Για να μπορούν διαφορετικές μορφές διευθύνσεων να περνούν σε συναρτήσεις υποδοχών, οι μορφές αυτές «μορφοποιούνται» (casting) σε μια γενική δομή διεύθυνσης υποδοχής (struct sockaddr). Δομή Ίντερνετ Διεύθυνσης για IPv4 πεδίο υποδοχών (struct sockaddr_in) /* Structure describing an Internet socket address. */ struct sockaddr_in { sa_family_t sin_family;/* address family */ in_port_t sin_port;/* Port number. */ struct in_addr sin_addr;/* Internet IPv4 address. */ };

12 Generic IP Specific sockaddr sockaddr_in Family Port Blob Internet address Not used 2 bytes 4 bytes 8 bytes struct in_addr { unsigned long s_addr; /* Internet address (32-bits) */ }; struct sockaddr_in { unsigned short sin_family;/* Internet protocol (AF_INET) */ unsigned short sin_port; /* Port (16-bits) */ struct in_addr sin_addr; /* Internet address (32-bits) */ char sin_zero[8]; /* Not used */ }; struct sockaddr { unsigned short sa_family;/* Address family (e.g., AF_INET) */ char sa_data[14]; /* Protocol-specific address information */ };

13 TCP επικοινωνία client/server Δημιουργία Υποδοχής Συσχέτιση Υποδοχής με διεύθυνση Ακούει για εισερχόμενες αιτήσεις Αποδέχεται αίτημα σύνδεσης Διαβάζει από τη σύνδεση Γράφει στη σύνδεση Δημιουργία Υποδοχής Διαβάζει από τη σύνδεση Γράφει στη σύνδεση Υποβολή αιτήματος σύνδεσης Εξυπηρετητής Πελάτης

14 int sockfd; struct sockaddr_in my_addr; sockfd = socket(PF_INET, SOCK_STREAM, 0); my_addr.sin_family = AF_INET; my_addr.sin_port = htons(MYPORT); my_addr.sin_addr.s_addr = inet_addr("10.12.110.57"); memset(my_addr.sin_zero, '\0', sizeof my_addr.sin_zero); bind(sockfd, (struct sockaddr *)&my_addr, sizeof my_addr); Κλήση συστήματος bind bind –Συσχέτιση υποδοχής, που έχει δημιουργηθεί και αντιστοιχεί στον περιγραφέα αρχείου fd, με συγκεκριμένη διεύθυνση *address (IP διεύθυνση και αριθμό θύρας). –Με αυτό τον τρόπο, ο πυρήνας μπορεί να καθοδηγήσει αιτήματα από πελάτες στη διεργασία με το συγκεκριμένο περιγραφέα υποδοχής. int bind(int fd, struct sockaddr *address, unsigned int addresslen) Περιγραφέας αρχείου Δείχτης που δείχνει από πού να πάρει πληροφορίες για την διεύθυνση και την θύρα του server Το μέγεθος της διεύθυνσης (address) server_addr.sin_port = htons(0); Επιλέγει τυχαία ο πυρήνας ένα ελεύθερο αριθμό θύρας server_addr.sin_addr.s_addr = htonl(INADDR_ANY); Χρησιμοποιείται αυτόματα η IP διεύθυνση της μηχανής στην οποία η συγκεκριμένη διεργασία τρέχει

15 TCP επικοινωνία client/server Δημιουργία Υποδοχής Συσχέτιση Υποδοχής με διεύθυνση Ακούει για εισερχόμενες αιτήσεις Αποδέχεται αίτημα σύνδεσης Διαβάζει από τη σύνδεση Γράφει στη σύνδεση Δημιουργία Υποδοχής Διαβάζει από τη σύνδεση Γράφει στη σύνδεση Υποβολή αιτήματος σύνδεσης Εξυπηρετητής Πελάτης

16 Διαχείριση υποδοχών listen, accept και connect Κλήση συστήματος listen –Ο εξυπηρετητής ανακοινώνει ότι είναι πρόθυμος να δεκτεί αιτήσεις σύνδεσης από πελάτες. queuelength –Ορίζει μια ουρά μήκους queuelength σε ένα server στην οποία μπορούν να συσσωρεύονται αιτήσεις από clients για σύνδεση στην υποδοχή που αντιστοιχεί στον περιγραφέα αρχείου fd int listen(int fd, int queuelength)

17 TCP επικοινωνία client/server Δημιουργία Υποδοχής Συσχέτιση Υποδοχής με διεύθυνση Ακούει για εισερχόμενες αιτήσεις Αποδέχεται αίτημα σύνδεσης Διαβάζει από τη σύνδεση Γράφει στη σύνδεση Δημιουργία Υποδοχής Διαβάζει από τη σύνδεση Γράφει στη σύνδεση Υποβολή αιτήματος σύνδεσης Εξυπηρετητής Πελάτης

18 Διαχείριση υποδοχών accept Κλήση συστήματος accept –Αποδέχεται μια αίτηση σύνδεσης που έχει υποβληθεί σε ένα server στην υποδοχή με περιγραφέα αρχείου fd int accept(int fd, struct sockaddr *address, unsigned int *addresslen) Επιστρέφει ένα νέο περιγραφέα αρχείου ο οποίος πρέπει να χρησιμοποιηθεί από τον server για επικοινωνία με τον client Πληροφορίες για τη διεύθυνση του client που συνδέθηκε επιστρέφονται μέσω της δομής *address το μέγεθος της οποίας επιστρέφεται στο *addresslen Περιγραφέας αρχείου

19 TCP επικοινωνία client/server Δημιουργία Υποδοχής Συσχέτιση Υποδοχής με διεύθυνση Ακούει για εισερχόμενες αιτήσεις Αποδέχεται αίτημα σύνδεσης Διαβάζει από τη σύνδεση Γράφει στη σύνδεση Δημιουργία Υποδοχής Διαβάζει από τη σύνδεση Γράφει στη σύνδεση Υποβολή αιτήματος σύνδεσης Εξυπηρετητής Πελάτης

20 Διαχείριση υποδοχών connect Κλήση συστήματος connect (client) Υποβολή αίτησης σύνδεσης από ένα client μέσω υποδοχής που αντιστοιχεί στον περιγραφέα αρχείου fd με το server του οποίου η διεύθυνση έχει κατασκευασθεί στη δομή *serv_address το μέγεθος της οποίας έχει τεθεί στο addresslen int connect(int fd, struct sockaddr *serv_address, unsigned int addresslen)

21 TCP επικοινωνία client/server Δημιουργία Υποδοχής Συσχέτιση Υποδοχής με διεύθυνση Ακούει για εισερχόμενες αιτήσεις Αποδέχεται αίτημα σύνδεσης Διαβάζει από τη σύνδεση Γράφει στη σύνδεση Δημιουργία Υποδοχής Διαβάζει από τη σύνδεση Γράφει στη σύνδεση Υποβολή αιτήματος σύνδεσης Εξυπηρετητής Πελάτης

22 Διαχείριση υποδοχών: recv και send Κλήσεις συστήματος recv και send –Χρησιμοποιούνται για την παραλαβή και την αποστολή μηνυμάτων int recv(int sockfd, void *buf, int len, unsigned int flags) Περιγραφέας αρχείου Δείχτης που δείχνει σε ποια διεύθυνση είναι καταχωρημένα τα δεδομένα που θέλουμε να διαβάσουμε. Το μέγεθος του msg Flags = 0 Επιστρέφει τον αριθμό των bytes που έχει διαβάσει από το buffer.

23 Διαχείριση υποδοχών: recv και send Κλήσεις συστήματος recv και send –Χρησιμοποιούνται για την παραλαβή και την αποστολή μηνυμάτων int send(int sockfd, const void *msg, int len, int flags) Περιγραφέας αρχείου Δείχτης που δείχνει σε ποια διεύθυνση είναι καταχωρημένα τα δεδομένα που θέλουμε να στείλουμε Το μέγεθος του msg Flags = 0 Επιστρέφει τον αριθμό των bytes που έχει στείλει.

24 Κλείσιμο Σύνδεσης Κλήση συστήματος: close –int close(int fd); –Κλείσιμο του περιγραφέα υποδοχής, αποδέσμευση του αριθμού θύρας. Κλήση συστήματος shutdown –int shutdown(int sockfd, int how); –Επιστρέφει 0 σε περίπτωση επιτυχίας, ή -1 σε λάθος –Αλλαγή χρήσης της υποδοχής: how = 0  δεν επιτρέπονται περαιτέρω παραλαβές how = 1  δεν επιτρέπονται περαιτέρω αποστολές how = 3  δεν επιτρέπονται περαιτέρω παραλαβές και αποστολές (δεν κλείνει τη σύνδεση)

25 TCP Client/Server Interaction Client 1.Create a TCP socket 2.Establish connection 3.Communicate 4.Close the connection Server 1.Create a TCP socket 2.Assign a port to socket 3.Set socket to listen 4.Repeatedly: a.Accept new connection b.Communicate c.Close the connection The server starts by getting ready to receive client connections…

26 TCP Client/Server Interaction /* Create socket for incoming connections */ if ((servSock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) DieWithError("socket() failed"); Client 1.Create a TCP socket 2.Establish connection 3.Communicate 4.Close the connection Server 1.Create a TCP socket 2.Assign a port to socket 3.Set socket to listen 4.Repeatedly: a.Accept new connection b.Communicate c.Close the connection

27 TCP Client/Server Interaction echoServAddr.sin_family = AF_INET; /* Internet address family */ echoServAddr.sin_addr.s_addr = htonl(INADDR_ANY);/* Any incoming interface */ echoServAddr.sin_port = htons(echoServPort); /* Local port */ if (bind(servSock, (struct sockaddr *) &echoServAddr, sizeof(echoServAddr)) < 0) DieWithError("bind() failed"); Client 1.Create a TCP socket 2.Establish connection 3.Communicate 4.Close the connection Server 1.Create a TCP socket 2.Assign a port to socket 3.Set socket to listen 4.Repeatedly: a.Accept new connection b.Communicate c.Close the connection

28 TCP Client/Server Interaction /* Mark the socket so it will listen for incoming connections */ if (listen(servSock, MAXPENDING) < 0) DieWithError("listen() failed"); Client 1.Create a TCP socket 2.Establish connection 3.Communicate 4.Close the connection Server 1.Create a TCP socket 2.Assign a port to socket 3.Set socket to listen 4.Repeatedly: a.Accept new connection b.Communicate c.Close the connection

29 TCP Client/Server Interaction for (;;) /* Run forever */ { clntLen = sizeof(echoClntAddr); if ((clntSock=accept(servSock,(struct sockaddr *)&echoClntAddr,&clntLen)) < 0) DieWithError("accept() failed"); Client 1.Create a TCP socket 2.Establish connection 3.Communicate 4.Close the connection Server 1.Create a TCP socket 2.Assign a port to socket 3.Set socket to listen 4.Repeatedly: a.Accept new connection b.Communicate c.Close the connection

30 TCP Client/Server Interaction Server is now blocked waiting for connection from a client Later, a client decides to talk to the server… Client 1.Create a TCP socket 2.Establish connection 3.Communicate 4.Close the connection Server 1.Create a TCP socket 2.Assign a port to socket 3.Set socket to listen 4.Repeatedly: a.Accept new connection b.Communicate c.Close the connection

31 TCP Client/Server Interaction /* Create a reliable, stream socket using TCP */ if ((sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) DieWithError("socket() failed"); Client 1.Create a TCP socket 2.Establish connection 3.Communicate 4.Close the connection Server 1.Create a TCP socket 2.Assign a port to socket 3.Set socket to listen 4.Repeatedly: a.Accept new connection b.Communicate c.Close the connection

32 TCP Client/Server Interaction echoServAddr.sin_family = AF_INET; /* Internet address family */ echoServAddr.sin_addr.s_addr = inet_addr(servIP); /* Server IP address */ echoServAddr.sin_port = htons(echoServPort); /* Server port */ if (connect(sock, (struct sockaddr *) &echoServAddr, sizeof(echoServAddr)) < 0) DieWithError("connect() failed"); Client 1.Create a TCP socket 2.Establish connection 3.Communicate 4.Close the connection Server 1.Create a TCP socket 2.Assign a port to socket 3.Set socket to listen 4.Repeatedly: a.Accept new connection b.Communicate c.Close the connection

33 TCP Client/Server Interaction if ((clntSock=accept(servSock,(struct sockaddr *)&echoClntAddr,&clntLen)) < 0) DieWithError("accept() failed"); Client 1.Create a TCP socket 2.Establish connection 3.Communicate 4.Close the connection Server 1.Create a TCP socket 2.Assign a port to socket 3.Set socket to listen 4.Repeatedly: a.Accept new connection b.Communicate c.Close the connection

34 TCP Client/Server Interaction echoStringLen = strlen(echoString); /* Determine input length */ /* Send the string to the server */ if (send(sock, echoString, echoStringLen, 0) != echoStringLen) DieWithError("send() sent a different number of bytes than expected"); Client 1.Create a TCP socket 2.Establish connection 3.Communicate 4.Close the connection Server 1.Create a TCP socket 2.Assign a port to socket 3.Set socket to listen 4.Repeatedly: a.Accept new connection b.Communicate c.Close the connection

35 TCP Client/Server Interaction /* Receive message from client */ if ((recvMsgSize = recv(clntSocket, echoBuffer, RCVBUFSIZE, 0)) < 0) DieWithError("recv() failed"); Client 1.Create a TCP socket 2.Establish connection 3.Communicate 4.Close the connection Server 1.Create a TCP socket 2.Assign a port to socket 3.Set socket to listen 4.Repeatedly: a.Accept new connection b.Communicate c.Close the connection

36 TCP Client/Server Interaction close(sock); close(clntSocket) Client 1.Create a TCP socket 2.Establish connection 3.Communicate 4.Close the connection Server 1.Create a TCP socket 2.Assign a port to socket 3.Set socket to listen 4.Repeatedly: a.Accept new connection b.Communicate c.Close the connection

37 Μετατροπή ακολουθίας bytes Διαφορετικές αρχιτεκτονικές υπολογιστών αποθηκεύουν αριθμούς διαφορετικά. –Little Endian αρχιτεκτονικές (π.χ. Intel  FreeBSD, Linux) αποθηκεύουν το Least Significant Byte (LSB) πρώτα, δηλαδή στη χαμηλότερη διεύθυνση. –Big Endian αρχιτεκτονικές (π.χ. Sun SPARC  Solaris) αποθηκεύουν το Most Significant Byte (MSB) πρώτα, δηλαδή στη χαμηλότερη διεύθυνση. –Η TCP/IP σουίτα πρωτοκόλλων χρησιμοποιεί την big-endian byte ακολουθία

38 Big-endian byte order

39 Little-endian byte order

40 Συναρτήσεις βιβλιοθήκης: htons, htonl, ntohs και ntohl Αυτό σημαίνει ότι little-endian μηχανές χρειάζεται να μετατρέψουν τις IP διευθύνσεις και αριθμούς θυρών σε big-endian μορφή (διάταξη «δικτύου»), έτσι ώστε να γίνει με επιτυχία η ζητούμενη επικοινωνία. – Oι εφαρμογές χρειάζεται να μεταφράσουν τις διευθύνσεις μεταξύ της ακολουθίας bytes σε διάταξη «μηχανής» και της ακολουθίας bytes σε διάταξη «δικτύου», για οτιδήποτε έχει σχέση με multi-byte data (π.χ., int, float/double, data structures). –Γενικά όμως, για σκοπούς μεταφερσιμότητας (portability), ανεξαρτήτως είδους αρχιτεκτονικής μηχανής, η μετατροπή ακολουθίας bytes πρέπει να γίνεται. unsigned short htons(unsigned short hostshort) –Επιστρέφει 16-bit (short) αριθμό σε διάταξη «δικτύου» unsigned long htonl(unsigned long hostlong) unsigned short ntohs(unsigned short netshort) unsigned long ntohl(unsigned long netlong) –Επιστρέφει 32-bit (long) αριθμό σε διάταξη «μηχανής» Απαιτήσεις –#include

41 Network Byte Order Functions

42 Μετατροπή ακολουθίας bytes

43 Όταν τρέξουμε το πρόγραμμα σε ένα little-endian επεξεργαστή: Όταν τρέξουμε το πρόγραμμα σε ένα big-endian επεξεργαστή: x in hex: 112a380 x by bytes: 80 a3 12 1 After htonl() x in hex: 80a31201 x by bytes: 1 12 a3 80 x in hex: 112a380 x by bytes: 1 12 a3 80 After htonl() x in hex: 112a380 x by bytes: 1 12 a3 80

44 Address transformation

45 Συναρτήσεις βιβλιοθήκης gethostbyname και gethostbyaddr struct hostent *gethostbyname(char *name) struct hostent *gethostbyaddr(char *addr, int len, int type) Επιστροφή ενός δείκτη σε δομή struct hostent για έναν υπολογιστή: –είτε δεδομένου του ονόματός του name, όπου στο πεδίο h_addr της δομής βρίσκεται η Internet διεύθυνσή του και στο πεδίο h_length το μέγεθός της, –είτε δεδομένης της διεύθυνσής του addr, του μεγέθους της len και του είδους της type (πάντα PF_INET), όπου στο πεδίο h_name της επιστρεφόμενης δομής βρίσκεται το όνομα του υπολογιστή. Απαίτηση: #include struct hostent { char *h_name; /* name of the host. */ char **h_aliases; /* pointer to alternate host name array. */ int h_addrtype; /* The type of address being returned; usually AF_INET.*/ int h_length; /* The length of the address in bytes. */ char **h_addr_list; // pointer to array of network addresses for the host. };

46 Διαχείριση υποδοχών getsockname, bzero και bcopy Κλήση συστήματος getsockname –int getsockname(int fd, struct sockaddr *address, unsigned int *addresslen) –Επιστρέφει στη δομή *address τη διεύθυνση με την οποία έχει συνδεθεί η υποδοχή που αντιστοιχεί στον περιγραφέα αρχείου fd και στο *addresslen το μέγεθος της διεύθυνσης αυτής –Είναι χρήσιμη στην περίπτωση που δεν προκαθορίζεται συγκεκριμένος αριθμός θύρας κατά τη σύνδεση μέσω της bind μιας υποδοχής με μια διεύθυνση για να βρεθεί ο αριθμός της πραγματικής θύρας που διατέθηκε από το σύστημα για τη σύνδεση (με απόδοση του 0 στο name.sin port) Συναρτήσεις βιβλιοθήκης bzero και bcopy –void bzero(char *buf, int count) Θέτει 0 σε count bytes αρχίζοντας από τη διεύθυνση buf –void bcopy(char *buf1, char *buf2, int count) Αντιγράφει count bytes αρχίζοντας από τη διεύθυνση buf1 στη διεύθυνση buf2 –Απαίτηση: #include Για μεταγλώττιση στο Solaris προγραμμάτων C με κλήσεις συστήματος, πρέπει να προστίθεται στην εντολή μεταγλώττισης και το «-lsocket -lnsl"

47 Παράδειγμα Εξυπηρετητής για αντιστροφή ενός string #include /* For sockets */ #include /* For Internet sockets */ #include /* For gethostbyaddr() */ #include /* For I/O */ #include void reverse(char *); /* Function for reversing a string */ /* Server with Internet stream sockets */ main(int argc, char *argv[]) { int port, sock, newsock, serverlen, clientlen; char buf[256]; struct sockaddr_in server, client; struct sockaddr *serverptr, *clientptr; struct hostent *rem; if (argc < 2) { /* Check if server's port number is given */ printf("Please give the port number\n"); exit(1); }

48 Παράδειγμα (Εξυπηρετητής) /* Create socket */ if ((sock = socket(PF_INET, SOCK_STREAM, 0)) < 0) {perror("socket"); exit(1); } /* Convert port number to integer */ port = atoi(argv[1]); server.sin_family = PF_INET; /* Internet domain */ server.sin_addr.s_addr = htonl(INADDR_ANY); /* My Internet address */ server.sin_port = htons(port); /* The given port */ serverptr = (struct sockaddr *) &server; serverlen = sizeof (server); /* Bind socket to address */ if (bind(sock, serverptr, serverlen) < 0) { perror("bind"); exit(1); } /* Listen for connections */ if (listen(sock, 5) < 0) { /* 5 max. requests in queue */ perror("listen"); exit(1); } printf("Listening for connections to port %d\n", port);

49 Παράδειγμα (Εξυπηρετητής) while(1) { clientptr = (struct sockaddr *) &client; clientlen = sizeof(client); /* Accept connection */ if ((newsock = accept(sock, clientptr, &clientlen)) < 0) { perror("accept"); exit(1); } /* Find client's address */ if ((rem = gethostbyaddr((char *) &client.sin_addr.s_addr, sizeof (client.sin_addr.s_addr), client.sin_family)) == NULL) { herror("gethostbyaddr"); exit(1); } printf("Accepted connection from %s\n", rem -> h_name);

50 Παράδειγμα (Εξυπηρετητής) /* Create child for serving the client */ switch (fork()) { case -1: perror("fork"); exit(1); case 0: /* Child process */ do { bzero(buf, sizeof buf); /* Initialize buffer */ if (read(newsock, buf, sizeof buf) < 0) { /* Get message */ perror("read"); exit(1); } printf("Read string: %s\n", buf); reverse(buf); /* Reverse message */ if (write(newsock, buf, sizeof buf) < 0){/* Send message */ perror("write"); exit(1); } } while (strcmp(buf, "dne") != 0); /*Finish on "end" message*/ close(newsock); /* Close socket */ exit(0); } /* end of switch */ } /* end of while(1) */ } /* end of main() */

51 Παράδειγμα (Εξυπηρετητής) /* Function for reversing a string */ void reverse(char *s) { int c, i, j; for (i = 0, j = strlen(s) - 1 ; i < j ; i++, j--) { c = s[i]; s[i] = s[j]; s[j] = c; }

52 Παράδειγμα (Πελάτης) #include /* For sockets */ #include /* For Internet sockets */ #include /* For gethostbyname() */ #include /* For I/O */ #include /* Client with Internet stream sockets */ main(int argc, char *argv[]) { int port, sock, serverlen; char buf[256]; struct sockaddr_in server; struct sockaddr *serverptr; struct hostent *rem; /* Are server's host name and port number given? */ if (argc < 3) { printf("Please give host name and port number\n"); exit(1); }

53 Παράδειγμα (Πελάτης) /* Create socket */ if ((sock = socket(PF_INET, SOCK_STREAM, 0)) < 0) { perror("socket"); exit(1); } /* Find server address */ if ((rem = gethostbyname(argv[1])) == NULL) { herror("gethostbyname"); exit(1); } port = atoi(argv[2]); /* Convert port number to integer */ server.sin_family = PF_INET; /* Internet domain */ bcopy((char *) rem -> h_addr, (char *) &server.sin_addr, rem -> h_length); server.sin_port = htons(port); /*Server's Internet address and port*/ serverptr = (struct sockaddr *) &server; serverlen = sizeof(server); if (connect(sock, serverptr, serverlen) < 0) { /* Request connection */ perror("connect"); exit(1); } printf("Requested connection to host %s port %d\n", argv[1], port);

54 Παράδειγμα (Πελάτης) do { bzero(buf, sizeof buf); /* Initialize buffer */ printf("Give input string: "); fgets(buf, sizeof buf, stdin); /* Read message from stdin */ buf[strlen(buf)-1] = '\0'; /* Remove newline character */ if (write(sock, buf, sizeof buf) < 0) { /* Send message */ perror("write"); exit(1); } bzero(buf, sizeof buf); /* Initialize buffer */ if (read(sock, buf, sizeof buf) < 0) { /* Receive message */ perror("read"); exit(1); } printf("Read string: %s\n", buf); } while (strcmp(buf, "dne") != 0); /* Finish on "end" message */ close(sock); /* Close socket */ exit(0); }

55 Παράδειγμα (Εκτέλεση) bash-3.1$ gcc int_str_server.c -o int_str_server bash-2.05b$./int_str_server 30000 Listening for connections to port 30000 Accepted connection from cs4122.in.cs.ucy.ac.cy Read string: Test no 1 Read string: test no 2 Read string: test no 3 Read string: end ^C bash-3.1$ Terminal 1 Terminal 2 bash-3.1$ gcc int_str_client.c -o int_str_client bash-3.1$./int_str_client localhost 30000 Requested connection to host localhost port 30000 Give input string: Test no 1 Read string: 1 on tseT Give input string: test no 2 Read string: 2 on tset Give input string: test no 3 Read string: 3 on tset Give input string: end Read string: dne bash-3.1$ cs4122.in.cs.ucy.ac.cy

56 Παράδειγμα (Εκτέλεση) bash-2.05b$./int_str_server 30000 Listening for connections to port 30000 Accepted connection from cs4122.in.cs.ucy.ac.cy Read string: Test no 1 Read string: Test no 2 Read string: Test no 3 Read string: end Accepted connection from cs4042.in.cs.ucy.ac.cy Read string: message 1 Read string: message 2 Read string: end ^C bash-2.05b$ astarti.cs.ucy.ac.cy cs4122.in.cs.ucy.ac.cy bash-3.1$./int_str_client astarti.cs.ucy.ac.cy 30000 Requested connection to host astarti.cs.ucy.ac.cy port 30000 Give input string: Test no 1 Read string: 1 on tseT Give input string: Test no 2 Read string: 2 on tseT Give input string: Test no 3 Read string: 3 on tseT Give input string: end Read string: dne bash-3.1$ bash-3.1$./int_str_client astarti.cs.ucy.ac.cy 30000 Requested connection to host astarti.cs.ucy.ac.cy port 30000 Give input string: message 1 Read string: 1 egassem Give input string: message 2 Read string: 2 egassem Give input string: end Read string: dne bash-3.1$ cs4042.in.cs.ucy.ac.cy


Κατέβασμα ppt "University of Cyprus Department of Computer Science Presenter : Yiannos Mylonas EPL475: Advanced Networks TCP/IP Socket Programming in C."

Παρόμοιες παρουσιάσεις


Διαφημίσεις Google