Skip to content

rigas2k19/SysPro-Project2

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

4 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Βασιλείου Ρηγίνος sdi1900019

Server-client model for directory transfering.

Μεταγλώττιση : make

Clean : make clean

Run : ./dataServer -p -s <thread_pool_size> -q <queue_size> -b <block_size>

  ./remoteClient -i <server_ip> -p <server_port> -d <directory>

Τα ζευγάρια ορισμάτων μπορεί να δίνονται σε διαφορετική σειρά από αυτή.

Έτρεξα την εργασία στα linux της σχολής τρέχοντας τον server στα linux 11 και τους clients στα linux 12 και 13 αντίστοιχα. Για τον τερματισμό του server πρέπει να δοθεί σήμα SIGINT, ενώ οι clients τερματίζουν με το που τελειώσουν την αντιγραφή του καταλόγου που τους δόθηκε ως όρισμα.

Η υλοποίηση της ουράς είναι παρόμοια με την υλοποίηση που είχα στην προηγούμενη εργασία με διαφορά ότι τώρα οι τιμές που περνιούνται στην ουρά είναι δείκτες σε struct addVars (στο οποίο κρατάω το socket id, το μέγεθος του αρχείου (size) και το path του αρχείου).

Στο myDeclarations.h βρίσκονται οι δηλώσεις του struct addVars και των συναρτήσεων που χρησιμοποιώ στο πρόγραμμα.

SERVER

Ο server αρχικοποιείται με τις τιμές που δίνονται ως ορίσματα, φτιάχνεται η ουρά execution_queue για max size το <queue_size> και για το thread pool υπάρχει ένας πίνακας <thread_pool_size> θέσεων για τα worker threads. Τα worker threads δημιουργούνται και περιμένουν να προστεθεί κάποιο αρχείο στην ουρά ώστε να το επεξεργαστούν και να το στείλουν στον client. Για να συμβεί αυτό έχω ένα condition variable στη συνάρτηση του worker η οποία ελέγχει αν το μέγεθος της ουράς είναι 0. Στην αρχή που δε θα έχουμε περάσει αρχεία οι workers θα περιμένουν και μόλις το communication thread περάσει κάποιο αρχείο θα στείλει σήμα στο condition variable και κάποιος worker θα "ξυπνήσει" και θα προχωρήσει στην επεξεργασία του αρχείου. Το worker thread περνάει στο socket το μέγεθος του αρχείου (ώστε να ξέρει ο client πόσο να διαβάσει), μετά περνάει το file path και μετά το αρχείο ανά <block_size>. Ο συγχρονισμός για την επικοινωνία μεταξύ client και server γίνεται με μηνύματα. Ο server στέλνει στοιχεία στον client και περιμένει απάντηση από τον client ότι τα έλαβε για να μπορέσει να προχωρήσει στην αποστολή των επόμενων στοιχείων. Οι απαντήσεις είναι ints με το 1 να σημαίνει ότι το μήνυμα διαβάστηκε και το 2 ότι ο client διάβασε και το τελευταίο αρχείο οπότε ο worker πρέπει να κλείσει το socket. Για να "καταλάβει" ο client το τέλος του αρχείου (αντί να διαβάζει file_size bytes) στέλνεται ένα μήνυμα από τον server της μορφής "file_path-EOF".

Για να αποφευχθούν τυχόν race conditions οποιοδήποτε access στην queue και γράψιμο στο socket γίνεται με mutex.

Για κάθε νέα σύνδεση (νέο client) δημιουργείται ένα communication thread. Το communication thread διαβάζει από τον client το path του directory που θέλει να αντιγράψει και καλεί 2 συναρτήσεις:

  • Την get_number_of_files η οποία διατρέχει τον κατάλογο προς αντιγραφή αναδρομικά και παίρνει τον αριθμό των αρχείων που περιέχει ο κατάλογος αυτός. Έπειτα τον περνάει στον client ώστε να ξέρει πόσα αρχεία να περιμένει.
  • Την get_files η οποία διατρέχει αναδρομικά τον κατάλογο και προσθέτει αντικείμενα τύπου AddVars στην ουρά (τύπου AddVars για να έχουν όλες τις πληροφορίες που χρειαζόμαστε στη συνάρτηση workerThread) Αν η ουρά έχει φτάσει το <max_queue_size> τότε περιμένει να σταλεί σήμα στο condition variable από τον worker. Ο worker στέλνει σήμα όταν παίρνει ένα στοιχείο από την ουρά για να δηλώσει ότι άδειασε μια θέση.

CLIENT

Ο client κάνει τη σύνδεση στο port που του δίνεται ως όρισμα και στέλνει στο socket το directory path που θέλουμε να αντιγράψουμε (το dir_path μπορείτε να το δώσετε και με '/' στο τέλος και χωρίς). Έπειτα δέχεται τον αριθμό των αρχείων που πρέπει να διαβάσει από τον server. Για κάθε ένα αρχείο δέχεται το file size - στέλνει μήνυμα στο server ότι το έλαβε και το file path - ξαναστέλνει μήνυμα στον server. Διαγράφει του επιπλέον φακέλους που ίσως έχει το dir_path πχ. από /home/users/sdi1900019/CopyFolder κρατάει το CopyFolder. Έπειτα δημιουργεί τους φακέλους και φτιάχνει το string που συμβολίζει το eof του αρχείου πχ. για την προηγούμενη περίπτωση /home/users/sdi1900019/CopyFolder-EOF. Αν κάποιο αρχείο υπάρχει ήδη τότε διαγράφεται και ξαναδημιουργείται. Διαβάζει το αρχείο μέχρι να λάβει το string τερματισμού και αν τελείωσε την ανάγνωση του τελευταίου αρχείου, αντί για 1 γράφει στον server 2 ώστε να κλείσει το socket.

ΠΑΡΑΔΟΧΕΣ

  • Τα αρχεία που θα βρίσκονται στον φάκελο προς αντιγραφή δε θα είναι άδεια.
  • Για την αντιγραφή δημιουργείται στο current directory ο φάκελος Client μέσα στον οποίο θα αντιγράφονται τα αρχεία και οι φάκελοι.
  • Μέρος του κώδικα για τα sockets πάρθηκε από τις διαφάνειες του μαθήματος.

Releases

No releases published

Packages

No packages published