2014-01-22 24 views
3

我有example echo server如何在Python中使用tulip/asyncio创建中继服务器?

import asyncio 

class EchoServer(asyncio.Protocol): 
    def connection_made(self, transport): 
     peername = transport.get_extra_info('peername') 
     print('connection from {}'.format(peername)) 
     self.transport = transport 

    def data_received(self, data): 
     self.transport.write(data) 
     # Client piece goes here 

loop = asyncio.get_event_loop() 
coro = loop.create_server(EchoServer, '127.0.0.1', 8888) 
server = loop.run_until_complete(coro) 
print('serving on {}'.format(server.sockets[0].getsockname())) 

try: 
    loop.run_forever() 
except KeyboardInterrupt: 
    print("exit") 
finally: 
    server.close() 
    loop.close() 

我想要做的就是添加一个客户端片而言,我的评论将连接到一个新的服务器并发送数据关闭该-A-方式。还有的echo client,但我需要一个过程,看起来像这样:

+-----------+ +-----------+ +--------------+ 
    | My Server | | My Client | | Other Server | 
    +-----------+ +-----------+ +--------------+ 
      |    |     | 
===>Get some data   |     | 
      |    |     | 
     Send data ---------->|     | 
      |    |     | 
      |   Send data ----------->| 
      |    |     | 
      |    |    Do Stuff 
      |    |     | 
      |    | <-----------Send Data 
      |    |     | 
      | <--------- Send data    | 
      |    |     | 
<=== Send data   |     | 
      |    |     | 
      |    |     | 
      |    |     | 
      |    |     | 

很显然,我可以做到这一点同步,但我试图使client -> other server位异步的,我真的不搞清楚如何使用asyncio方法在我的服务器部分和客户端部分之间进行通信。

我需要在这里做什么?

回答

11

下面是一个简单的代理,让你可以wget 127.0.0.1:8888,并从谷歌一个HTML响应:

import asyncio 

class Client(asyncio.Protocol): 

    def connection_made(self, transport): 
     self.connected = True 
     # save the transport 
     self.transport = transport 

    def data_received(self, data): 
     # forward data to the server 
     self.server_transport.write(data) 

    def connection_lost(self, *args): 
     self.connected = False 

class Server(asyncio.Protocol): 
    clients = {} 
    def connection_made(self, transport): 
     # save the transport 
     self.transport = transport 

    @asyncio.coroutine 
    def send_data(self, data): 
     # get a client by its peername 
     peername = self.transport.get_extra_info('peername') 
     client = self.clients.get(peername) 
     # create a client if peername is not known or the client disconnect 
     if client is None or not client.connected: 
      protocol, client = yield from loop.create_connection(
       Client, 'google.com', 80) 
      client.server_transport = self.transport 
      self.clients[peername] = client 
     # forward data to the client 
     client.transport.write(data) 

    def data_received(self, data): 
     # use a task so this is executed async 
     asyncio.Task(self.send_data(data)) 

@asyncio.coroutine 
def initialize(loop): 
    # use a coroutine to use yield from and get the async result of 
    # create_server 
    server = yield from loop.create_server(Server, '127.0.0.1', 8888) 

loop = asyncio.get_event_loop() 

# main task to initialize everything 
asyncio.Task(initialize(loop)) 

# run 
loop.run_forever() 
+1

交叉参考件不会出现在这里工作... –

+1

为什么呢?我已经使用过这种引用。任何回溯或有用的错误消息...? – gawel

+1

'在回调函数中的异常<绑定方法_SelectorSocketTransport._read_ready在0x7f1c5d10e198上的>() 回溯函数(最近调用最后一次): 文件“/usr/local/lib/python3.4/asyncio/ events.py“,第38行,在_run中 self._callback(* self._args) 文件”/usr/local/lib/python3.4/asyncio/selector_events.py“,第486行,在_read_ready中 self._protocol .data_received(数据) 文件 “the_test.py”,第9行,在DATA_RECEIVED self.client.transport.write(数据) AttributeError的: '服务器' 对象没有属性 '客户' ' –

相关问题