是否可以通过相同的TCP连接从服务器向客户端发送异步通知?

时间:2013-12-25 16:53:41

标签: python sockets networking tcp client-server

据我了解客户端 - 服务器模型的基础知识,通常只有客户端可以发起请求;服务器响应它们。现在我遇到了一个系统,服务器在需要时通过相同的持久性TCP连接将异步消息发送回客户端。所以,有几个问题:

  • 这样做是否正确?它似乎真的使客户端的实现过于复杂。
  • 我是否可以使用任何好的模式/方法在Python中为这样的系统实现客户端?无法更改服务器。

显然,客户端必须同时观察本地请求队列(即要发送到服务器的请求)以及来自服务器的传入消息。每个连接启动两个线程(Rx和Tx)对我来说感觉不对。在这里使用select()是一个主要的PITA。我想念一下吗?

3 个答案:

答案 0 :(得分:1)

在python中处理异步io时,我通常使用geventeventlet等库。这些库的目标是允许以同步方式编写的应用程序由后端反应器进行多路复用。

这个基本示例演示了如何启动两个绿色线程/协同例程/光纤来处理TCP双工的任一侧。双工的发送端正在侦听异步队列。

这都是在一个硬件线程中执行的。 gevent&& amp; eventlet在他们的文档中有更多实质性的例子,我在下面提供了这些例子。

如果您运行nc -l -p 8000,您会看到打印出“012”。退出netcat后,此代码将被终止。

from eventlet       import connect, sleep, GreenPool
from eventlet.queue import Queue


def handle_i(sock, queue):
    while True:
        data = sock.recv(8)

        if data:
            print(data)
        else:
            queue.put(None) #<- signal send side of duplex to exit
            break

def handle_o(sock, queue):
    while True:
        data = queue.get()

        if data:
            sock.send(data)
        else:
            break

queue = Queue()
sock  = connect(('127.0.0.1', 8000))

gpool = GreenPool()
gpool.spawn(handle_i, sock, queue)
gpool.spawn(handle_o, sock, queue)

for i in range(0, 3):
    queue.put(str(i))
    sleep(1)

gpool.waitall() #<- waits until nc exits

答案 1 :(得分:0)

我相信你想要实现的目标与jsonp有点类似。发送到客户端时,通过您知道的回调方法发送,该方法存在于客户端。

就像发送"some data xyz"一样,请像server.send("callback('some data xyz')");一样发送。这个建议适用于javascript,因为它执行返回的代码就像通过该方法调用它一样。我相信你可以将这个理论移植到python中有一些困难。但是我不确定。

答案 2 :(得分:0)

是的,这是非常正常的,服务器也可以在建立连接之后将消息发送到客户端,就像telnet服务器一样,当您发起连接时,它会向您发送功能交换的消息,之后它会询问您的用户名&安培;密码。

你可以很好地使用select()或者如果我在你的鞋子里,我会产生一个单独的线程来接收来自服务器的异步消息。会让主线程自由地进行进一步的处理。