关于Python网络编程的设计问题

时间:2010-09-22 19:00:38

标签: python network-programming twisted event-driven-design

我目前正在用Python编写一个项目,它有一个客户端和一个服务器部分。我在网络通信方面遇到麻烦,所以我需要解释一些事情......

客户端主要执行服务器告诉他的操作,并将操作结果发送回服务器。我需要一种在TCP套接字上进行双向通信的方法。

现状

我目前在服务器端使用了LineReceiver的Twisted框架,在客户端使用了普通的Python socket(和ssl)(因为我无法正确实现扭曲PushProducer)。客户端有一个Queue,它填满了应该发送到服务器的数据;子进程不断从队列中提取数据并将其发送到服务器(参见下面的代码)。

如果只有客户端将其结果推送给经理,则此方案效果很好。服务器不可能向客户端发送数据。更准确的是,客户端无法接收服务器发送的数据。

问题

我需要一种从服务器向客户端发送命令的方法。

我考虑过在客户端循环中侦听传入数据,用于从队列中发送数据:

def run(self):
    while True:
        data = self.queue.get()
        logger.debug("Sending: %s", repr(data))
        data = cPickle.dumps(data)
        self.socket.write(data + "\r\n")
        # Here would be a good place to listen on the socket

但是这个解决方案有几个问题

  • SSLSocket.read()方法是阻止方法
  • 如果队列中没有数据,客户端将永远不会收到任何数据

是的,我可以使用Queue.get_nowait()代替Queue.get(),但总而言之,我认为这不是一个好的解决方案。

问题

有没有一种很好的方法来实现Twisted的这个要求?我真的没有那么多的Twisted技能来找到我的方式。我甚至不知道使用LineReceiver是否对这类问题是一个好主意,因为它不能发送任何数据,如果它不从客户端接收数据。只有lineReceived个事件。

Twisted(或者更通用的任何事件驱动的框架)是否能够解决这个问题?我甚至没有在通信方面有真实的事件。如果服务器决定发送数据,它应该能够发送它;不应该有可能在通信方面等待任何事件。

2 个答案:

答案 0 :(得分:2)

“我甚至不知道使用LineReceiver是否对这类问题是一个好主意,因为它不能发送任何数据,如果它没有从客户端接收数据。只有{{ {1}}事件。“

您可以使用lineReceived从任何地方发送数据,而不仅仅是protocol.transport.write

答案 1 :(得分:0)

  

“我需要一种从服务器向客户端发送命令的方法。”

不要这样做。它颠倒了“客户”和“服务器”的通常含义。客户端扮演主动角色并从服务器发送内容或请求内容。

  

Twisted(或更通用的任何事件驱动框架)能够解决这个问题吗?

不应该。你正在颠倒客户端和服务器的角色。

  

如果服务器决定发送数据,它应该能够发送它;

实际上是假的。

服务器受限于等待客户端请求数据。这通常是“客户”和“服务器”的公认含义。


  

“一个用于向客户端发送命令,另一个用于将结果发送到服务器。此解决方案听起来更像是标准的客户端 - 服务器通信吗?”

没有

如果客户端向服务器发送消息并从服务器收到响应,则它将满足更常见的定义。

有时,这种事情被描述为拥有“代理”,它们是 - 每种 - 一种服务器和“控制器”,它是所有这些服务器的单个客户端。

控制器将工作分派给代理。代理是服务器 - 它们在端口上侦听,从控制器接受工作,并且工作。每个代理必须执行两个并发操作(通常通过select API):

  • 监控一个众所周知的套接字,它将从唯一的客户端接收工作。

  • 完成工作(在后台)。

这就是Client-Server通常的含义。

如果每个代理都是服务器,您会发现许多库都会支持这一点。这是每个人都这样做的方式。