Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
283 views
in Technique[技术] by (71.8m points)

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

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?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...