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

Σχετικά έγγραφα
2η Προγραµµατιστική Εργασία

Βιβλιοθήκες Αφηρημένοι τύποι δεδομένων. Προγραμματισμός II 1

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

#include <stdlib.h> Α. [-128,127] Β. [-127,128] Γ. [-128,128]

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

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

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

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

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

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

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

είκτες και Πίνακες (2)

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

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

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

Πληροφορική & Τηλεπικοινωνίες. K18 - Υλοποίηση Συστημάτων Βάσεων Δεδομένων Εαρινό Εξάμηνο

(programming interfaceή/και application programming interface API).

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

Μεταγλώττιση και σύνδεση πολλαπλών αρχείων κώδικα. Προγραμματισμός II 1

Πληροφορική & Τηλεπικοινωνίες K18 - Υλοποίηση Συστηµάτων Βάσεων εδοµένων Εαρινό Εξάµηνο

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

Επεξεργασία Αρχείων Κειµένου

Προεπεξεργαστής C. Προγραμματισμός Ι 1

Δομημένος Προγραμματισμός

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

double sum(double a, double b) { return(a+b); } double my_avg(double a, double b) { return(sum(a, b)/2.0); }

ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΣ Η/Υ Ακαδημαϊκό έτος ΤΕΤΡΑΔΙΟ ΕΡΓΑΣΤΗΡΙΟΥ #4

Διάλεξη 20: Χαμηλού Επιπέδου Προγραμματισμός II

lab13grades 449 PASS 451 PASS PASS FAIL 1900 FAIL Page 1

ΕΡΓΑΣΤΗΡΙΟ 9: Συμβολοσειρές και Ορίσματα Γραμμής Εντολής

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

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

Θέτοντας και επιστρέφοντας την τιµή της προτεραιότητας διεργασίας

Πληροφορική & Τηλεπικοινωνίες. K18 - Υλοποίηση Συστημάτων Βάσεων Δεδομένων Χειμερινό Εξάμηνο

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

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

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

int array[10]; double arr[5]; char pin[20]; Προγραµµατισµός Ι

B. Ενσωμάτωση Ιθαγενών Μεθόδων

Κεφάλαιο Αλφαριθµητικές Σειρές Χαρακτήρων (Strings)

ΤΕΧΝΟΛΟΓΙΑ ΙΚΤΥΩΝ ΕΠΙΚΟΙΝΩΝΙΩΝ

Α. unsigned int Β. double. Γ. int. unsigned char x = 1; x = x + x ; x = x * x ; x = x ^ x ; printf("%u\n", x); Β. unsigned char

Α Β Γ static; printf("%c\n", putchar( A +1)+2); B DB BD. int i = 0; while (++i); printf("*");

Λύβας Χρήστος Αρχική επιµέλεια Πιτροπάκης Νικόλαος και Υφαντόπουλος Νικόλαος

ΕΙΣΑΓΩΓΗ ΣΤΟΝ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟ Ενδεικτικές Απαντήσεις Εξετάσεων Α' Περιόδου Θέµα 1. (α') 2 - ii 3 - iii 4 - iv

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

Αλγόριθμοι Ταξινόμησης Μέρος 1

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

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

Π. Σταθοπούλου ή Οµάδα Α (Φοιτητές µε µονό αριθµό Μητρώου ) ιδασκαλία : Παρασκευή 11πµ-13µµ ΗΛ7

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

Πληροφορική & Τηλεπικοινωνίες. K18 - Υλοποίηση Συστημάτων Βάσεων Δεδομένων Εαρινό Εξάμηνο

Κατανεµηµένασυστήµατα αρχείων

Δομημένος Προγραμματισμός. Τμήμα Επιχειρηματικού Σχεδιασμού και Πληροφοριακών Συστημάτων

CloudBox!: Ένα εργαλείο cloud αποθήκευσης αρχείων με κατανεμημένο τρόπο

ΑΣΚΗΣΗ 2: ΔΟΜΗ ΠΡΟΓΡΑΜΜΑΤΟΣ C, ΧΕΙΡΙΣΜΟΣ ΜΕΤΑΒΛΗΤΩΝ ΚΑΙ ΣΥΝΑΡΤΗΣΕΙΣ ΕΙΣΟΔΟΥ ΚΑΙ ΕΞΟΔΟΥ

Εργαστήριο Λειτουργικών Συστημάτων. Minix Overview

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

ΑΡ Χ Ε Ι Α Κ Ε Ι Μ Ε Ν Ο Υ (text files)

'Ασκηση 1: Στατικός Κατακερματισμός. Εισαγωγή. Ρουτίνες υλοποίησης κατακερματισμού. (Ημερομηνία Παράδοσης: Παρασκευή, 16/5/2008, 5μμ) HT_Init()


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

Πίνακες: μια σύντομη εισαγωγή. Πίνακες χαρακτήρων: τα "Αλφαριθμητικά"

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

Δομή Προγράμματος C++, Χειρισμός Μεταβλητών και Συναρτήσεις Εισόδου - Εξόδου

Πληροφορική & Τηλεπικοινωνίες K25 Ανάπτυξη Λογισμικού Εαρινό Εξάμηνο 2008 Καθηγητής Γιάννης Ιωαννίδης. Μέρος 2ο: Επίπεδο Ευρετηρίου Β+ Δένδρων

Προγραμματισμός Η/Υ 1 (Εργαστήριο)

Πρότυπο Αναφοράς Open Systems Interconnection (OSI) Επικοινωνίες Δεδομένων Μάθημα 5 ο

ιαφάνειες παρουσίασης #6 (β)

ΠΑΝΕΠΙΣΤΗΜΙΟ ΠΕΙΡΑΙΩΣ ΣΧΟΛΗ ΤΕΧΝΟΛΟΓΙΩΝ ΠΛΗΡΟΦΟΡΙΚΗΣ ΚΑΙ ΕΠΙΚΟΙΝΩΝΙΩΝ ΤΜΗΜΑ ΨΗΦΙΑΚΩΝ ΣΥΣΤΗΜΑΤΩΝ «ΔΟΜΕΣ ΔΕΔΟΜΕΝΩΝ»

Κεφάλαιο , 3.2: Συναρτήσεις II. ( ιάλεξη 12) ιδάσκων: ηµήτρης Ζεϊναλιπούρ

Πληροφορική & Τηλεπικοινωνίες K18 - Υλοποίηση Συστημάτων Βάσεων Δεδομένων Εαρινό Εξάμηνο

ΠΛΗ111. Ανοιξη Μάθηµα 3 ο. Συνδεδεµένες Λίστες. Τµήµα Ηλεκτρονικών Μηχανικών και Μηχανικών Υπολογιστών Πολυτεχνείο Κρήτης

7.2 Τεχνολογία TCP/IP

ΕΡΓΑΣΤΗΡΙΟ 9: Συμβολοσειρές και Ορίσματα Γραμμής Εντολής

Πληροφορική & Τηλεπικοινωνίες Υλοποίηση Συστημάτων Βάσεων Δεδομένων - Χειμερινό Εξάμηνο Καθηγητής Δ. Γουνόπουλος

(Κεφάλαιο 2.7 και 12) Αρχεία στην C. ( ιάλεξη 13) ιδάσκων: ηµήτρης Ζεϊναλιπούρ

Πανεπιστήμιο Θεσσαλίας Τμήμα Πληροφορικής

Ινστιτούτο Επαγγελµατική Κατάρτιση Κορυδαλλού "ΤΕΧΝΙΚΟΣ ΣΥΣΤΗΜΑΤΩΝ ΥΠΟΛΟΓΙΣΤΩΝ" (Ερωτήσεις Πιστοποίησης στην γλώσσα προγραµµατισµού C)

Κεφάλαιο 8.7. Πολυδιάστατοι Πίνακες ( ιάλεξη 18) ιδάσκων: ηµήτρης Ζεϊναλιπούρ

int a[5]; a[0] a[1] a[2] a[3] a[4] 15/10/2009

ΑΡΧΕΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΥ

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

Πληροφορική & Τηλεπικοινωνίες Υλοποίηση Συστημάτων Βάσεων Δεδομένων - Χειμερινό Εξάμηνο Καθηγητής Δ. Γουνόπουλος

(Κεφάλαιο 2.7 και 12) Αρχεία στην C. (Διάλεξη 15)

Η γλώσσα προγραμματισμού C

Ενώσεις δεδομένων Απαριθμητές Ψηφιακοί τελεστές Αναδρομικές συναρτήσεις

Προγραμματισμός Υπολογιστών με C++

ιεργασίες και νήµατα Προγραµµατισµός ΙΙΙ 1 lalis@inf.uth.gr

ΕΡΓΑΣΤΗΡΙΟ 1 ΕΙΣΑΓΩΓΗ ΣΤΗ C. Τµήµα Πληροφορικής και Τηλεπικοινωνιών

Εργαστήριο ΔΙΕΡΓΑΣΙΕΣ - ΔΙΑΧΕΙΡΙΣΗ

Π. Σταθοπούλου ή Οµάδα Α (Φοιτητές µε µονό αριθµό Μητρώου ) ιδασκαλία : Παρασκευή 11πµ-13µµ ΗΛ7

Εργαστήριο 2: Πίνακες

Δημιουργία & Τερματισμός Διεργασιών. Προγραμματισμός II 1

Διάλεξη 9: Δυναμική Δέσμευση Μνήμης

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

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

CE121 Προγραµµατισµός 2. Εισαγωγή σε Makefiles. CE121 -

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

ΣΕΤ ΑΣΚΗΣΕΩΝ 2. Προθεσµία: 15/11/09, 23:59

Transcript:

Προγραµµατισµός ικτύων (Ε-01) 1η Προγραµµατιστική Εργασία ηµιουργία ϐασικής ϐιβλιοθήκης δικτυακού προγραµµατισµού και χρήση της για την υλοποίηση απλού πελάτη και εξυπηρετητή ανταλλαγής αρχείων ιδάσκων : Νίκος Ντάρµος Σχολή Πληροφορικής, Πανεπιστήµιο Ιωαννίνων Ιωάννινα, Νοέµβριος 2010

1 Γενικά Η εργασία αυτή έχει ως στόχο την εισαγωγή των ϕοιτητών σε έννοιες δικτυακού προγραµ- µατισµού και στην προγραµµατιστική διεπαφή των BSD sockets. Στην εργασία αυτή καλείσθε να υλοποιήσετε : 1. Μία ϐασική προγραµµατιστική διεπαφή (API) συναρτήσεων δικτυακού προγραµµατισµού. 2. Εναν ϐασικό εξυπηρετητή αποστολής/λήψης αρχείων. 3. Ενα Ϲεύγος ϐασικών πελατών αποστολής/λήψης αρχείων. Βαρύτητα επίσης δίνεται στη µεταφερσιµότητα του κώδικα και στη δυνατότητα λειτουργίας του σε διαφορετικά περιβάλλοντα (αρχιτεκτονικές, λειτουργικά συστήµατα, κτλ.) και µε διαφορετικά πρωτόκολλα (TCP, UDP). 1.1 Παράδοση Ως καταληκτική ηµεροµηνία παράδοσης της εργασίας σας ορίζεται η Κυριακή, 5 εκεµβρίου 2010 (23:59:59), ενώ η παράδοση ϑα είναι µέσω e-mail στο ntarmos@cs.uoi.gr. Οπως συζητήθηκε και στο πρώτο µάθηµα 1, ϑα πρέπει να παραδώσετε : 1. Τα αρχεία πηγαίου κώδικα. 2. Ενα απλό Makefile. 3. Αναφορά/σχολιασµό (σε µορφή txt/ps/pdf). Για οποιαδήποτε απορία ή πρόβληµα µπορείτε να επικοινωνείτε µαζί µου στο παραπάνω e-mail ή στο τηλέφωνο 2651008866 ή κατ ιδίαν τις ώρες γραφείου που έχουµε συζητήσει στο µάθηµα. Υπάρχει ακόµα και η δυνατότητα επικοινωνίας µέσω προγραµµάτων IM ϱωτήστε µε για λεπτοµέρειες. 2 Βασική ϐιβλιοθήκη Η ϐασική σας ϐιβλιοθήκη ϑα αποτελείται από συναρτήσεις οι οποίες ϑα «κρύβουν» τις λεπτο- µέρειες υλοποίησης και τις κλήσεις συστήµατος και ϑα προσφέρει στον χρήστη της µία ενιαία πλατφόρµα ανάπτυξης εφαρµογών. Το API που ϑα υλοποιεί η ϐιβλιοθήκη σας αποτελείται από δοµές δεδοµένων και συναρτήσεις και περιγράφεται παρακάτω. Για τον τρόπο µε τον οποίο µπο- ϱείτε να δηµιουργήσετε µια ϐιβλιοθήκη λογισµικού σε σύστηµα UNIX την οποία να µπορείτε να συνδέετε (link) µε τον κωδικά σας κατά την µετάφρασή του, δείτε το παράρτηµα Α. Το API ορίζει συναρτήσεις για δηµιουργία, σύνδεση και καταστροφή άκρων επικοινωνίας, για αποδοχή αιτήσεων σύνδεσης, καθώς και για ανταλλαγή δεδοµένων. Επίσης, για την απο- ϑήκευση και διαχείριση των πληροφοριών των sockets, το API χρησιµοποιεί µία δική του δοµή δεδοµένων. Στο σχήµα 1 ϕαίνεται συνολικά το header file το οποίο ορίζει το API αυτό. Τα ορίσµατα και η λειτουργικότητα των συναρτήσεων καθορίζονται παρακάτω. Στη ϕάση αυτή απαιτείται η υποστήριξη των πρωτοκόλλων TCP και UDP στο επίπεδο µετα- ϕοράς και των πρωτοκόλλων IPv4 και IPv6 στο επίπεδο διαδικτύου. Οπως ϕαίνεται και από το σχήµα 1, ούτε οι δοµές δεδοµένων αλλά ούτε και οι συναρτήσεις έχουν κάποιο πεδίο/όρισµα για το αν η υλοποίηση είναι σε IPv4 ή IPv6, οπότε ϑα πρέπει να λειτουργούν πάνω από οποιοδήποτε δίκτυο αυτών των τύπων. Η περιγραφή των δοµών δεδοµένων και των συναρτήσεων που ακολουθεί καθορίζει την ελάχιστη λειτουργικότητα του API είστε ελεύθεροι να προσθέσετε και 1 http://www.cs.uoi.gr/~ntarmos/courses/networkprogramming/lectures/lecture01.pdf 1

Σχήµα 1: mynetlib.h 1 #ifndef MY_NET_LIB_H 2 #define MY_NET_LIB_H 3 4 typedef enum { 5 TCPEndpoint, // TCP endpoint. 6 UDPEndpoint, // UDP endpoint. 7 } EndpointType; 8 9 typedef struct { 10 EndpointType type; // Type of the endpoint. 11 int backlog; // For TCP server sockets. 12 int* sd; // Table of socket descriptors. 13 int sdlen; // # elements in sd. 14 struct addrinfo* addr; // Info for the above descriptors. 15 } EndpointInfo; 16 17 int createserverendpoint(const char *host, const char *service, EndpointInfo *info); 18 int createclientendpoint(const char *host, const char *service, EndpointInfo *info); 19 int closeendpoint(endpointinfo *info); 20 int getnextclientfromendpoint(const EndpointInfo *serverinfo, EndpointInfo *clientinfo); 21 int senddatatoendpoint(const EndpointInfo *info, const void *data, size_t datalen); 22 int recvdatafromendpoint(const EndpointInfo *info, void *data, size_t datalen); 23 24 #endif δικές σας ϐοηθητικές/εσωτερικές συναρτήσεις ή/και επιπλέον πεδία στις δοµές δεδοµένων, αν ϑεωρείτε ότι αυτό είναι απαραίτητο, κάτι που ϑα πρέπει και να τεκµηριώσετε στην αναφορά σας. 2.1 createserverendpoint(...) Η συνάρτηση αυτή ϑα δηµιουργεί τα άκρα επικοινωνίας στα οποία η διεργασία του εξυπη- ϱετητή ϑα δέχεται εισερχόµενες αιτήσεις σύνδεσης. Τα ορίσµατα είναι ως εξής : 1. host: Η διεύθυνση IP ή το συµβολικό όνοµα στο οποίο ϑα αναµένουµε εισερχόµενες συνδέσεις, σε ASCII αναπαράσταση (π.χ. «zeus.cs.uoi.gr», «195.130.121.11» κτλ). Αν το πεδίο αυτό έχει την τιµή NULL τότε ϑα πρέπει η αντιστοίχηση να γίνεται µε όλες τις διευθύνσεις του κόµβου στον οποίο εκτελείται η διεργασία του εξυπηρετητή («passive socket»). 2. service: Το συµβολικό όνοµα υπηρεσίας ή ο αριθµός ϑύρας στην οποία ϑα αναµένουµε εισερχόµενες συνδέσεις, σε ASCII αναπαράσταση (π.χ. «http», «80» κτλ.). Το πεδίο αυτό δεν µπορεί να έχει την τιµή NULL. 3. info: είκτης σε δοµή τύπου EndpointInfo. Οταν κληθεί η συνάρτηση ϑα πρέπει 2

Σχήµα 2: TCP createserverendpoint example 1 int err; 2 EndpointInfo tcpinfo; 3 //... 4 tcpinfo.type = TCPEndpoint; 5 tcpinfo.backlog = 5; 6 err = createserverendpoint("zeus.cs.uoi.gr", "http", &tcpinfo); Σχήµα 3: UDP createserverendpoint example 1 int err; 2 EndpointInfo udpinfo; 3 //... 4 udpinfo.type = UDPEndpoint; 5 err = createserverendpoint("gaia.cs.uoi.gr", "domain", &udpinfo); το πεδίο type να έχει τον τύπο του άκρου επικοινωνίας που ϑέλουµε να δηµιουργηθεί. Οταν η συνάρτηση επιστρέψει, στο πεδίο addr ϑα έχουν αποθηκευθεί οι πληροφορίες για το άκρο επικοινωνίας που ϑα δηµιουργήσει η συνάρτηση αυτή. Η συνάρτηση απαιτεί ο δείκτης αυτός να δείχνει σε ισχύουσα ϑέση µνήµης και δε ϑα δεσµεύει αυτή το χώρο µνήµης για τη δοµή αυτή. Ωστόσο ϑα είναι υπεύθυνη να δεσµεύει χώρο για τον πίνακα sd καθώς και την δοµή addr. Ο χώρος αυτός ϑα πρέπει να αποδεσµεύεται όταν κληθεί η closeendpoint(...). Η συνάρτηση αυτή ϑα πρέπει : να µεταφράζει τα ορίσµατα host και service σε δυαδική µορφή, κατάλληλη για χρήση από τις κλήσεις συστήµατος του API των BSD sockets. να δεσµεύει τον απαραίτητο χώρο για τα πεδία sd και addr της δοµής στην οποία δείχνει ο δείκτης info. να εκτελεί κατάλληλες κλήσεις στις συναρτήσεις getaddrinfo(3), socket(2), bind(2) και listen(2), ανάλογα µε τον Ϲητούµενο τύπο άκρου επικοινωνίας. Στην περίπτωση που πρέπει να κληθεί και η listen(2), το µέγεθος της ουράς αναµονής ϑα ϐρίσκεται στο πεδίο backlog της δοµής στην οποία δείχνει ο info, αλλιώς το πεδίο αυτό ϑα αγνοείται. Σε αυτό το στάδιο της υλοποίησης, στην περίπτωση που ο κόµβος στον οποίο ϑα εκτελεστεί η συνάρτηση αυτή έχει παραπάνω από µία διευθύνσεις ή/και υποστηρίζει και IPv4 και IPv6, ϑα επιλέγεται µόνο µία εκ των διευθύνσεων (δηλ. ο πίνακας sd ϑα έχει το πολύ µία ϑέση) συγκεκριµένα, ϑα επιλέγεται η πρώτη διεύθυνση στην λίστα που επιστρέφει η getaddrinfo(3). Η συνάρτηση επιστρέφει 0 όταν πέτυχε να δηµιουργήσει έστω ένα άκρο επικοινωνίας ή -1 για αποτυχία. Ο κώδικας στα σχήµατα 2 και 3 δίνει ένα παράδειγµα χρήσης της συνάρτησης αυτής για συνδέσεις πρωτοκόλλου TCP και UDP αντίστοιχα. 2.2 createclientendpoint(...) Η συνάρτηση αυτή ϑα δηµιουργεί µία σύνδεση ανάµεσα στον πελάτη που την καλεί και τον εξυπηρετητή που της ορίζεται, µέσω της οποίας ο πελάτης ϑα µπορεί να ανταλλάξει κατόπιν 3

Σχήµα 4: TCP createclientendpoint example 1 int err; 2 EndpointInfo tcpinfo; 3 //... 4 tcpinfo.type = TCPEndpoint; 5 err = createclientendpoint("zeus.cs.uoi.gr", "http", &tcpinfo); Σχήµα 5: UDP createclientendpoint example 1 int err; 2 EndpointInfo udpinfo; 3 //... 4 udpinfo.type = UDPEndpoint; 5 err = createclientendpoint("gaia.cs.uoi.gr", "domain", &udpinfo); δεδοµένα µε τον αποµακρυσµένο εξυπηρετητή. Τα ορίσµατα είναι ως εξής : 1. host: Η διεύθυνση IP ή το συµβολικό όνοµα στο οποίο ϑα συνδεθεί ο πελάτης, σε ASCII αναπαράσταση (π.χ. «zeus.cs.uoi.gr», «195.130.121.11» κτλ). Το πεδίο αυτό δε µπορεί να έχει την τιµή NULL. 2. service: Το συµβολικό όνοµα υπηρεσίας ή ο αριθµός ϑύρας στην οποία ϑα συνδεθεί ο πελάτης, σε ASCII αναπαράσταση (π.χ. «http», «80» κτλ.). Το πεδίο αυτό δεν µπορεί να έχει την τιµή NULL. 3. info: είκτης σε δοµή τύπου EndpointInfo. Οταν κληθεί η συνάρτηση ϑα πρέπει το πεδίο type να έχει τον τύπο του άκρου επικοινωνίας που ϑέλουµε να δηµιουργηθεί. Οταν η συνάρτηση επιστρέψει, στο πεδίο addr ϑα έχουν αποθηκευθεί οι πληροφορίες για την σύνδεση που δηµιούργησε η συνάρτηση αυτή. Η συνάρτηση απαιτεί ο δείκτης αυτός να δείχνει σε ισχύουσα ϑέση µνήµης και δε ϑα δεσµεύει αυτή το χώρο µνήµης για τη δοµή αυτή. Ωστόσο ϑα είναι υπεύθυνη να δεσµεύει χώρο για τον πίνακα sd καθώς και την δοµή addr. Ο χώρος αυτός ϑα πρέπει να αποδεσµεύεται όταν κληθεί η closeendpoint(...). Η συνάρτηση αυτή ϑα πρέπει : να µεταφράζει κατάλληλα τα ορίσµατα host και service σε δυαδική µορφή, κατάλληλη για χρήση από τις κλήσεις συστήµατος του API των BSD sockets. να δεσµεύει τον απαραίτητο χώρο για τα πεδία sd και addr της δοµής στην οποία δείχνει ο δείκτης info. ανάλογα µε τον Ϲητούµενο τύπο άκρου επικοινωνίας, να εκτελεί κατάλληλες κλήσεις στις συναρτήσεις getaddrinfo(3), socket(2) και connect(2). Το πεδίο backlog της δοµής στην οποία δείχνει ο info αγνοείται. Στην περίπτωση που ο εξυπηρετητής έχει παραπάνω από µία διευθύνσεις ή/και υποστηρίζει και IPv4 και IPv6, η συνάρτηση ϑα πρέπει να προσπαθήσει να δηµιουργήσει το πολύ µία σύνδεση (δηλ. ο πίνακας sd ϑα έχει το πολύ µία ϑέση). Η συνάρτηση επιστρέφει 0 όταν πέτυχε να δηµιουργήσει έστω µία σύνδεση µε την αποµακρυσµένη διεργασία ή -1 για αποτυχία. Ο κώδικας στα σχήµατα 4 και 5 δίνει ένα παράδειγµα χρήσης της συνάρτησης αυτής για συνδέσεις πρωτοκόλλου TCP και UDP αντίστοιχα. 4

Σχήµα 6: TCP getnextclientfromendpoint example 1 int err; 2 EndpointInfo serverinfo, clientinfo; 3 //... 4 serverinfo.type = TCPEndpoint; 5 serverinfo.backlog = 5; 6 err = createserverendpoint(null, "http", &serverinfo); 7 //... 8 err = getnextclientfromendpoint(&serverinfo, &clientinfo); 2.3 closeendpoint(...) Η συνάρτηση αυτή ϑα κλείνει το άκρο επικοινωνίας που δηµιουργήθηκε από αντίστοιχη κλήση µίας εκ των createserverendpoint(...) και createclientendpoint(...) και ϑα απελευθερώνει τους πόρους που αυτή καταλάµβανε. Τα ορίσµατα είναι ως εξής : 1. info: είκτης σε δοµή τύπου EndpointInfo. Η συνάρτηση απαιτεί ο δείκτης αυτός να δείχνει σε ισχύουσα ϑέση µνήµης. Η συνάρτηση αυτή ϑα πρέπει : να εκτελεί κατάλληλες κλήσεις στις συναρτήσεις close(2) και freeaddrinfo(3). να απελευθερώνει την µνήµη που καταλαµβάνουν τα πεδία sd και addr της δοµής δεδο- µένων στην οποία δείχνει ο info. Η συνάρτηση επιστρέφει 0 για επιτυχία και -1 για αποτυχία. 2.4 getnextclientfromendpoint(...) Η συνάρτηση αυτή ϑα καλείται από εξυπηρετητές τόσο συνδεσµοστραφούς όσο και ασυνδεσµικής επικοινωνίας. Με την συνάρτηση αυτή οι πρώτοι ϑα αποδέχονται την αίτηση σύνδεσης από τον επόµενο πελάτη στη λίστα αναµονής του άκρου επικοινωνίας τους. Για τους δεύτε- ϱους, η συνάρτηση αυτή ϑα µπλοκάρει µέχρι να έρθουν δεδοµένα στο άκρο επικοινωνίας του εξυπηρετητή. Τα ορίσµατα είναι ως εξής : 1. server: είκτης σε δοµή τύπου EndpointInfo. Η συνάρτηση απαιτεί ο δείκτης αυτός να δείχνει σε ισχύουσα ϑέση µνήµης. Η δοµή αυτή αντιστοιχεί στην πληροφορία του άκρου επικοινωνίας του εξυπηρετητή και ϑα πρέπει να έχει προηγουµένως αρχικοποιηθεί µε κατάλληλη κλήση της createserverendpoint(...). 2. client: είκτης σε δοµή τύπου EndpointInfo. Η συνάρτηση απαιτεί ο δείκτης αυτός να δείχνει σε ισχύουσα ϑέση µνήµης. Η δοµή αυτή αντιστοιχεί στην πληροφορία του νέου socket που ϑα δηµιουργηθεί για να συνδέσει τον εξυπηρετητή µε τον επόµενο πελάτη. Οταν η συνάρτηση επιστρέψει, η δοµή αυτή ϑα πρέπει να έχει όλη την απαραίτητη πλη- ϱοφορία για να µπορεί κατόπιν ο εξυπηρετητής να ανταλλάξει δεδοµένα µε τον επόµενο πελάτη. Η συνάρτηση αυτή ϑα πρέπει : να δεσµεύει τον απαραίτητο χώρο για τα πεδία sd και addr της δοµής στην οποία δείχνει ο δείκτης client. 5

να εκτελεί κατάλληλες κλήσεις στη συνάρτηση accept(2) ή recvfrom(2), ανάλογα µε το Ϲητούµενο τύπο άκρου επικοινωνίας. Η συνάρτηση ϑα επιστρέφει 0 για επιτυχία και -1 για αποτυχία. Ο κώδικας στο σχήµα 6 δίνει ένα παράδειγµα χρήσης της συνάρτησης αυτής για συνδέσεις πρωτοκόλλου TCP. 2.5 senddatatoendpoint(...) και recvdatafromendpoint(...) Οι συναρτήσεις αυτές ϑα χρησιµοποιούνται τόσο από εξυπηρετητές όσο και από πελάτες για να ανταλλάξουν µεταξύ τους δεδοµένα. Τα ορίσµατα είναι ως εξής : 1. info: είκτης σε δοµή τύπου EndpointInfo. Η συνάρτηση απαιτεί ο δείκτης αυτός να δείχνει σε ισχύουσα ϑέση µνήµης. Η δοµή αυτή αντιστοιχεί στην πληροφορία του άκρου επικοινωνίας στο οποίο ϑα στείλουµε ή από το οποίο ϑα λάβουµε δεδοµένα καλώντας την senddatatoendpoint(...) ή την recvdatafromendpoint(...) αντίστοιχα. 2. data: είκτης σε ϑέση µνήµης όπου ϐρίσκονται τα δεδοµένα που ϑα στείλουµε ή στον οποίο ϑα γραφούν τα δεδοµένα που ϑα λάβουµε. Οι συναρτήσεις αυτές απαιτούν ο δείκτης αυτός να δείχνει σε ισχύουσα ϑέση µνήµης και δε ϑα δεσµεύουν αυτές τον αντίστοιχο χώρο. 3. datalen: Μέγεθος σε bytes του χώρου µνήµης στον οποίο δείχνει ο δείκτης data. Οι συναρτήσεις αυτές ϑα πρέπει : να µετατρέπουν τα δεδοµένα από και πρός κάποια ενδιάµεση µορφή της επιλογής σας (σχολιάστε την σχεδίασή σας στην αναφορά σας), ώστε να επιτρέπουν την επικοινωνία ανάµεσα σε υπολογιστές µε διαφορετική δυαδική αναπαράσταση (big-endian vs. littleendian). Προφανώς η senddatatoendpoint(...) ϑα µετατρέπει τα δεδοµένα στην ενδιάµεση µορφή, ενώ η recvdatatoendpoint(...) ϑα αντιστρέφει την παραπάνω µετατροπή. να εκτελεί κατάλληλες κλήσεις στις συναρτήσεις read(2), write(2), send(2), recv(2), sendto(2) και recvfrom(2), ανάλογα µε τον τύπο του άκρου επικοινωνίας που περιγράφει η δοµή στην οποία δείχνει ο info και µε το αν στέλνουµε ή λαµβάνουµε δεδοµένα. Οι συναρτήσεις ϑα επιστρέφουν -1 για αποτυχία ή τον αριθµό των bytes που στάλθηκαν ή λήφθηκαν προς/από το άκρο επικοινωνίας. Για την περίπτωση σύνδεσης UDP, ϑα πρέπει οι συναρτήσεις αυτές να κατακερµατίζουν τα δεδοµένα που τους δίνονται σε πακέτα κατάλληλου µεγέθους, ενώ δε ϑα πρέπει να σας απασχολεί η απώλεια πακέτων κατά τη µεταφορά µεγάλου όγκου δεδοµένων καθώς κάτι τέτοιο είναι αποδεκτό για το πρωτόκολλο αυτό. 2.6 Συνολική εικόνα Στα σχήµατα 7 και 8 ϕαίνεται ένα πλήρες παράδειγµα κώδικα πελάτη και εξυπηρετητή αντίστοιχα οι οποίοι χρησιµοποιούν το παραπάνω API. Ο πελάτης δέχεται ως ορίσµατα γραµµής εντολών το συµβολικό όνοµα ή την IP διεύθυνση του εξυπηρετητή και το συµβολικό όνοµα υπηρεσίας ή τον αριθµό ϑύρας στα οποία ϑα συνδεθεί, καθώς και ποιο πρωτόκολλο («tcp» ή «udp») ϑα χρησιµοποιήσει. Αντίστοιχα, ο εξυπηρετητής δέχεται ως ορίσµατα γραµµής εντολών µόνο το συµβολικό όνοµα υπηρεσίας ή τον αριθµό ϑύρας όπου και ϑα περιµένει για νέους πελάτες, καθώς και ποιο πρωτόκολλο («tcp» ή «udp») ϑα χρησιµοποιήσει. Παρατηρήστε ότι τόσο ο κώδικας του πελάτη όσο και αυτός του εξυπηρετητή είναι πανο- µοιότυποι ανεξάρτητα απ το αν η επικοινωνία γίνεται πάνω από TCP ή UDP και από το αν στο επίπεδο διαδικτύου έχουµε IPv4 ή IPv6 (το µόνο που αλλάζει είναι το πεδίο server.type). Ο 6

κώδικάς σας ϑα πρέπει να παρέχει όλη την απαιτούµενη λειτουργικότητα ώστε αυτό να είναι εφικτό. Σχήµα 7: Client example 1 #include <stdio.h> 2 #include <string.h> 3 #include "mynetlib.h" 4 5 int main(int argc, char **argv) { 6 EndpointInfo server; 7 const char data[11] = "0123456789"; 8 9 if (argc!= 4 (strcmp(argv[3], "tcp") && strcmp(argv[3], "udp"))) { 10 fprintf(stderr, "Usage: %s <host> <service> <tcp udp>\n", argv[0]); 11 return 1; 12 } 13 14 server.type = strcmp(argv[3], "tcp")? UDPEndpoint : TCPEndpoint; 15 if (createclientendpoint(argv[1], argv[2], &server)) 16 return 1; 17 if (senddatatoendpoint(&server, data, sizeof(data))!= sizeof(data)) 18 return 1; 19 if (closeendpoint(&server)) 20 return 1; 21 return 0; 22 } Σχήµα 8: Server example 1 #include <stdio.h> 2 #include <string.h> 3 #include "mynetlib.h" 4 5 int main(int argc, char **argv) { 6 char buf[11]; 7 EndpointInfo server, client; 8 9 if (argc!= 3 (strcmp(argv[2], "tcp") && strcmp(argv[2], "udp"))) { 10 fprintf(stderr, "Usage: %s <service> <tcp udp>\n", argv[0]); 11 return 1; 12 } 13 14 server.type = strcmp(argv[2], "tcp")? UDPEndpoint : TCPEndpoint; 15 server.backlog = 5; 16 if (createserverendpoint(null, argv[1], &server)) 17 return 1; 18 while (1) { 19 if (getnextclientfromendpoint(&server, &client)) 20 return 1; 21 memset(buf, 0, sizeof(buf)); 22 if (recvdatafromendpoint(&client, buf, sizeof(buf)) < 0) 23 return 1; 7

24 printf("%s\n", buf); 25 if (closeendpoint(&client) < 0) 26 return 1; 27 } 28 if (closeendpoint(&server) < 0) 29 return 1; 30 return 0; 31 } 3 Εφαρµογή ανταλλαγής αρχείων Στο δεύτερο κοµµάτι της εργασίας αυτής σας Ϲητείται να υλοποιήσετε έναν απλό εξυπηρετητή και ένα Ϲεύγος απλών πελατών ανταλλαγής αρχείων, χρησιµοποιώντας τη ϐιβλιοθήκη που ϕτιάξατε προηγουµένως. Η Ϲητούµενη λειτουργικότητα των προγραµµάτων αυτών περιγράφεται παρακάτω. 3.1 Πελάτες Θα πρέπει να υλοποιήσετε δύο πελάτες : download και upload. Ο πρώτος ϑα µεταφορτώνει ένα αρχείο από τον εξυπηρετητή στον τρέχοντα κατάλογο ενώ ο δεύτερος ϑα µεταφορτών ένα αρχείο από τον τρέχοντα κατάλογο στον εξυπηρετητή. Και στις δύο περιπτώσεις, το πρόγραµµά σας ϑα πρέπει να δέχεται ως ορίσµατα γραµµής εντολών ένα όνοµα κόµβου (συµβολικό ή αριθ- µητικό), ένα όνοµα υπηρεσίας (συµβολικό ή αριθµητικό), προαιρετικά το πρωτόκολλο επιπέδου µεταφοράς («tcp» ή «udp») που ϑα χρησιµοποιήσει κατά τη σύνδεσή του µε τον αποµακρυσµένο εξυπηρετητή, και το όνοµα του αρχείου που ϑα µεταφορτώσει. Αν δεν ορίζεται πρωτόκολλο επιπέδου µεταφοράς, ϑα εννοείται ως όρισµα το «tcp». Κατά την εκτέλεσή του, ϑα πρέπει : 1. Να συνδέεται µε τον εξυπηρετητή που ορίζεται από το όνοµα κόµβου και το όνοµα υπη- ϱεσίας της γραµµής εντολών, 2. Να δηµιουργεί ή/και να ανοίγει το αρχείο που ορίστηκε στη γραµµή εντολών, 3. Στην περίπτωση του upload, να στέλνει την null-terminated ( \0 ) συµβολοσειρά «PUT» και τα δεδοµένα του αρχείου στον εξυπηρετητή. 4. Στην περίπτωση του download, να στέλνει την null-terminated συµβολοσειρά «GET filename» στον εξυπηρετητή (όπου filename το όνοµα του αρχείου που ϑέλει να µεταφορτώσει), να λαµβάνει τα δεδοµένα που του στέλνει ο εξυπηρετητής και να τα γράφει στο τοπικό αρχείο, 5. Να τερµατίζει τη σύνδεση και να επιστρέφει : (α ) 0, αν η µεταφόρτωση τερµατίσει οµαλά. (ϐ ) 1, αν συµβεί κάποιο λάθος στην επικοινωνία, τυπώνοντας στο standard error του το κατάλληλο µήνυµα (δείτε τις gai_strerror(3) και perror(3)), ή αν δεν µετέφερε καθόλου δεδοµένα (π.χ. δεν υπήρχε το Ϲητούµενο αρχείο στον εξυπηρετητή). 3.2 Εξυπηρετητής Το πρόγραµµά σας ϑα πρέπει να δέχεται ως ορίσµατα γραµµής εντολών το συµβολικό όνοµα υπηρεσίας ή τον αριθµό ϑύρας όπου και ϑα περιµένει αιτήσεις από πελάτες και προαιρετικά το 8

πρωτόκολλο επιπέδου µεταφοράς («tcp» ή «udp») µέσω του οποίου ϑα γίνει η επικοινωνία. Αν δεν ορίζεται πρωτόκολλο ϑα εννοείται ως όρισµα το «tcp». Κατά την εκτέλεσή του, ο εξυπηρετητής σας ϑα πρέπει : 1. Να δεσµεύει την Ϲητούµενη ϑύρα σε όλες τις διευθύνσεις του κόµβου στον οποίο εκτελείται, 2. Να περιµένει εισερχόµενες αιτήσεις από πελάτες, 3. Για κάθε τέτοια αίτηση, να διαβάζει τη συµβολοσειρά που του στέλνει ο πελάτης, µέχρι να ϐρει χαρακτήρα \0», 4. Για την εντολή «PUT», να δηµιουργεί/µηδενίζει/ανοίγει το Ϲητούµενο αρχείο και να γράφει τα δεδοµένα που του στέλνει ο πελάτης σε αυτό. 5. Για την εντολή «GET», να ανοίγει το Ϲητούµενο αρχείο και να στέλνει τα δεδοµένα του στον πελάτη. 6. Αν υπάρξει κάποιο πρόβληµα µε το αρχείο (π.χ. δεν υπάρχει, δεν µπορεί να αναγνωστεί, δε µπορεί να δηµιουργηθεί, κτλ.), ϑα πρέπει να κλείνει απευθείας την σύνδεση χωρίς να στέλνει δεδοµένα στον πελάτη. 7. Να επανέρχεται στο ϐήµα 2 σε αναµονή για νέο πελάτη. Στη ϕάση αυτή δεν απαιτείται ο εξυπηρετητής σας να έχει τη δυνατότητα παράλληλης επεξεργασίας πολλαπλών αιτήσεων ή την εκτέλεσή του στο παρασκήνιο. Σε περίπτωση που συµβεί κάποιο σφάλµα κατά την επικοινωνία του εξυπηρετητή µε κάποιον πελάτη, ϑα πρέπει να τυπώνει κατάλληλο µήνυµα λάθους στο standard error του και να συνεχίζει µε τον επόµενο πελάτη στη λίστα, αφού πρώτα κλείσει τη σύνδεση µε τον προηγούµενο πελάτη. Α ηµιουργία ϐιβλιοθήκης Σε περιβάλλον UNIX µπορείτε να «συλλέξετε» διάφορα αρχεία ενδιάµεσου κώδικα (.o) και να δηµιουργήσετε µία ϐιβλιοθήκη, την οποία κατόπιν µπορείτε να συνδέετε µε τον κώδικά σας κατά τη µετάφρασή του (linking). Αυτό επιτυγχάνεται ως εξής : 1. Οργανώνετε τον κώδικά σας όπως ϑέλετε σε αρχεία.c και.h. Εστω ότι η ϐιβλιοθήκη που σας Ϲητείται στο πρώτο τµήµα της εργασίας αυτής είναι υλοποιηµένη στα αρχεία createserverendpoint.c, createclientendpoint.c, closeendpoint.c, getnext- ClientFromEndpoint.c, senddatatoendpoint.c και recvdatafromendpoint.c και ότι ο πελάτης και ο εξυπηρετητής είναι υλοποιηµένοι στα αρχεία myhttpclient.c και myhttpserver.c αντίστοιχα 2. 2. Μεταφράζουµε τα αρχεία.c της υλοποίησης του API σε αντίστοιχα αρχεία ενδιάµεσου κώδικα.o, εκτελώντας την εντολή gcc -c <filename>. 3. Κατόπιν συλλέγουµε όλα τα αρχεία ενδιάµεσου κώδικα σε ένα «archive» (lib*.a), µε την εντολή ar rc <archive> <filenames>. 4. ηµιουργούµε δοµή δεικτοδότησης στο αρχείο που προκύπτει από το προηγούµενο ϐήµα εκτελώντας την εντολή ranlib <archive>. Η ϐιβλιοθήκη είναι τώρα έτοιµη προς χρήση. Μπορούµε στη συνέχεια να µεταφράσουµε τα αρχεία του πελάτη και του εξυπηρετητή και να συνδέσουµε τη ϐιβλιοθήκη, προσθέτοντας στη γραµµή εντολών του µεταφραστή τα ορίσµατα -L. -l<archive>, όπου από το όνοµα του archive έχουµε αφαιρέσει το πρόθεµα lib. Το σχήµα 9 δίνει ένα παράδειγµα των παραπάνω σε περιβάλλον κελύφους. Στη γραµµή 7 µεταφράζουµε όλα τα αρχεία της υλοποίησης του API σε αρχεία ενδιάµεσου κώδικα, τα 2 Προφανώς κάτι τέτοιο ούτε απαιτείται ούτε ενδείκνυται χρησιµοποιούµε τη δοµή αυτή εδώ χάριν παραδείγµατος. 9

Σχήµα 9: Library creation 1 user@host:~/myproject1$ ls 2 MyNetLib.h myclient.c 3 closeendpoint.c myserver.c 4 createclientendpoint.c recvdatafromendpoint.c 5 createserverendpoint.c senddatatoendpoint.c 6 getnextclientfromendpoint.c 7 user@host:~/myproject1$ gcc -c *Endpoint.c 8 user@host:~/myproject1$ ls 9 MyNetLib.h getnextclientfromendpoint.o 10 closeendpoint.c myclient.c 11 closeendpoint.o myserver.c 12 createclientendpoint.c recvdatafromendpoint.c 13 createclientendpoint.o recvdatafromendpoint.o 14 createserverendpoint.c senddatatoendpoint.c 15 createserverendpoint.o senddatatoendpoint.o 16 getnextclientfromendpoint.c 17 user@host:~/myproject1$ ar rc libmynet.a *.o 18 user@host:~/myproject1$ rm *.o 19 user@host:~/myproject1$ ranlib libmynet.a 20 user@host:~/myproject1$ gcc myclient.c -L. -lmynet -o myclient 21 user@host:~/myproject1$ gcc myserver.c -L. -lmynet -o myserver 22 user@host:~/myproject1$ οποία και ϐλέπουµε µε την εντολή της γραµµής 8. ηµιουργούµε το archive µε την εντολή της γραµµής 17 και διαγράφουµε τα αρχεία ενδιάµεσου κώδικα µε την εντολή της γραµµής 18 αφού δεν τα χρειαζόµαστε άλλο. Με την εντολή στη γραµµή 19 δηµιουργούµε µία δοµή δεικτοδότησης στο archive η οποία απαιτείται για τη χρήση του από τον µεταφραστή, οπότε και η ϐιβλιοθήκη είναι πλέον έτοιµη. Τέλος, στις γραµµές 20 και 21 ϐλέπουµε πως τη χρησιµοποιούµε κατά την µετάφραση των αρχείων του πελάτη και του εξυπηρετητή. 10