On 29 Lug, 13:09, Frank Millman <[EMAIL PROTECTED]> wrote: > Firstly, having got asyncore working, I had a look at asynchat. As far > as I can see I get very little benefit from using it. I have already > set up a 'messaging' protocol between server and client, where all > messages consist of 5 digits for the message length, followed by the > message. The message consists of a pickled tuple, where the first > element is a message identifier, and the rest is the message body. > > This is how it works in asyncore - > > def __init__(self,channel): > [...] > self.msgLength = 0 > self.recvData = '' # temporary buffer > > def handle_read(self): > self.recvData += self.recv(8192) > if not self.msgLength: > if len(self.recvData) < 5: # 1st 5 bytes = msg length > return > self.msgLength = int(self.recvData[:5]) > self.recvData = self.recvData[5:] > if len(self.recvData) < self.msgLength: > return > data = loads(self.recvData[:self.msgLength]) > self.recvData = self.recvData[self.msgLength:] > self.msgLength = 0 > [handle data] > > This is how I got it working in asynchat - > > def __init__(self,channel): > [...] > self.recvData = '' # temporary buffer > self.set_terminator(5) > self.gotMsgLength = False > > def collect_incoming_data(self, data): > self.recvData += data > > def found_terminator(self): > if self.gotMsgLength: # what follows is the message > data = loads(self.recvData) > self.set_terminator(5) > self.gotMsgLength = False > [handle data] > else: # what follows is the message length > self.set_terminator(int(self.recvData)) > self.gotMsgLength = True > self.recvData = '' > > It may be slightly neater, but it does not seem worth adding an extra > layer just for that. Does asynchat give me any other benefits I may > have overlooked?
The benefit of asynchat is that it automatically handles the buffering of both input and output. Aside from set/found_terminator() the other two methods you could want to look at are push() and push_with_producer(). push() is a buffered version of asyncore.send(), push_with_producer() accepts a data-producer object you can use in case you want to deal with something other than strings (e.g. files, lists, generators, and so on...). > My second question relates to writing a dummy client program to test > the server. I just want to send it some messages and print the > responses. Some messages incorporate data extracted from previous > responses, so I have to wait for the reply before continuing. > > I am using asyncore for this as well. However, the only way I can > think of to get it working is to run asyncore.dispatcher in a separate > thread. > > To send messages, I append them to a list of messages to be sent. The > dispatcher method writable() returns True if there is anything in the > list, else False. > > To receive messages, I run a 'while 1' loop in the main thread, with a > sleep of 0.1, until recvData has something in it. > > It works, but it seems odd to use a separate thread, as one of the > points of asyncore is to avoid multi-threading. Is there a better way > to write the client program? I'm not sure to understand but I doubt you have to use a thread. If you "have to wait for the reply before continuing" just implement this logic into handle_read() or found_terminator() method. --- Giampaolo http://code.google.com/p/pyftpdlib/ -- http://mail.python.org/mailman/listinfo/python-list