Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/317.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 在非协程函数中,如何从Tornado TCP的协程函数中获取返回值?_Python_Tornado - Fatal编程技术网

Python 在非协程函数中,如何从Tornado TCP的协程函数中获取返回值?

Python 在非协程函数中,如何从Tornado TCP的协程函数中获取返回值?,python,tornado,Python,Tornado,我用Tornado TCP编写了3段代码。我遇到了一些困难 我的代码如下: client.py '''tcp client''' from socket import socket, AF_INET, SOCK_STREAM s = socket(AF_INET, SOCK_STREAM) s.connect(('localhost', 20000)) resp = s.recv(8192) print('Response:', resp) s.send(b'Hello\n') s.clos

我用Tornado TCP编写了3段代码。我遇到了一些困难

我的代码如下:

client.py

'''tcp client'''


from socket import socket, AF_INET, SOCK_STREAM
s = socket(AF_INET, SOCK_STREAM)
s.connect(('localhost', 20000))
resp = s.recv(8192)
print('Response:', resp)
s.send(b'Hello\n')
s.close()
'''tcp server'''

#! /usr/bin/env python
#coding=utf-8

from tornado.tcpserver import TCPServer
from tornado.ioloop import IOLoop
from tornado.gen import *

clientDict=dict()        #save infomation of client

class TcpConnection(object):
    def __init__(self,stream,address):
        self._stream=stream
        self._address=address
        self._stream.set_close_callback(self.on_close)

    @coroutine
    def send_messages(self):
        yield self.send_message(b'world \n')
        response = yield self.read_message()

        return response


    def read_message(self):
        return self._stream.read_until(b'\n')

    def send_message(self,data):
        return self._stream.write(data)

    def on_close(self):
        global clientDict
        clientDict.pop(self._address)
        print("the monitored %d has left",self._address)

class MonitorServer(TCPServer):
    @coroutine
    def handle_stream(self,stream,address):
        global clientDict
        print("new connection",address,stream)
        clientDict.setdefault(address, TcpConnection(stream,address))



if __name__=='__main__':
    print('server start .....')
    server=MonitorServer()
    server.listen(20000)
    IOLoop.instance().start()
import time
from threading import Thread
import copy
from server import *

def watchClient():
    '''call the "send" function when a new client connect''

    global clientDict
    print('start watch')
    lastClientList=list()
    while True:
        currentClientList=copy.deepcopy([key for key in clientDict.keys()])
        difference=list(set(currentClientList).difference(set(lastClientList)))

        if len(difference)>0:
            send(difference)
            lastClientList=copy.deepcopy(currentClientList)
            time.sleep(5)
        else:
            time.sleep(5)
            continue

def send(addressList):
    '''send message to a new client and get response'''
    global clientDict
    for address in addressList:
        response=clientDict[address].send_messages()
        print(address," response :",response)

def listen():
    server=MonitorServer()
    server.listen(20000)
    IOLoop.instance().start()


if __name__=='__main__':
    listenThread=Thread(target=listen)
    watchThead=Thread(target=watchClient)
    watchThead.start()
    listenThread.start()
server.py

'''tcp client'''


from socket import socket, AF_INET, SOCK_STREAM
s = socket(AF_INET, SOCK_STREAM)
s.connect(('localhost', 20000))
resp = s.recv(8192)
print('Response:', resp)
s.send(b'Hello\n')
s.close()
'''tcp server'''

#! /usr/bin/env python
#coding=utf-8

from tornado.tcpserver import TCPServer
from tornado.ioloop import IOLoop
from tornado.gen import *

clientDict=dict()        #save infomation of client

class TcpConnection(object):
    def __init__(self,stream,address):
        self._stream=stream
        self._address=address
        self._stream.set_close_callback(self.on_close)

    @coroutine
    def send_messages(self):
        yield self.send_message(b'world \n')
        response = yield self.read_message()

        return response


    def read_message(self):
        return self._stream.read_until(b'\n')

    def send_message(self,data):
        return self._stream.write(data)

    def on_close(self):
        global clientDict
        clientDict.pop(self._address)
        print("the monitored %d has left",self._address)

class MonitorServer(TCPServer):
    @coroutine
    def handle_stream(self,stream,address):
        global clientDict
        print("new connection",address,stream)
        clientDict.setdefault(address, TcpConnection(stream,address))



if __name__=='__main__':
    print('server start .....')
    server=MonitorServer()
    server.listen(20000)
    IOLoop.instance().start()
import time
from threading import Thread
import copy
from server import *

def watchClient():
    '''call the "send" function when a new client connect''

    global clientDict
    print('start watch')
    lastClientList=list()
    while True:
        currentClientList=copy.deepcopy([key for key in clientDict.keys()])
        difference=list(set(currentClientList).difference(set(lastClientList)))

        if len(difference)>0:
            send(difference)
            lastClientList=copy.deepcopy(currentClientList)
            time.sleep(5)
        else:
            time.sleep(5)
            continue

def send(addressList):
    '''send message to a new client and get response'''
    global clientDict
    for address in addressList:
        response=clientDict[address].send_messages()
        print(address," response :",response)

def listen():
    server=MonitorServer()
    server.listen(20000)
    IOLoop.instance().start()


if __name__=='__main__':
    listenThread=Thread(target=listen)
    watchThead=Thread(target=watchClient)
    watchThead.start()
    listenThread.start()
main.py

'''tcp client'''


from socket import socket, AF_INET, SOCK_STREAM
s = socket(AF_INET, SOCK_STREAM)
s.connect(('localhost', 20000))
resp = s.recv(8192)
print('Response:', resp)
s.send(b'Hello\n')
s.close()
'''tcp server'''

#! /usr/bin/env python
#coding=utf-8

from tornado.tcpserver import TCPServer
from tornado.ioloop import IOLoop
from tornado.gen import *

clientDict=dict()        #save infomation of client

class TcpConnection(object):
    def __init__(self,stream,address):
        self._stream=stream
        self._address=address
        self._stream.set_close_callback(self.on_close)

    @coroutine
    def send_messages(self):
        yield self.send_message(b'world \n')
        response = yield self.read_message()

        return response


    def read_message(self):
        return self._stream.read_until(b'\n')

    def send_message(self,data):
        return self._stream.write(data)

    def on_close(self):
        global clientDict
        clientDict.pop(self._address)
        print("the monitored %d has left",self._address)

class MonitorServer(TCPServer):
    @coroutine
    def handle_stream(self,stream,address):
        global clientDict
        print("new connection",address,stream)
        clientDict.setdefault(address, TcpConnection(stream,address))



if __name__=='__main__':
    print('server start .....')
    server=MonitorServer()
    server.listen(20000)
    IOLoop.instance().start()
import time
from threading import Thread
import copy
from server import *

def watchClient():
    '''call the "send" function when a new client connect''

    global clientDict
    print('start watch')
    lastClientList=list()
    while True:
        currentClientList=copy.deepcopy([key for key in clientDict.keys()])
        difference=list(set(currentClientList).difference(set(lastClientList)))

        if len(difference)>0:
            send(difference)
            lastClientList=copy.deepcopy(currentClientList)
            time.sleep(5)
        else:
            time.sleep(5)
            continue

def send(addressList):
    '''send message to a new client and get response'''
    global clientDict
    for address in addressList:
        response=clientDict[address].send_messages()
        print(address," response :",response)

def listen():
    server=MonitorServer()
    server.listen(20000)
    IOLoop.instance().start()


if __name__=='__main__':
    listenThread=Thread(target=listen)
    watchThead=Thread(target=watchClient)
    watchThead.start()
    listenThread.start()
我想在main.py运行时获取“打印信息”-地址,响应:b'hello\n'

但事实上,我得到的“打印信息”是----

('127.0.0.1',41233)响应:
它无法返回b'hello\n'

那么我猜它无法从协同路由函数(@coroutine def send_messages(self))中合理地获得无协同路由函数(def send(addressList))中的响应

如何解决这个问题

顺便说一下,我想知道如何使clientDict成为类MonitorServer的属性,而不是全局属性。
请帮帮我!谢谢。

一般来说,任何称为协同程序的东西都应该是协同程序本身。混合线程和协同程序可能非常棘手;大多数基于协同程序的代码故意不保证线程安全

从不同线程上的非协程函数调用协程的正确方法如下:

def call_coro_from_thread(f, *args, **kwargs):
    q = queue.Queue()
    def wrapper():
        fut = f(*args, **kwargs)
        fut.add_done_callback(q.put)
    IOLoop.instance().add_callback(wrapper)
    fut = q.get()
    return fut.result()

IOLoop.add\u回调
是安全地将控制转移到IOLoop线程所必需的,然后使用队列将结果转移回来。

非常感谢!!!它工作得很好!我可以再问你一个问题吗如何使clientDict成为MonitorServer类的属性,而不是全局属性。