gon1332 Δημοσ. 28 Δεκεμβρίου 2014 Δημοσ. 28 Δεκεμβρίου 2014 Καλημέρα σας, το σύστημά μου έχει ως εξής: Έχω έναν server και πολλούς clients. Ο κάθε client έχει έναν αριθμό από αιτήματα, τα οποία και αποστέλει στον server. O server πρέπει να τα δεχτεί όλα χωρίς να είναι ανάγκη να γνωρίζει από ποιόν στάλθηκαν. Τί προσπάθησα να κάνω: Αρχικά έπαιξα με απλό client-server scheme: (ο κώδικας που δίνω παρακάτω δείχνει περισσότερο το τί θέλω να κάνω και αποκρύπτει περιττές λεπτομέρειες) server: #!/usr/bin/python import socket s = socket.socket() host = socket.gethostname() port = 12345 s.bind((host, port)) s.listen(5) # Now wait for client connection. while True: c, addr = s.accept() # Establish connection with client. print c.recv(12345) c.close() # Close the connection client: #!/usr/bin/python import socket s = socket.socket() host = socket.gethostname() port = 12345 for i in xrange(10): s.connect((host, port)) print s.send("data"+str(i)) s.close # Close the socket when done Το πρώτο μήνυμα αποστέλονταν κανονικά. Όταν όμως προχωρούσε με τα υπόλοιπα η εκτέλεση σταματούσε με ένα "Bad file descriptor" μήνυμα. Ψάχνοντάς το βρήκα πως αυτό που θέλω να κάνω γίνεται με ασύγχρονη επικοινωνία sockets, οπότε υπήρξαν παραπομπές στο asyncore. Από την περιγραφή του module καταλαβαίνω πως είναι ό,τι χρειάζομαι. Το θέμα είναι ότι δε βρήκα ακόμη πώς να το προσαρμόσω στα θέλω μου. Η αλήθεια είναι ότι δεν έχω πολύ εμπειρία με sockets γενικότερα. Μία άλλη σκέψη που μου πέρασε είναι η χρήση της πρώτης λύσης σε συνδυασμό με multithreading, αλλά τα requests τα θέλω να στέλνονται με κάποια συγκεκριμένη σειρά. Γιατί να μπλέξω με συγχρο- νισμούς κλπ ενώ θέλω κάτι (φαινομενικά τουλάχιστον) απλό; Τί θα μπορούσα να κάνω; Κάποια κατεύθυνση, συμπλήρωση διόρθωση στα παραπάνω;
pmav99 Δημοσ. 28 Δεκεμβρίου 2014 Δημοσ. 28 Δεκεμβρίου 2014 Αυτό το είδες; http://pymotw.com/2/asyncore/
gon1332 Δημοσ. 28 Δεκεμβρίου 2014 Μέλος Δημοσ. 28 Δεκεμβρίου 2014 Αυτό το είδες; http://pymotw.com/2/asyncore/ Η αλήθεια είναι ότι το είχα βρει αλλά δεν το έκανα bookmark να το θυμηθώ. Εμένα με μπέρδεψε λίγο η ονομασία της κλάσης του Client. Στην ουσία εγώ που έχω πολλούς client και o κάθε client στέλνει έναν αριθμό από requests, θα μετονομάσω την κλά- ση σε ClientRequest και θα ακολουθήσω την ίδια διαδικασία; Στέκει κάτι τέτοιο σαν λογική σεναρίου χρήσης του module;
παπι Δημοσ. 28 Δεκεμβρίου 2014 Δημοσ. 28 Δεκεμβρίου 2014 Το error το παίρνεις επειδή κανεις connect σε μια closed socket. Βαλέ όλο το init της socket μέσα στη while. Async θες όταν έχεις πολλαπλούς συνδεδεμένους clients, κάτι που δεν εχεις στο παράδειγμα σου. Edit στη for θέλω να πω...
gon1332 Δημοσ. 28 Δεκεμβρίου 2014 Μέλος Δημοσ. 28 Δεκεμβρίου 2014 Εγώ όμως επιθυμώ να έχω πολλαπλούς clients και αυτοί οι clients να στέλνουν πολλαπλά requests. Αυτό που μου είπες δούλεψε πάντως.Είχες δίκαιο.
pmav99 Δημοσ. 28 Δεκεμβρίου 2014 Δημοσ. 28 Δεκεμβρίου 2014 Για ό,τι θες από την Standard Library της Python 2, να κοιτάς πάντα στο Python module of the week. Βάλτο στα bookmarks. Δυστυχώς, δεν υπάρχει κάτι αντίστοιχο για Python 3. Από εκεί και πέρα, ο «παπί» έχει δίκιο, αν και νομίζω ότι είναι καλύτερα να βάλεις το s.close() εκτός loop στον client. Να ξαναχρησιμοποιείς δηλαδή το ίδιο socket. Τώρα διάβασα πιο προσεκτικά το post σου. Αν έχεις να στείλεις πολλά requests από τον κάθε client και δες θες να τα στείλεις ένα ένα (σειριακά) τότε μπορείς να χρησιμοποιήσεις το asyncore. Αν η σειριακή αποστολή τους είναι ΟΚ, τότε δεν το χρειάζεσαι. Την ερώτηση σου για την ονομασία της κλάσης δεν την καταλαβαίνω. Δεν έχω ασχοληθεί πολύ και εγώ με αυτά, η λογική εν γένει είναι ότι για κάθε request που θες να στείλεις από τον client θα φτιάχνεις ένα instance του HTTPClient(asyncore.dispatcher) και μετά θα καλείς την asyncore.loop(). edit Αν σε ενδιαφέρει γενικά το network programming, κυκλοφόρησε πρόσφατα αυτό: http://www.amazon.com/Foundations-Python-Network-Programming-Brandon/dp/1430258543/ref=dp_ob_title_bk#reader_1430258543 https://github.com/brandon-rhodes/fopnp
gon1332 Δημοσ. 28 Δεκεμβρίου 2014 Μέλος Δημοσ. 28 Δεκεμβρίου 2014 Ευχαριστώ για τις απαντήσεις σας. Τελικά το κατάφερα με τη select έτσι: server: #!/usr/bin/env python """ An echo server that uses select to handle multiple clients at a time. Entering any line of input at the terminal will exit the server. """ import select import socket host = '' port = 12345 backlog = 5 size = 1024 server = socket.socket(socket.AF_INET, socket.SOCK_STREAM) server.bind((host, port)) server.listen(backlog) input = [server, ] running = 1 while running: inputready, outputready, exceptready = select.select(input, [], []) for s in inputready: if s == server: # handle the server socket client, address = server.accept() input.append(client) print 'server: new client added: %s' % str(address) else: # handle all other sockets data = s.recv(size) if data: print 'server: %s received from %s' % (data, s.getsockname()) s.send(data) else: s.close() input.remove(s) server.close() client: #!/usr/bin/env python """ An echo client that allows the user to send multiple lines to the server. Entering a blank line will exit the client. """ import socket import sys host = 'localhost' port = 12345 size = 1024 s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.connect((host, port)) sys.stdout.write('%') while 1: # read from keyboard line = sys.stdin.readline() if line == ' ': break s.send(line) data = s.recv(size) sys.stdout.write(data) sys.stdout.write('%') s.close() Αν το δοκιμάσετε θα δείτε πώς δουλεύει. Στην ουσία οι clients στέλνουν κείμενο από το stdin στον server κι αυτός το κάνει echo στον αντίστοιχο αποστολέα. 1
Προτεινόμενες αναρτήσεις
Δημιουργήστε ένα λογαριασμό ή συνδεθείτε για να σχολιάσετε
Πρέπει να είστε μέλος για να αφήσετε σχόλιο
Δημιουργία λογαριασμού
Εγγραφείτε με νέο λογαριασμό στην κοινότητα μας. Είναι πανεύκολο!
Δημιουργία νέου λογαριασμούΣύνδεση
Έχετε ήδη λογαριασμό; Συνδεθείτε εδώ.
Συνδεθείτε τώρα