Асинхронный клиент Python отправляет только последний элемент из списка внутри потока

Это мой клиент:

class TestClient(asyncore.dispatcher):
    #private
    _buffer = ""
    #public
    def __init__(self, host, port):
        asyncore.dispatcher.__init__(self)
        self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
        self.connect((host, port))
        self.client = Sender(self)
        self.client.start()
        # other code
    def handle_connect(self):
        pass

    def handle_close(self):
        self.close()
        self.client.stop()

    def handle_read(self):
        try:
            data = self.recv(8192)
            self.artist.ParseFromString(data)
            # print data here
        except Exception as ex:
            print ex

    def writable(self):
        return (len(self._buffer) > 0)

    def handle_write(self):
        sent = self.send(self._buffer)
        self.buffer = self._buffer[sent:]

    def link(self, name):
        return name.replace(' ', '%20')

    def sendArtist(self, artist):
        print "here"
        self._buffer = self.link(artist)


class Sender(threading.Thread):
    #private
    _stop = False
    #public
    def __init__(self, client):
        super(Sender, self).__init__()
        self.client = client

    def stop(self):
        self._stop = True

    def run(self):
        i = 0
        while self._stop == False and i < len(artists.artistList):
            self.client.sendArtist(artists.artistList[i])
            i += 1

client = TestClient("127.0.0.1", 7899)
asyncore.loop()

Моя проблема заключается в методе запуска в классе Sender, для каждого элемента в artist.artistList при вызове sendArtist() будет вызываться writable() для всех из них, а handle_write() только для последнего элемента.

Что я могу сделать, чтобы handle_write() вызывался для каждого элемента в списке, а не только для последнего?

Вот как это работает сейчас: artist.artistList = ["madonna", "tiesto", "atb"];

writable - madonna
writable - tiesto
writable - atb
handle_write - atb
handle_write - atb
...................
handle_write - atb

Это то, что я хочу:

writable - madonna
handle_write - madonna
writable - tiesto
handle_write - tiesto
writable - atb
handle_write - atb

person Adrian    schedule 03.09.2013    source источник
comment
Почему бы вам не добавить в буфер?   -  person Thomas Orozco    schedule 04.09.2013
comment
Внутри sendArtist. Весь смысл асинхронного программирования в том, что вы не контролируете, когда что-то отправляется в сеть, поэтому то, чего вы пытаетесь достичь, невозможно с помощью asyncore. Однако вы можете использовать обычные розетки.   -  person Thomas Orozco    schedule 04.09.2013
comment
Хорошо, вы можете сделать это как ответ, чтобы я мог его принять.   -  person Adrian    schedule 04.09.2013


Ответы (1)


Asyncore — это асинхронный фреймворк, поэтому вы не контролируете, когда пишете в сеть.

Здесь у вас есть два варианта:

  • Используйте обычные синхронные сокеты
  • Добавить в буфер вместо его замены

Второй вариант не требует пояснений, поэтому вот как вы это сделаете с обычными сокетами:

import socket

class TestClient(object):
    _buffer = ""

    def __init__(self, host, port):
        self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        self.connect((host, port))

    def writable(self):
        return (len(self._buffer) > 0)

    def write(self):
        while self.writable():
            sent = self.send(self._buffer)
            self.buffer = self._buffer[sent:]

    def link(self, name):
        return name.replace(' ', '%20')

    def sendArtist(self, artist):
        print "here"
        self._buffer = self.link(artist)
        self.write()
person Thomas Orozco    schedule 03.09.2013