Python网络客户端,试图响应服务器响应

时间:2011-04-18 11:24:40

标签: python networking tcp

该应用程序是一个WxPython客户端/服务器设置,它有多个客户端连接到服务器并参与双工网络协议。

过去我曾让Twisted与AMP挂钩,但它并没有完全削减它在应用程序中的体系结构,最终没有使事情过于复杂。

因此,对于服务器,我已经设置了ThreadingMixIn的SocketServer。目前我正在处理服务器的缓冲区/命令队列,但这不是问题。

在客户端,我可以完成所有正常的数据发送,由UI中的事件触发,没有太多问题。我目前卡住了试图让客户端听取响应而不阻止整个应用程序。所以我想把它放在一个线程中,但它应该从现在注释掉的部分开始,还是应该完全不同处理,我只是没有看到它?

简而言之:我希望客户端向服务器发送命令并监听任何响应,而不会阻塞/停止整个应用程序。

下面的代码是原型代码,请原谅任何典型错误,例如魔法值和其他硬编码数据,最终代码会有所不同。

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()

2 个答案:

答案 0 :(得分:1)

我认为你错误地认为单线程或多线程方法是否会使你的应用程序或多或少地复杂化。你现在正在努力解决的问题是(例如)扭曲解决方案中的许多问题之一。

人们对Twisted最常见的抱怨是,它让他们以一种他们不习惯的方式奇怪地构造他们的代码。但是,当您使用像wxPython这样的GUI库时,您已经接受了这个约束。 Twisted的事件驱动架构与所有流行的GUI工具包的事件驱动架构完全相同。只要你继续使用wxPython,使用Twisted也不会强迫你做任何 else 你不想做的事情。

另一方面,切换到线程意味着您需要非常小心访问共享数据结构,您将无法有效地进行单元测试,并且出现的许多问题只有在其他人是运行您的应用程序 - 因为它们具有与您不同的核心数,或者它们的网络具有不同的延迟特性,或者导致您的线程代码以您从未体验过的方式运行的任何其他内容。你会非常小心地写一些有用的东西,但这会更困难。

由于您尚未在此处发布任何基于Twisted的代码,因此我无法就如何使事情尽可能简单地提供任何具体建议。但是,我建议您再看一下非线程解决方案。加入twisted-python@twistedmatrix.com邮件列表,跳转到freenode上的#twisted,或发布更多有关它的stackoverflow问题。很多人都渴望提供帮助。 :)

答案 1 :(得分:0)

IMO使用线程的权利。为每个请求启动一个线程,当它完成并有数据时,生成一个wx事件(参见http://wiki.wxpython.org/CustomEventClasses