Python networking client, trying to respond to server responses
The application is a WxPython client/server setup that has multiple clients connect to the server and engaging in duplex networking protocol.
I've had Twisted hooked up with AMP in the past, but it did not fully cut it for the architecture in the application without overly complicating things in the end.
So for the server I have got SocketServer with the ThreadingMixIn set up. At the moment I am working on the buffer/command queue for the server, but that's not the issue.
On the client side I can do all the normal sending of data, triggered by events in the UI, without too much problems. I am currently stuck trying to get the client to listen for responses without blocking the entire application. So I want to put this in a thread, but should it start at the part that's now commented out or should it be handled completely different and I am just not seeing it?
In short: I want the client to send commands to the server and listen for any responses without blocking/stalling the entire application.
The code below is prototyping code, please excuse any typical mistakes such as magical values and other hardcoded data, it will be different in the final code.
import socket
import threading
import time
class CommandProxy(object):
def __init__(self, host, port):
self.host = host
self.port = port
def close(self):
if self.connection:
self.connection.close()
def connect(self):
try:
self.connection = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.connection.connect((self.host, self.port))
except socket.error as e:
print "Socket error: {0}".format(e)
def send_command(self, command, *kw):
datalist = ' '.join(kw)
data = command + ' ' + datalist + '\x00'
print 'DATA: {0}'.format(data)
self._write(data)
# while True:
# data = self._read()
# if data == 0:
# break
#
# print "DATA RECEIVED: {0}".format(data)
def _read(self):
data = self.connection.recv(1024)
return data
def _write(self, bytes):
self.connection.sendall(bytes)
if __name__ =开发者_运维知识库= '__main__':
HOST, PORT = 'localhost', 1060
proxy = CommandProxy(HOST, PORT)
proxy.connect()
try:
while True:
proxy.send_command('ID', '1')
time.sleep(2)
except KeyboardInterrupt:
print "Interrupted by user"
except socket.error as e:
print "Socket error: {0}".format(e)
except Exception as e:
print "something went wrong: {0}".format(e)
finally:
proxy.close()
I think you're mistaken about whether a single-threaded or multi-threaded approach will complicate your application more or less. The problem you're wrestling with now is one of the many that (for example) Twisted solves for you out of the box.
The most common complaint people have about Twisted is that it makes them structure their code strangely, in a way they're not used to. However, when you're using a GUI library like wxPython, you have already accepted this constraint. Twisted's event-driven architecture is exactly like the event-driven architecture of all the popular GUI toolkits. As long as you keep using wxPython, also using Twisted isn't going to force you to do anything else you don't want to do.
On the other hand, switching to threads will mean you need to be very careful about access to shared data structures, you won't be able to unit test effectively, and many problems that arise will only do so when someone else is running your application - because they have a different number of cores than you, or their network has different latency characteristics, or any of a number of other things which cause your threaded code to run in ways you never experienced. With extreme care you can still write something that works, but it will be much more difficult.
Since you haven't posted any of your Twisted-based code here, I can't really give any specific advice on how to keep things as simple as possible. However, I recommend that you take another look at a non-threaded solution. Join the twisted-python@twistedmatrix.com mailing list, hop on #twisted on freenode, or post more stackoverflow questions about it. Lots of people will be eager to help. :)
IMO your right with using a thread. Start a thread for every request, and when it's done and have a data, generate a wx event (see http://wiki.wxpython.org/CustomEventClasses)
精彩评论