Επικοινωνία Διεργασιών στο Internet με POSIX Sockets

Σχετικά έγγραφα
Δικτυακός Προγραμματισμός (Sockets Programming) Εργαστήριο Γ Εξάμηνο, Τμήμα Πληροφορικής Πανεπιστήμιο Θεσσαλίας

Ζητήματα Σχεδίασης Λογισμικού Πελάτη

Προγραμματισμός με BSD Sockets σε περιβάλλον Linux

Δίκτυα Επικοινωνιών ΙΙ: Network Programming UDP Sockets, Signals

Δίκτυα Επικοινωνιών ΙΙ: Network Programming TCP Sockets

Εργαστήριο Δικτύων Υπολογιστών

Υποδοχείς (Sockets) Προγραμματισμός II 1

Κ. Στάµος Μηχανικός Η/Υ και Πληροφορικής, Πανεπιστήµιο Πατρών Μηχανικός Έρευνας και Ανάπτυξης, ΕΜ6/ΕΑΙΤΥ

Προγραµµατισµός ικτύων Ε-01

Ζητήματα Σχεδίασης Λογισμικού Εξυπηρετητή

Socket Application Programming Interface

Ντίρλης Νικόλαος- ΕΤΥ 3ο ΦΡΟΝΤΙΣΤΗΡΙΟ ΠΑΡΑΣΚΕΥΗ 25 ΟΚΤΩΒΡΙΟΥ 2013 ΑΙΘΟΥΣΑ Β4

Δικτυακός προγραμματισμός

4 η ιάλεξη: Signals UDP Sockets

Εργαστήριο Λειτουργικών Συστήματων 8ο εξάμηνο, Ακαδημαϊκή περίοδος

Λειτουργικά Συστήματα

Επικοινωνία Client/Server Υποδοχές

{ int pipe(int fd[ ]) close

Εγχειρίδιο Συναρτήσεων. Socket *sopen(const int type, const int protocol, const char *host, const char *service)

ΗY335: Δίκτυα Υπολογιστών Χειμερινό Εξάμηνο Τμήμα Επιστήμης Υπολογιστών Πανεπιστήμιο Κρήτης Διδάσκουσα: Μαρία Παπαδοπούλη

ΟΙΚΟΝΟΜΙΚΟ ΠΑΝΕΠΙΣΤΗΜΙΟ ΑΘΗΝΩΝ ΤΜΗΜΑ ΠΛΗΡΟΦΟΡΙΚΗΣ

Προγραµµατισµός ικτύων Ε-01

Επίπεδο Μεταφοράς. (ανεβαίνουμε προς τα πάνω) Εργαστήριο Δικτύων Υπολογιστών Τμήμα Μηχανικών Η/Υ και Πληροφορικής

Ειδικά Θέματα Προγραμματισμού

Η Υλοποίηση της Επικοινωνίας. Κατανεµηµένα Συστήµατα

Εισαγωγή Επανάληψη. ΤΕΙ Στερεάς Ελλάδας. ΣT Εξάμηνο, Κατεύθυνση Μηχανικών Δικτύων Τ.Ε. Τμήμα Μηχανικών Πληροφορικής Τ.Ε. Διαδικτυακός Προγραμματισμός

Κεφάλαιο 7.3. Πρωτόκολλο TCP

Διαδιεργασιακή επικοινωνία (inter-process communication IPC) Προγραμματισμός II 1

Πρωτόκολλα Διαδικτύου

HY-335a Project: microtcp *, μία lightweight TCP βιβλιοθήκη

2η Προγραµµατιστική Εργασία

14. Δικτύωση με Java Δικτύωση με Java Sockets Δημιουργία της σύνδεσης Διευθυνσιοδότηση της σύνδεσης

ικτύωσησε Java Κατανεµηµένα Συστήµατα 08-1

Εργαστήριο Λειτουργικών Συστημάτων 8o εξάμηνο, Ροή Υ, ΗΜΜΥ

4.1.1 Πρωτόκολλο TCP - Δομή πακέτου

Προγραμματισμός Ι (ΗΥ120)

Δίκτυα Υπολογιστών ΙΙ (Ασκήσεις Πράξης)

Βασικά Θέματα Επικοινωνίας. Κατανεμημένα Συστήματα 1

Αποµακρυσµένη κλήση διαδικασιών

ΚΑΤΑΝΕΜΗΜΕΝΑ ΣΥΣΤΗΜΑΤΑ. Παράδοση Ασκήσεων Κεφάλαιο 2 Ασκήσεις 3,6,8,9,15,22,24,26. Γεωργόπουλος Άλκης Α.Μ.: 39 Κοντογιώργης Αναστάσιος A.M.

Επικοινωνία Client/Server Απομακρυσμένη Κλήση Διαδικασιών

ΛΕΙΤΟΥΡΓΙΚΑ ΣΥΣΤΗΜΑΤΑ II. Υφαντόπουλος Νικόλαος Υποψήφιος Διδάκτορας Contact:

Διαδικασιακός Προγραμματισμός

Βιβλιοθήκη stdio. Προγραμματισμός II 1

Εισαγωγή. E-03: Λειτουργικά Συστήµατα ΙΙ 6. Εαρινό Εξάµηνο SUN RPC. Κλήση Αποµακρυσµένων ιαδικασιών (RPC) Σύνδεση: Port Mapper.

Προγραμματισμός Η/Υ (ΤΛ2007 )

Δυναμική δέσμευση και αποδέσμευση μνήμης. Προγραμματισμός II 1

Γενικές Αρχές. Τεχνολογία ικτύων Επικοινωνιών ΙΙ

ΤΕΧΝΟΛΟΓΙΑ ΔΙΚΤΥΩΝ ΕΠΙΚΟΙΝΩΝΙΩΝ 7ο ΚΕΦΑΛΑΙΟ

Εικονική Μνήμη (Virtual Memory) Προγραμματισμός II 1

Προγραμματισμός συστημάτων UNIX/POSIX

Network Address Translation (NAT)

Διάλεξη 3η: Τύποι Μεταβλητών, Τελεστές, Είσοδος/Έξοδος

Προγραμματισμός Ι (ΗΥ120)

Ανάπτυξη και Σχεδίαση Λογισμικού

Topic 5: Sockets. *Ευχαριστίες στους Jim Kurose, Keith Ross, Τάκη Σταµατόπουλο, Αλέξη ελή, και Αντώνη ελιγιαννάκη

Δίκτυα Υψηλών Ταχυτήτων Ενότητα 7: Διευθυνσιοδότηση Internet Protocol (IP) v4

Συστήματα Παράλληλης & Κατανεμημένης Επεξεργασίας

Προγραμματισμός Ι. Είσοδος/Έξοδος. Δημήτρης Μιχαήλ. Ακ. Έτος Τμήμα Πληροφορικής και Τηλεματικής Χαροκόπειο Πανεπιστήμιο

Δομημένος Προγραμματισμός (ΤΛ1006)

Εικονική Μνήμη (Virtual Memory) Προγραμματισμός II 1

Αρχιτεκτονική υπολογιστών

Προγραμματισμός Ι. Δυναμική Διαχείριση Μνήμης. Δημήτρης Μιχαήλ. Ακ. Έτος Τμήμα Πληροφορικής και Τηλεματικής Χαροκόπειο Πανεπιστήμιο

Κατανεμημένα Συστήματα. Ενότητα # 4: Μηχανισμοί Επικοινωνίας Διδάσκων: Γεώργιος Ξυλωμένος Τμήμα: Πληροφορικής

(C) 2010 Pearson Education, Inc. All rights reserved.

Προγραμματισμός Η/Υ (ΤΛ2007 )

Δίκτυα Θεωρία

Προγραμματισμός Η/Υ (ΤΛ2007 )

Εργαστήριο Δικτύων Υπολογιστών

ιαδικτυακές Εφαρµογές

ΗΜΥ 213 Εργαστήριο Οργάνωσης Ηλεκτρονικών Υπολογιστών και Μικροεπεξεργαστών

ΗΜΥ 213 Εργαστήριο Οργάνωσης Ηλεκτρονικών Υπολογιστών και Μικροεπεξεργαστών

Δομημένος Προγραμματισμός (ΤΛ1006)

Διαδικασιακός Προγραμματισμός

Δίκτυα Υπολογιστών Firewalls. Χάρης Μανιφάβας

Τι είναι το πρωτόκολλο Διαδικτύου (Internet Protocol, IP);

Διδάσκων: Παναγιώτης Ανδρέου

Βιβλιοθήκη stdio. Προγραμματισμός II 1

Πρωτόκολλο TCP Διάλεξη Ι

Προγραμματισμός Ι. Εγγραφές. Δημήτρης Μιχαήλ. Τμήμα Πληροφορικής και Τηλεματικής Χαροκόπειο Πανεπιστήμιο

Δομημένος Προγραμματισμός (ΤΛ1006)

ΑΤΜ PROJECT ΛΕΙΤΟΥΡΓΙΚΑ ΣΥΣΤΗΜΑΤΑ Άννα Τριανταφύλλου ΑΕΜ : 456. επιβλέπων καθηγητής: Μηνάς Δασυγένης

Μετατροπή χαρακτήρων ASCII σε αριθμό (atoi) & διάβασμα, και αποθήκευση του περιεχομένου του στη μνήμη. (Διάλεξη. Πανεπιστήμιο Κύπρου

ΕΑΠ/ΠΛΗ22/ΑΘΗ.3 4 η ΟΣΣ 15/03/2014 Συμπληρωματικές Διαφάνειες

ΔΙΚΤΥΑ ΥΠΟΛΟΓΙΣΤΩΝ Γ Τάξη ΤΟΜΕΑΣ ΠΛΗΡΟΦΟΡΙΚΗΣ ΕΠΑ.Λ. ΤΕΤΡΑΔΙΟ ΜΑΘΗΤΗ Κωνσταντοπούλου Μ., Χρυσοστόμου Γ.

Πρωτόκολλα Επικοινωνίας Πρωτόκολλο IP

ΕΠΙΚΟΙΝΩΝΙΕΣ ΔΕΔΟΜΕΝΩΝ ΚΑΙ ΤΕΧΝΟΛΟΓΙΕΣ INTERNET

ΒΑΣΙΚΟΙ ΤΥΠΟΙ ΚΑΙ ΠΙΝΑΚΕΣ

Κατανεμημένα Συστήματα. Ενότητα # 11: Μηνυματοστρεφές ενδιάμεσο λογισμικό Διδάσκων: Γεώργιος Ξυλωμένος Τμήμα: Πληροφορικής

Μνήμη Διευθύνσεις Δείκτες. Προγραμματισμός II 1

Προγραμματισμός Ι. Δείκτες. Δημήτρης Μιχαήλ. Τμήμα Πληροφορικής και Τηλεματικής Χαροκόπειο Πανεπιστήμιο

Εισαγωγή εκτελέσιμου κώδικα σε διεργασίες

Σύντομη παρουσίαση των εργαλείων/εντολών telnet, ping, traceroute nslookup και nmap, zenmap

ΗΜΥ 213 Εργαστήριο Οργάνωσης Ηλεκτρονικών Υπολογιστών και Μικροεπεξεργαστών

Μετατροπή χαρακτήρων ASCII σε ακέραιο αριθµό (atoi) & Άνοιγµα αρχείου µέσα από τo QtSPIM, διάβασµα, και αποθήκευση του περιεχοµένου του στη µνήµη

Η πρώτη παράμετρος είναι ένα αλφαριθμητικό μορφοποίησης

Μάθημα 4: Πρότυπα, Πρωτόκολλα & Υπηρεσίες

υναµική έσµευση Μνήµης (συν.) ΕΠΛ 132 Αρχές Προγραµµατισµού ΙΙ 2 Εφαρµογή

Ουρές Μηνυμάτων (Message Queues in System V) Προγραμματισμός II 1

Αγωγοί/Σωλήνες (Pipes) Προγραμματισμός II 1

Transcript:

Επικοινωνία Διεργασιών στο Internet με POSIX Sockets ΣΤ Εξάμηνο, Κατεύθυνση Μηχανικών Δικτύων Τ.Ε. Τμήμα Μηχανικών Πληροφορικής Τ.Ε. ΤΕΙ Στερεάς Ελλάδας plam@inf.teilam.gr, 2016

Δήλωση Οι διαφάνειες βασίζονται στα βιβλία: (1) Δικτυακός, Douglas E. Comer, David L. Stevens, Εκδόσεις ΙΩΝ, 2005 (2) Unix Network Programming, W. Richard Stevens, Prentice-Hall, 1994 plam@inf.teilam.gr, 2016

Δήλωση (συνέχεια) Για τη δημιουργία των διαφανειών χρησιμοποιήθηκε υλικό των μαθημάτων: (1) Κατανεμημένα Συστήματα, Σπύρος Λάλης & Αλέξανδρος Καρυπίδης, ΤΜΗΥΤΔ, Πανεπιστήμιο Θεσσαλίας (2) Εργαστήριο Δικτύων Υπολογιστών, Ε. Βαρβαρίγος & Κ. Βλάχος, ΤΜΗΥΠ, Πανεπιστήμιο Πατρών plam@inf.teilam.gr, 2016

Στόχοι της ενότητας Η παρουσίαση αρχιτεκτονικών επικοινωνίας διεργασιών σε διαδίκτυο Η παρουσίαση του ΑΡΙ των υποδοχών (POSIX sockets API) για τον προγραμματισμό δικτυακών εφαρμογών Η παρουσίαση βημάτων για την ανάπτυξη πελατών και εξυπηρετητών με χρήση των πρωτοκόλλων TCP και UDP 4

Υποδοχές (Sockets) Προγραμματιστική διεπαφή η οποία: παρέχει συναρτήσεις για δημιουργία/καταστροφή υποδοχών. Η υποδοχή θεωρείται το τελικό σημείο (endpoint) της επικοινωνίας σε ένα δίκτυο παρέχει συναρτήσεις για την αίτηση σύνδεσης και την αποδοχή σύνδεσης υποδοχών Παρέχει συναρτήσεις για την αποστολή και λήψη δεδομένων μέσω των υποδοχών Επιχειρεί να αποκρύψει τις λεπτομέρειες της μεταφοράς δεδομένων μέσω του δικτύου 5

Υποδοχές 6

Υποδοχές και θύρες (ports) 7

Υποδοχές και πολύπλεξη 8

Επικοινωνία ροής / datagram Επικοινωνία ροής (SOCK_STREAM): αξιόπιστη, με «σύνδεση» (connection oriented) πρωτόκολλο μεταφοράς: TCP Επικοινωνία datagram (SOCK_DGRAM): χωρίς σύνδεση (connectionless) πρωτόκολλο μεταφοράς: UDP (μη αξιόπιστη μεταφορά) χρησιμοποιείται συνήθως σε εφαρμογές που λειτουργούν σε τοπικό δίκτυο ή απαιτούν υψηλές ταχύτητες μετάδοσης χωρίς ανάγκη απόλυτης αξιοπιστίας η όποια αξιοπιστία απαιτείται, επαφίεται στην εφαρμογή 9

TCP: Παροχή Αξιόπιστης Υπηρεσίας στις Εφαρμογές Υπηρεσία με Σύνδεση (Connection- Oriented Service) ή Επικοινωνία Ροής (Stream) plam@inf.teilam.gr, 2016

Κλήσεις συστήματος για εφαρμογή πελάτη εξυπηρετητή στο TCP 11

Σύνοψη λειτουργιών και κλήσεων συστήματος 12

Κλήσεις συστήματος για εφαρμογή πελάτη-εξυπηρετητή TCP Εξυπηρετητής: δημιουργία υποδοχής (socket()) δέσμευση σε διεύθυνση (bind()) προσδιορισμός μεγέθους ουράς (listen()) αναμονή για σύνδεση (accept()) μεταφορά δεδομένων (read(), write()) Πελάτης: δημιουργία υποδοχής (socket()) σύνδεση με τον εξυπηρετητή (connect()) μεταφορά δεδομένων (write(), read()) 13

Η αντίληψη των υποδοχών από τα προγράμματα 14

Υλοποίηση Πελάτη TCP plam@inf.teilam.gr, 2016

Πελάτης TCP Βήματα πελάτη για τη σύνδεση: δημιουργεί μια υποδοχή (ή τελικό σημείο - endpoint) Προαιρετικά: δεσμεύει την υποδοχή στην επιθυμητή τοπική δικτυακή διεύθυνση Συνήθως υπάρχει μόνο μια κάρτα δικτύου / διεύθυνση Γενικά το ΛΣ μπορεί να επιλέγει αυτόματα Υπάρχουν περιπτώσεις που απαιτείται (firewalls) ζητά από το ΛΣ να συνδέσει την υποδοχή με κάποια υποδοχή στη διεύθυνση αποδέκτη (τη διεύθυνση αποδέκτη την παρέχει ο πελάτης) 16

Δομές για Ονόματα και Διευθύνσεις IPv4 και IPv6 plam@inf.teilam.gr, 2016

Δομές για την αποθήκευση τελικού σημείου στο Internet IPv4 struct sockaddr { unsigned short sa_family; // address family char sa_data[14]; // 14 bytes of protocol address }; sa_family: AF_INET (IPv4) ή AF_INET6 (IPv6) sa_data: περιέχει τη διεύθυνση και τη θύρα προορισμού 18

Δομές για την αποθήκευση τελικού σημείου στο Internet ΙPv4 struct sockaddr_in {//struct to hold an address }; u_short sin_family; u_short sin_port; struct in_addr sin_addr; char sin_zero[8]; sin_family: sa_family // type of address // protocol port number // IPv4 address // unused (set to zero) sin_port: ο αριθμός θύρας σε network byte order (δες παρακάτω) sin_addr: η διεύθυνση ΙΡv4 του τελικού σημείου sin_zero: πρέπει να είναι 0 (με τη συνάρτηση memset()) 19

Δομές για την αποθήκευση τελικού σημείου στο Internet ΙPv4 struct in_addr { // IPv4 Internet address }; uint32_t s_addr; // Α 32-bit int (4 bytes) Το πεδίο της δομής sockaddr_in που περιέχει τη διεύθυνση ΙΡ είναι τύπου in_addr. Άρα, αν σε ένα πρόγραμμα υπάρχει η ακόλουθη δήλωση: struct sockaddr_in address; Μπορούμε να αναφερθούμε στην ΙΡv4 διεύθυνση με τον παρακάτω τρόπο: address.sin_addr.s_addr /* διεύθυνση IPv4 σε Network Byte Order */ 20

Δομές για την αποθήκευση τελικού σημείου στο Internet ΙPv6 // (IPv6 only) struct sockaddr_in6 { }; u_int16_t sin6_family; // address family, AF_INET6 u_int16_t sin6_port; Byte Order u_int32_t sin6_flowinfo; information // port number, Network 21 // IPv6 flow struct in6_addr sin6_addr; // IPv6 address u_int32_t sin6_scope_id; struct in6_addr { }; // Scope ID unsigned char s6_addr[16]; // IPv6 address

Δομές για την αποθήκευση τελικού σημείου στο Internet ΙPv6 Υπάρχουν κλήσεις για τις οποίες δεν γνωρίζουμε εκ των προτέρων αν επιστρέφουν διευθύνσεις IPv4 ή IPv6 Σε αυτές τις κλήσεις περνάμε τη δομή struct sockaddr_storage που είναι αρκετά μεγάλη ώστε να χωράει τόσο δομές IPv4 όσο και IPv6 Η δομή αυτή είναι παρόμοια με τη struct sockadrr αλλά μεγαλύτερη 22

Δομές για την αποθήκευση τελικού σημείου στο Internet ΙPv4 και 6 struct sockaddr_storage { sa_family_t ss_family; // address family /* all this is padding, implementation specific, ignore it: */ }; char ss_pad1[_ss_pad1size]; int64_t ss_align; char ss_pad2[_ss_pad2size]; Τρόπος χρήσης: ελέγχουμε το πεδίο ss_family (αν είναι AF_INET ή AF_INET6) και ανάλογα μετατρέπουμε (type cast) αυτή τη δομή σε struct sockaddr_in ή struct sockaddr_in6 23

Δομή δεδομένων για τήρηση διευθύνσεων ΙΡ IPv4 sockaddr_in length AF_INET αριθμός θύρας (16bit) διεύθυνση ΙΡ (32 bit) IPv6 sockaddr_in6 length AF_INET6 αριθμός θύρας (16bit) ετικέτα ροής (32 bit) (unused) διεύθυνση ΙΡv6 (128 bit) μέγεθος: 16 bytes 24 μέγεθος: 24 bytes

Δομή για την αποθήκευση τελικού σημείου στο Internet ΙPv6 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;// sockaddr_in or _in6 char *ai_canonname; // full canonical hostname struct addrinfo *ai_next;//linked list, next node 25

Δομή για την αποθήκευση τελικού σημείου στο Internet ΙPv6 Μπορείτε να εξαναγκάσετε να χρησιμοποιήσει IPv4 ή IPv6 στο πεδίο ai_family, ή να το αφήσετε AF_UNSPEC Ο κώδικάς σας έτσι είναι IP version-agnostic Η δομή αυτή είναι μια συνδεδεμένη λίστα: το ai_next δείχνει στο επόμενο στοιχείο (μπορεί να υπάρχουν πολλά αποτελέσματα και να χρειάζεται κανείς να διαλέξει) 26

Κλήσεις Συστήματος Υποδοχών plam@inf.teilam.gr, 2016

Δημιουργία υποδοχής int socket ( family, type, protocol ); family int type int protocol int Οικογένεια πρωτοκόλλων ή διευθύνσεων (PF_INET για TCP/IP) Τύπος υπηρεσίας (SOCK_STREAM για TCP ή SOCK_DGRAM για UDP) Αριθμός πρωτοκόλλου που θα χρησιμοποιηθεί ή 0 για χρήση του καθορισμένου πρωτοκόλλου για συγκεκριμένο family και type 28

Δημιουργία υποδοχής TCP int main(int argc, char *argv[]) { int sock, ret; sock = socket (PF_INET, SOCK_STREAM, 0); if (sock == -1) { // error check perror ("Failed to create socket"); return -1; } } PF_INET: Protocol Family Internet, SOCK_STREAM: Υποδοχή TCP. Επιστρέφει έναν ακέραιο (sock) που είναι ο περιγραφέας της υποδοχής (socket descriptor) 29

BSD Socket Πρόκειται για Δομή δεδομένων σε kernel space 30

Σύνδεση με τον εξυπηρετητή Ι int connect(int sockfd, const struct sockaddr *serv_addr, socklen_t addrlen); sockfd int serv_addr &sock_addr addrlen int Ο τοπικός περιγραφέας υποδοχής που θα συνδεθεί Η διεύθυνση τελικού σημείου του εξυπηρετητή με την οποία θα συνδεθεί ο περιγραφέας Το μέγεθος (σε bytes) της διεύθυνσης 31

Σύνδεση με τον εξυπηρετητή ΙΙ struct sockaddr_in address; address.sin_family = AF_INET; address.sin_addr.s_addr = htonl(inaddr_loopback); address.sin_port = htons(15000); ret = connect (sock, (struct sockaddr *) &address, sizeof(address)); Σύνδεση με τη διεργασία εξυπηρετητή που βρίσκεται στη διεύθυνση address 32

Δημιουργία σύνδεσης (κλήσεις συστήματος) socket() connect() (μπλοκάρει) client server socket(), bind(), listen(), accept() (μπλοκάρει) επιστρέφει η connect() αποστολή αίτησης χρόνος 33 χρόνος επιστρέφει η accept() ανάγνωση δεδομένων αποστολή απόκρισης

Κλήσεις Συστήματος για Ονόματα και Διευθύνσεις IPv4 και IPv6 plam@inf.teilam.gr, 2016

Πως βρίσκουμε τη διεύθυνση ΙΡv4 του εξυπηρετητή; struct hostent { }; char *h_name; /* Official name of host.*/ char **h_aliases; /* Alias list. */ int h_addrtype; /* Host address type. */ int h_length; /* Length of address. */ char **h_addr_list; /* List of addresses from name server. */ # define h_addr h_addr_list[0]; #include <netdb.h> struct hostent *gethostbyname(const char *hostname); 35

Η δομή hostent 36

Ανάλυση (resolve) ενός ονόματος με τη gethostbyname() I struct hostent *phe; /* pointer to host information entry (IPv4 only) */ char *host; struct sockaddr_in address; if ( phe = gethostbyname(host) ) memcpy(&address.sin_addr, phe->h_addr, phe-> h_length); else if ( (sin.sin_addr.s_addr = inet_addr(host)) == INADDR_NONE ) errexit("can't get \"%s\" host entry\n", host); 37

Ανάλυση (resolve) ενός ονόματος με τη gethostbyname() II struct hostent *hptr; struct sockaddr_in peeraddr; char *examplenam = "merlin.cs.purdue.edu"; (ή char *examplenam = argv[1];) if (hptr = gethostbyname (examplenam )) { /* IP address is now in hptr ->h_addr */ } else { /* error in name - handle it */ } peeraddr.sin_family = AF_INET; peeraddr.sin_addr.s_addr = ((struct in_addr *) (hptr->h_addr))->s_addr; 38

Πως βρίσκουμε τον αριθμό θύρας που ακούει ο εξυπηρετητής; struct servent { }; char *s_name; /*official service name */ char **s_aliases; /*other aliases */ int s_port; /*port for this service */ char *s_proto; /*protocol to use */ όπου: s_name το επίσημο όνομα της υπηρεσίας (π.χ. daytime), s_port ο αριθμός θύρας για την υπηρεσία στη διάταξη των bytes στο δίκτυο (δες παρακάτω) και s_proto το όνομα του πρωτοκόλλου που θα χρησιμοποιηθεί για αυτή την υπηρεσία 39

Αναζήτηση προκαθορισμένης θύρας #include <netdb.h> struct servent *getservbyname(const char *servname, const char *protoname); #include <netdb.h> struct servent *getservbyport(int port, const char *protoname); 40

Αναζήτηση προκαθορισμένης θύρας με τη getservbyname() I struct servent *sptr; if (sptr = getservbyname ("smtp","tcp" )) { /* port number is now in sptr ->s_port */ } else { /* error occurred - handle it */ } peeraddr.sin_port = sptr->s_port; Η χρήση συναρτήσεων όπως οι παραπάνω, οδηγεί σε μεγαλύτερη μεταφερσιμότητα, λειτουργικότητα και γενικότητα στην πλευρά του πελάτη, αφού είναι εφικτό το πέρασμα παραμέτρων. Λειτουργούν μόνο για IPv4 41

Αναζήτηση προκαθορισμένης θύρας με τη getservbyname() II struct servent *pse; /* pointer to service information entry */ char *service, *transport; struct sockaddr_in address; if ( pse = getservbyname(service, transport) ) address.sin_port = pse->s_port; else if ((sin.sin_port = htons((unsigned short)atoi(service))) == 0) errexit("can't get \"%s\" service entry\n", service); 42

Δημιουργία τελικού σημείου με την getaddrinfo() I #include <sys/types.h> #include <sys/socket.h> #include <netdb.h> int getaddrinfo( const char *node,// e.g. "www.example.com" or IP const char *service, // e.g. "http" or port number const struct addrinfo *hints, struct addrinfo **res ); 43

Δημιουργία τελικού σημείου με την getaddrinfo() IΙ Η getaddrinfo() παίρνει τρεις παραμέτρους: την παράμετρο node, που είναι το όνομα του ΥΣ ή μια διεύθυνση ΙΡ την παράμετρο service, που είναι το όνομα μιας υπηρεσίας (σύμφωνα με την ΙΑΝΑ) ή ο αριθμός θύρας της υπηρεσίας την παράμετρο hints, που «δείχνει» σε ένα struct addrinfo που έχετε ήδη γεμίσει με τις απαραίτητες πληροφορίες 44

Παράδειγμα κλήσης της 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("www.example.net", "3490", &hints, &servinfo); /* servinfo now points to a linked list of 1 or more struct addrinfos */ 45

Μετατροπή μεταξύ διαφόρων μορφών διευθύνσεων IPv4 Ι #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> char *inet_ntoa(struct in_addr in); int inet_aton(const char *cp, struct in_addr *inp); in_addr_t inet_addr(const char *cp); 46

Μετατροπή μεταξύ διαφόρων μορφών διευθύνσεων IPv4 ΙΙ Οι συναρτήσεις αυτές μετατρέπουν από struct in_addr σε δεκαδικό συμβολισμό με τελείες (inet_ntoa) και αντίστροφα (inet_aton) n = network, a = ASCII (για ιστορικούς λόγους). Οι λειτουργίες και τα ορίσματα είναι προφανή Η συνάρτηση inet_addr() είναι παλαιότερη και κάνει ότι και η inet_aton() Οι συναρτήσεις αυτές έχουν αντικατασταθεί από τις inet_pton() και inet_ntop() 47

Μετατροπή μεταξύ διαφόρων μορφών διευθύνσεων IPv6 Ι #include <arpa/inet.h> const char *inet_ntop(int af, const void *src, char *dst, socklen_t size); int inet_pton(int af, const char *src, void *dst); n = network, p = presentation ή printable Και οι δύο παίρνουν την οικογένεια διευθύνσεων στην παράμετρο af (AF_INET ή AF_INET6) Στην inet_ntop() η παράμετρος src θα πρέπει να είναι ένα δείκτης είτε σε struct in_addr ή σε struct in6_addr που θα περιέχουν τη διεύθυνση που πρέπει να μετατραπεί σε συμβολοσειρά 48

Αναπαράσταση διευθύνσεων IPv6 Στην inet_pton() η παράμετρος src είναι μια συμβολοσειρά που περιέχει τη διεύθυνση ΙΡ σε εκτυπώσιμη μορφή Η παράμετρος dst δείχνει που θα αποθηκευθεί το αποτέλεσμα, που θα είναι struct in_addr ή struct in6_addr Προφανώς και στις δύο συναρτήσεις χρειάζεται κατάλληλη μετατροπή τύπων όπου η παράμετρος είναι τύπου void * 49

Διάταξη των bytes στο Δίκτυο (Network byte Ordering) plam@inf.teilam.gr, 2016

Μορφή big-endian και little-endian Οι μορφές αυτές περιγράφουν τη διάταξη των bytes (byte order) στη μνήμη του υπολογιστή αλλά κατά τη μετάδοση πάνω από κύκλωμα Τα bytes μπορεί να αναπαρίστανται στη μνήμη με μορφή big-endian ή little-endian Στη μορφή big-endian το πιο σημαντικό byte μιας «λέξης» αποθηκεύεται σε μια θέση μνήμης και τα ακόλουθα στις επόμενες μεγαλύτερες θέσεις μνήμης 51

Μορφή big-endian και little-endian Στη μορφή little-endian αντιστρέφεται η σειρά και αποθηκεύεται το λιγότερο σημαντικό byte στη χαμηλότερη θέση μνήμης ενώ το πιο σημαντικό byte αποθηκεύεται στη μεγαλύτερη θέση μνήμης Γιατί όμως μας απασχολεί κάτι τέτοιο; 52

Little endian vs big endian Έστω η ανάθεση: int a = 1 και έστω ότι sizeof(int) = 2 bytes περισσότερο σημαντικό byte λιγότερο σημαντικό byte 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 53

Little endian vs big endian int a=1; Λιγότερο σημαντικό byte Περισσότερο σημαντικό byte little endian 0 1 2 3 4 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0... int a=1; big endian 0 1 2 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 4... 54

Μορφή big-endian και little-endian Η μεταβλητή x με τιμή 0x01234567 θα αποθηκευθεί όπως φαίνεται παρακάτω: 55

Διάταξη των bytes στο δίκτυο Υποθέστε ότι γράφετε ακεραίους σε ένα αρχείο σε ένα υπολογιστικό σύστημα (ΥΣ) little endian και στη συνέχεια μεταφέρετε αυτό το αρχείο σε ένα ΥΣ big endian Αν δεν υπάρχει μετασχηματισμός από little endian σε big endian, το ΥΣ που λειτουργεί με big endian θα διαβάσει διαφορετικούς ακεραίους από το αρχείο! 56

Διάταξη των bytes στο δίκτυο και το υπολογιστικό σύστημα Το TCP/IP αναπαριστά τους ακέραιους που χρησιμοποιούνται στις επικεφαλίδες των πρωτοκόλλων με πρώτο το πιο σημαντικό byte (network byte order) Δηλαδή, τα πεδία περιγράφονται από αριστερά προς τα δεξιά, με το πιο σημαντικό byte αριστερά, και το λιγότερο σημαντικό byte δεξιά H χρήση κατάλληλων ρουτινών μετατροπής κάνει τον κώδικα μεταφέρσιμο (ανεξάρτητα από τη διάταξη των bytes στο τοπικό ΥΣ) 57

Επεξεργαστές και αναπαράσταση Οι Intel-based επεξεργαστές είναι little endians. Οι επεξεργαστές ARM ήταν little endians Η τρέχουσα γενιά επεξεργαστών ARM είναι bi-endian Οι επεξεργαστές Motorola 68K είναι big endians. Οι επεξεργαστές PowerPC (από τη Motorola) και οι SPARK (από τη Sun) είναι big endian Οι τρέχουσες εκδόσεις αυτών των επεξεργαστών είναι bi-endians 58

Διάταξη των bytes στο δίκτυο και το υπολογιστικό σύστημα #include <netinet.h> uint16_t htons(uint16_t hostshort) Μετατροπή από τη διάταξη των bytes στο ΥΣ (h: host) στη διάταξη των bytes του δικτύου (n: network) για μικρούς ακεραίους (s: short int 16 bit). Αντίστοιχα, οι παρακάτω συναρτήσεις κάνουν μετατροπές για s και l (l: int 32 bit) uint32_t htonl(uint32_t hostlong) uint16_t ntohs(uint16_t netshort) uint32_t ntohl(uint32_t netlong) 59

Παράδειγμα κώδικα πελάτη TCP I #include<stdio.h> #include<string.h> //strlen #include<sys/socket.h> #include<arpa/inet.h> //inet_addr int main(int argc, char *argv[]) { int socket_desc; struct sockaddr_in server; 60

Παράδειγμα κώδικα πελάτη TCP II char *message, server_reply[2000]; //Create socket socket_desc = socket(af_inet, SOCK_STREAM, 0); if (socket_desc == -1) { } printf("could not create socket"); 61

Παράδειγμα κώδικα πελάτη TCP III server.sin_addr.s_addr = inet_addr("74.125.235.20"); server.sin_family = AF_INET; server.sin_port = htons( 80 ); //Connect to remote server if (connect(socket_desc, (struct sockaddr *)&server, sizeof(server)) < 0) { puts("connect error"); return 1; } 62

Παράδειγμα κώδικα πελάτη TCP IV puts("connected\n"); //Send some data message = "GET / HTTP/1.1\r\n\r\n"; if( send(socket_desc, message, strlen(message), 0) < 0) { } puts("send failed"); return 1; 63

Παράδειγμα κώδικα πελάτη TCP V puts("data Send\n"); //Receive a reply from the server if( recv(socket_desc, server_reply, 2000, 0) < 0) { } } puts("recv failed"); puts("reply received\n"); puts(server_reply); return 0; 64

Υλοποίηση Εξυπηρετητή TCP plam@inf.teilam.gr, 2016

Εξυπηρετητής TCP Βήματα εξυπηρετητή για τη σύνδεση: δημιουργεί μια υποδοχή δεσμεύει την υποδοχή στην επιθυμητή τοπική δικτυακή διεύθυνση τελικού σημείου ζητά από το ΛΣ να ακούει για συνδέσεις εισέρχεται σε κατάσταση όπου αναμένει διαρκώς (σύγχρονα ή ασύγχρονα) να του παραδώσει μια σύνδεση το ΛΣ 66

Δημιουργία υποδοχής TCP int main(int argc, char *argv[]) { int serversocket; serversocket = socket (PF_INET, SOCK_STREAM, 0); if (serversocket == -1) { // error check perror ("Failed to create socket"); return -1; } } PF_INET: Protocol Family Internet, SOCK_STREAM: Υποδοχή TCP 67

Δέσμευση της υποδοχής σε τελικό σημείο Πρέπει να ορίσουμε τη διεύθυνση στην οποία θα αναμένουμε συνδέσεις Στο TCP/IP το ουσιαστικό ζητούμενο είναι η δημιουργία τελικού σημείου επικοινωνίας (endpoint) που αποτελείται από διεύθυνση ΙΡ και αριθμό θύρας πρωτοκόλλου Οι πελάτες πρέπει να γνωρίζουν τη διεύθυνση αυτή για να μπορέσουν να συνδεθούν Το ΛΣ δεν επιτρέπει σε άλλο πρόγραμμα να δεσμεύσει τη διεύθυνση αυτή 68

Διεύθυνση αναμονής σύνδεσης struct sockaddr_in address; address.sin_family = AF_INET; address.sin_addr.s_addr = htonl (INADDR_ANY); address.sin_port = htons (15000); Δημιουργία Τελικού Σημείου Εξυπηρετητή sin_family: πρέπει να είναι αντίστοιχο του socket family sin_addr: ακέραιος 32bit. Αντιστοιχεί σε ένα μοναδικό μηχάνημα sin_port: ακέραιος 16bit. Αντιστοιχεί σε ένα μοναδικό πρόγραμμα στον εξυπηρετητή 69

Δέσμευση υποδοχής στη διεύθυνση αναμονής (bind()) int bind ( socket, localaddr, addrlen ); socket int localaddr &sockaddr addrlen int Περιγραφέας υποδοχής που δημιουργείται από τη socket() Η διεύθυνση μιας δομής που προσδιορίζει μια διεύθυνση IP και τον αριθμό θύρας πρωτοκόλλου Μέγεθος του δεύτερου ορίσματος σε bytes 70

bind() ret = bind (serversocket, (struct sockaddr *) &address, sizeof (address)); if (ret == -1) { // error check } perror ("Failed to bind socket"); return -1; Δέσμευση Υποδοχής σε Τοπική Διεύθυνση 71

Τοποθέτηση σε παθητική κατάσταση int listen( socket, queuelen ); socket int Ένας περιγραφέας υποδοχής που έχει δημιουργηθεί από την κλήση socket() queuelen int Το μέγεθος της ουράς των εισερχόμενων αιτήσεων σύνδεσης (εξ ορισμού 5) 72

listen() ret = listen (serversocket, 10); if (ret == -1) { // error check } perror ("Failed to start listening on socket"); return -1; Τοποθέτηση υποδοχής εξυπηρετητή σε παθητική κατάσταση (δηλ. κατάσταση αναμονής αιτήσεων μέσω της υποδοχής, με μέγιστο μέγεθος ουράς 10 αιτήσεις) 73

Αποδοχή αίτησης για σύνδεση: accept() I int accept( int s, struct sockaddr *addr, socklen_t *addrlen ); Η accept() δέχεται ως ορίσματα: την υποδοχή που αναμένει για αιτήσεις σύνδεσης μια δομή διεύθυνσης που συμπληρώνει με τα στοιχεία του πελάτη τη διεύθυνση ακεραίου (socklen_t) που: αρχικά έχει το μέγεθος της δομής διεύθυνσης στην επιστροφή έχει το μέγεθος που χρησιμοποιήθηκε 74

Αποδοχή αίτησης για σύνδεση: accept() II int accept(int s, struct sockaddr *addr, socklen_t *addrlen); Επιστρέφει μια νέα υποδοχή! Η αρχική συνεχίζει να χρησιμοποιείται για την αναμονή αιτήσεων και τη δημιουργία συνδέσεων Η νέα χρησιμοποιείται για την ανταλλαγή δεδομένων για τη συγκεκριμένη σύνδεση 75

Ενημέρωση για τη διεύθυνση του αποστολέα struct sockaddr_in remoteaddress; int addresslength, clientsocket; addresslength = sizeof (remoteaddress); clientsocket = accept (serversocket, (struct sockaddr *) &remoteaddress, &addresslength); if (clientsocket == -1) { // error check perror ("Error while accepting connection"); return -1; } printf ("Connection has been established\n"); Παραδίδεται η πρώτη αίτηση σύνδεσης από την ουρά. Η δομή remoteaddress και η addresslength περιέχουν τη διεύθυνση τελικού σημείου του πελάτη 76

Αποδοχή αίτησης για σύνδεση: accept() ΙII Από την στιγμή που η accept() επιστρέφει τη νέα υποδοχή, η σύνδεση µε τον πελάτη έχει εγκατασταθεί Μέχρι να ξανακληθεί η accept(), o εξυπηρετητής δεν ικανοποιεί αιτήσεις Οι αιτήσεις που φτάνουν όσο ο εξυπηρετητής δεν βρίσκεται στην accept() τοποθετούνται σε μια ουρά (εξορισμού μεγέθους 5 μπορεί να αλλάξει µε την listen()) 77

Αποδοχή αίτησης για σύνδεση: accept() ΙV Ένας τρόπος επεξεργασίας της αίτησης είναι η δημιουργία διεργασιών ή νημάτων, που είναι παιδιά της αρχικής διεργασίας του εξυπηρετητή Με τον τρόπο αυτό ο πελάτης επικοινωνεί µε έναν «αφοσιωµένο» σε αυτόν τμήμα του εξυπηρετητή Ο «αρχικός» εξυπηρετητής επιστρέφει για να συνεχίσει να αναμένει για νέες αιτήσεις σύνδεσης (επιστροφή στην accept()) 78

Δημιουργία σύνδεσης (κλήσεις συστήματος) socket() connect() (μπλοκάρει) client server socket(), bind(), listen(), accept() (μπλοκάρει) επιστρέφει η connect() αποστολή αίτησης χρόνος 79 χρόνος επιστρέφει η accept() ανάγνωση αίτησης αποστολή απόκρισης

Αποστολή και Λήψη Δεδομένων σε Υποδοχές TCP plam@inf.teilam.gr, 2016

Αποστολή και λήψη δεδομένων σε υποδοχές TCP Γίνεται όπως η ανάγνωση/εγγραφή σε αρχεία με χρήση των συναρτήσεων Ε/Ε: read()/write() Επίσης, μπορούν να χρησιμοποιηθούν οι συναρτήσεις: send()/recv() Η λειτουργικότητα είναι αντίστοιχη 81

Ενδιάμεση αποθήκευση (TCP Buffers) Το ΛΣ παρέχει μια περιοχή ενδιάμεσης αποθήκευσης (TCP buffer) Τα πακέτα, με την άφιξή τους τοποθετούνται στον TCP buffer Η read() παραδίδει τα δεδομένα στη διεργασία Ανάλογη λειτουργικότητα με την listen() και την ουρά εισερχόμενων συνδέσεων 82

send() / recv() count = send(sock, buf, buflen, flags) int count, sock, buflen, flags; char *buf; count = recv(sock, buf, buflen, flags) int count, sock, buflen, flags; char *buf; 83

Αξιόπιστη υπηρεσία Η send() μπλοκάρει αν ο παραλήπτης δεν μπορεί να λάβει τα δεδομένα με το ρυθμό που στέλνονται (έλεγχος ροής) Ο buffer του ΛΣ χρησιμοποιείται για την παράδοση των δεδομένων στην εφαρμογή με τη σειρά που εστάλησαν Ο buffer έχει κάθε φορά συγκεκριμένο παράθυρο λήψης (έλεγχος ροής) 84

Ανάγνωση από σύνδεση TCP Το TCP κατά την παραλαβή δε διατηρεί την ομαδοποίηση με την οποία εστάλησαν τα δεδομένα (πρωτόκολλο ροής χαρακτήρων) Κάθε πρόγραμμα που διαβάζει δεδομένα από μια σύνδεση TCP πρέπει να είναι έτοιμο να δεχθεί τα δεδομένα σε διαφορετικά τμήματα από αυτά που εστάλησαν Γενικά, το πλήθος των αναγνώσεων μπορεί να μην είναι ίσο με το πλήθος των εγγραφών 85

Κώδικας ανταλλαγής δεδομένων σε σύνδεση TCP I /* Example code segment */ #define BLEN 120 /*Buffer length to use*/ char *req = "request of some sort"; char buf [BLEN] ; /*Buffer for answer*/ char *bptr; /* Pointer to Buffer*/ int n; /*Number of bytes read*/ int buflen; /*space left in buffer*/ bptr = buf; buflen= BLEN; 86

Κώδικας ανταλλαγής δεδομένων σε σύνδεση TCP II /*Send request*/ send(s, req, strlen(req), 0); /*Read response (may come in many pieces)*/ while ((n=recv(s, bptr, buflen, 0)>0) { bptr += n; buflen-=n; } 87

Ανάγνωση με διακοπές Η ανάγνωση μπορεί να γίνεται με διακοπές: λόγω άφιξης σήματος επειδή η υποδοχή ορίστηκε O_NONBLOCK η μεταβλητή errno σε αυτή την περίπτωση λαμβάνει τιμή EINTR ή EAGAIN αντίστοιχα Ο κώδικας θα πρέπει να είναι γραμμένος έτσι ώστε να διαχωρίζει αυτές τις περιπτώσεις από περιπτώσεις λαθών 88

Τερματισμός σύνδεσης Όταν τα προγράμματα τελειώσουν την ανταλλαγή δεδομένων, πρέπει να τερματίζουν τη σύνδεση (απελευθέρωση περιγραφέα, δομών δεδομένων για την υποδοχή, buffer ΛΣ) Το ΛΣ: ενημερώνει με ειδικά πακέτα (FIN) το άλλο άκρο ώστε να γνωρίζει ότι πλέον η σύνδεση είναι άκυρη απελευθερώνει τους πόρους που υποστηρίζουν τη λειτουργία της σύνδεσης 89

close() int close(int sock); Ίδια ακριβώς χρήση και στα δυο άκρα Δεδομένα που έχει στείλει το άλλο πρόγραμμα πριν κλείσει τη σύνδεση, παραδίδονται από την ενδιάμεση αποθήκευση του ΛΣ Μετά από μια κλήση στην close() ο περιγραφέας υποδοχής αχρηστεύεται 90

Μερικός τερματισμός shutdown() int shutdown ( sock, direction ); Ο πελάτης δηλώνει ότι δε θα μεταφέρει δεδομένα (προς κάποια κατεύθυνση) και δεν αποδεσμεύει την υποδοχή Η εφαρμογή εξυπηρετητή λαμβάνει ένα σήμα end-of-file Ο εξυπηρετητής θα κλείσει τη σύνδεση μετά την τελευταία απόκριση Ιδιαίτερα χρήσιμο για πρωτόκολλα που ανταλλάσσουν αυθαίρετα μεγάλες ποσότητες δεδομένων 91

Επικοινωνία διεργασιών με χρήση UDP Υπηρεσία Χωρίς Σύνδεση (Connectionless Service) ή Επικοινωνία Δεδομενογραφημάτων (Datagram) plam@inf.teilam.gr, 2016

Αλληλεπίδραση πελάτη εξυπηρετητή στο UDP 93

Σύνοψη λειτουργιών και κλήσεων συστήματος 94

Κλήσεις συστήματος για επικοινωνία υποδοχών UDP Εξυπηρετητής: δημιουργία τελικού σημείου (socket()) δέσμευση διεύθυνσης (bind(), όπως στο TCP) ανταλλαγή δεδομένων (sendto(), recvfrom()) Πελάτης: δημιουργία τελικού σημείου (socket()) ανταλλαγή δεδομένων (sendto(), recvfrom()) 95

Χαρακτηριστικά του UDP Χωρίς σύνδεση (datagram-based) πιθανή άφιξη των πακέτων με διαφορετική σειρά η παράδοση των δεδομένων στον παραλήπτη δεν είναι εγγυημένη Χωρίς έλεγχο ροής Αποθήκευση ολόκληρων πακέτων (δεν είναι εφικτή η ανάγνωση μέρους του πακέτου) Μέγιστο μέγεθος πακέτου τα 64ΚΒ (επικεφαλίδα + φορτίο (payload)) 96

Επικοινωνία χωρίς σύνδεση Μέσα από την ίδια υποδοχή UDP ένα πρόγραμμα μπορεί: να στείλει πακέτα σε οποιοδήποτε άλλο πρόγραμμα στο Internet να λάβει πακέτα από οποιοδήποτε άλλο πρόγραμμα στο Internet Συγκρίνετε με το TCP όπου: οι υποδοχές συνδέονται σε ζεύγη ανταλλαγή δεδομένων υπάρχει μόνο μεταξύ συνδεδεμένων ζευγών 97

Χώρος θυρών TCP και UDP Η επικεφαλίδα του ΙΡ περιέχει το πρωτόκολλο επιπέδου μεταφοράς για το οποίο προορίζεται ένα πακέτο Οι χώροι διευθύνσεων τελικού σημείου (θύρες) UDP και TCP είναι διαφορετικοί (μια υποδοχή TCP με αριθμό θύρας Χ μπορεί να συνυπάρχει στο ίδιο σύστημα με μια υποδοχή UDP με αριθμό θύρας Χ) Τα πακέτα TCP με αριθμό θύρας Χ θα παραδοθούν σε διαφορετική διεργασία από τα πακέτα UDP με αριθμό θύρας X 98

Δημιουργία πακέτων Σχηματισμός πακέτων: Στο TCP γίνεται από το ΛΣ διαδοχικές send() μπορεί να ενωθούν στο ίδιο πακέτο μεγάλες send() μπορεί να σπάσουν σε > 1 πακέτα Στο UDP ελέγχεται από τον προγραμματιστή κάθε sendto() μπαίνει σε ένα πακέτο κλήση στη sendto() με δεδομένα > 64K επιστρέφει λάθος 99

Ανάγνωση δεδομένων Ι Ο τρόπος δημιουργίας πακέτων επηρεάζει τον τρόπο ανάγνωσης δεδομένων: Στο TCP: η recv() λειτουργεί πάνω σε μια ροή (stream) εισερχόμενων bytes της ενδιάμεσης αποθήκευσης του ΛΣ, που δεν έχει καμιά σχέση με τη δημιουργία πακέτων 100

Ανάγνωση δεδομένων ΙΙ Στο UDP: κάθε recvfrom() παραλαμβάνει ακριβώς ένα πακέτο αν στην recvfrom() δεν υπάρχει αρκετός χώρος στο σημείο όπου τοποθετούνται τα εισερχόμενα δεδομένα, τα bytes του πακέτου αποκόπτονται 101

Δημιουργία υποδοχής UDP int main(int argc, char *argv[]) { int sock; sock = socket (PF_INET, SOCK_DGRAM, 0); if (sock == -1) { // error check perror ("Failed to create socket"); return -1; } } PF_INET: Protocol Family Internet, SOCK_DGRAM: Υποδοχή UDP. Επιστρέφει έναν ακέραιο (sock) που είναι ο περιγραφέας της υποδοχής (socket descriptor) 102

Αποστολή και λήψη δεδομένων int sendto(sock, buf, buflen, flags, to, tolen) int sock, buflen, flags, tolen; char *buf; struct sockaddr *to; int recvfrom(sock, buf, buflen, flags, from, fromlen) int sock, buflen, flags, *fromlen; char *buf; struct sockaddr *from; 103

sendto() sock int Ένας περιγραφέας υποδοχής buff &char Ένας δείκτης στο μήνυμα buflen int flags int Bits ελέγχου to Το μέγεθος του μηνύματος σε bytes &sockaddr Δείκτης στη δομή της διεύθυνσης tolen int Το μέγεθος της διεύθυνσης 104

recvfrom() sock int Ένας περιγραφέας υποδοχής buff &char Η προσωρινή μνήμη που θα μπει το μήνυμα buflen int Μέγεθος της προσωρινής μνήμης flags int Bits ελέγχου from &sockaddr Θα τοποθετηθεί η διεύθυνση του αποστολέα fromlen &int Επιστρέφει το μέγεθος του from 105

Παράδειγμα UDP time server struct sock_addr_in fsin; unsigned int alen; time_t now; while (1) { } alen = sizeof(fsin); if (recvfrom(sock, buf, sizeof(buf), 0, (struct sockaddr *)&fsin, &alen) < 0) errexit("recvfrom: %s\n", strerror(errno)); time(&now); now = htonl((unsigned long)(now + UNIXEPOCH)); sendto(sock, (char *)&now, sizeof(now), 0, (struct sockaddr *)&fsin, sizeof(fsin)); 106

connect() Εφόσον αποστέλλουμε συνεχώς σε συγκεκριμένο παραλήπτη μπορούμε να χρησιμοποιήσουμε την connect() Η connect() στο UDP δε δημιουργεί σύνδεση Για δική μας ευκολία, η υποδοχή έχει έναν προκαθορισμένο αποδέκτη (μπορεί πλέον να χρησιμοποιείται η send()) Μπορεί κανείς να στείλει και σε άλλους αποδέκτες καλώντας την sendto() αντί για την send() 107

Παράδειγμα int main(int argc, char *argv[]) { int sock, ret; struct sockaddr_in recvadr; recvadr.sin_family = AF_INET; inet_aton ( 197.2.1.14, &recvadr.sin_addr); recvadr.sin_port = htons (15000); connect (sock, &recvadr, sizeof (recvadr)); send (sock, data, DATASIZE, 0); send (sock, moredata, DATASIZE, 0); } Αφού χρησιμοποιηθεί η connect() δεν απαιτείται ο προσδιορισμός παραλήπτη στη send() 108

Προχωρημένα Θέματα Επικοινωνίας Διεργασιών plam@inf.teilam.gr, 2016

Σήματα (Signals) Signal id default SIGKILL 9 Terminate SIGALRM 14 Terminate SIGSYS 12 Core SIGCHLD 20 Ignore 110

Σήματα Μπορούμε να καθορίσουμε επακριβώς την συμπεριφορά μίας διεργασίας, ύστερα από την λήψη ενός σήματος εκτέλεση μίας συνάρτησης (signal handler) καμία ενέργεια (SIG_IGN) προκαθορισμένη συμπεριφορά (SIG_DFL) Τα σήματα SIGKILL και SIGSTOP δεν μπορούν ούτε να αγνοηθούν ούτε να «πιαστούν» από μία συνάρτηση (signal handler) 111

Χειρισμός κλήσεων συστήματος που διακόπτονται Όταν μια κλήση συστήματος που μπλοκάρει (π.χ. accept()) διακοπεί από ένα σήμα, μετά την επιστροφή από το χειριστή σήματος η κλήση συστήματος θέτει τη μεταβλητή errno ίση με EINTR Ο πυρήνας δεν είναι βέβαιο ότι θα επανεκιννήσει την κλήση συστήματος Θα πρέπει ο προγραμματιστής να φροντίζει για την επανεκκίνηση της κλήσης συστήματος 112

Χειρισμός κλήσεων συστήματος που διακόπτονται for ( ; ; ) { clilen = sizeof(cliaddr); if ((connfd = accept(listenfd, (sockaddr *)&cliaddr, &clilen)) < 0) { } if (errno == EINTR) continue; else perror( accept error ); 113

Βιβλιογραφία BSD Sockets: http://cis-linux1.temple.edu/~giorgio/old/ cis307s96/readings/docs/sockets.html Socket Guide by GNU: http://www.gnu.org/software/libc/ manual/html_node/sockets.html#sockets Beej's Guide to Network Programming Using Internet Sockets: http://beej.us/guide/bgnet/output/html/ multipage/index.html οδηγός για το TCP/IP: http://www.tcpipguide.com/free/t_toc.htm 114