Is it OK to send asynchronous notifications from server to client via the same TCP connection?

喜欢而已 提交于 2019-12-11 14:49:21

问题


As far as I understand the basics of the client-server model, generally only client may initiate requests; server responds to them. Now I've run into a system where the server sends asynchronous messages back to the client via the same persistent TCP connection whenever it wants. So, a couple of questions:

  • Is it a right thing to do at all? It seems to really overcomplicate implementation of a client.
  • Are there any nice patterns/methodologies I could use to implement a client for such a system in Python? Changing the server is not an option.

Obviously, the client has to watch both the local request queue (i.e. requests to be sent to the server), and the incoming messages from the server. Launching two threads (Rx and Tx) per connection does not feel right to me. Using select() is a major PITA here. Do I miss something?


回答1:


When dealing with asynchronous io in python I typically use a library such as gevent or eventlet. The objective of these libraries is allow for applications written in a synchronous to be multiplexed by a back-end reactor.

This basic example demonstrates the launching of two green threads/co-routines/fibers to handle either side of the TCP duplex. The send side of the duplex is listening on an asynchronous queue.

This is all performed within a single hardware thread. Both gevent && eventlet have more substantive examples in their documentation that what I have provided below.

If you run nc -l -p 8000 you will see "012" printed out. As soon netcat is exited, this code will be terminated.

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




回答2:


I believe what you are trying to achieve is a bit similar to jsonp. While sending to the client, send through a callback method which you know of, that is existing in client.

like if you are sending "some data xyz", send it like server.send("callback('some data xyz')");. This suggestion is for javascript because it executes the returned code as if it were called through that method., and I believe you can port this theory to python with some difficulty. But I am not sure, though.




回答3:


Yes this is very normal and Server can also send the messages to client after connection is made like in case of telnet server when you initiate a connection it sends you a message for the capability exchange and after that it asks you about your username & password.

You could very well use select() or if I were in your shoes I would have spawned a separate thread to receive the asynchronous messages from the server & would have left the main thread free to do further processing.



来源:https://stackoverflow.com/questions/20774949/is-it-ok-to-send-asynchronous-notifications-from-server-to-client-via-the-same-t

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!