Προς το περιεχόμενο

Προτεινόμενες αναρτήσεις

Δημοσ.

Καλημέρα σας,

 

το σύστημά μου έχει ως εξής:

 

Έχω έναν 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 τα θέλω να στέλνονται με κάποια συγκεκριμένη σειρά. Γιατί να μπλέξω με συγχρο-

νισμούς κλπ ενώ θέλω κάτι (φαινομενικά τουλάχιστον) απλό;

 

Τί θα μπορούσα να κάνω; Κάποια κατεύθυνση, συμπλήρωση διόρθωση στα παραπάνω;

Δημοσ.

Αυτό το είδες;

http://pymotw.com/2/asyncore/

Η αλήθεια είναι ότι το είχα βρει αλλά δεν το έκανα bookmark να το θυμηθώ.

 

Εμένα με μπέρδεψε λίγο η ονομασία της κλάσης του Client.

Στην ουσία εγώ που έχω πολλούς client και o κάθε client

στέλνει έναν αριθμό από requests, θα μετονομάσω την κλά-

ση σε ClientRequest και θα ακολουθήσω την ίδια διαδικασία;

Στέκει κάτι τέτοιο σαν λογική σεναρίου χρήσης του module;

Δημοσ.

Το error το παίρνεις επειδή κανεις connect σε μια closed socket. Βαλέ όλο το init της socket μέσα στη while. Async θες όταν έχεις πολλαπλούς συνδεδεμένους clients, κάτι που δεν εχεις στο παράδειγμα σου.

Edit στη for θέλω να πω...

Δημοσ.

Εγώ όμως επιθυμώ να έχω πολλαπλούς clients και

αυτοί οι clients να στέλνουν πολλαπλά requests.

Αυτό που μου είπες δούλεψε πάντως.Είχες δίκαιο.

Δημοσ.

Για ό,τι θες από την 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

Δημοσ.

Ευχαριστώ για τις απαντήσεις σας. Τελικά το κατάφερα με τη 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 στον αντίστοιχο

αποστολέα.

  • Like 1

Δημιουργήστε ένα λογαριασμό ή συνδεθείτε για να σχολιάσετε

Πρέπει να είστε μέλος για να αφήσετε σχόλιο

Δημιουργία λογαριασμού

Εγγραφείτε με νέο λογαριασμό στην κοινότητα μας. Είναι πανεύκολο!

Δημιουργία νέου λογαριασμού

Σύνδεση

Έχετε ήδη λογαριασμό; Συνδεθείτε εδώ.

Συνδεθείτε τώρα
  • Δημιουργία νέου...