2014-01-22 25 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的: '服務器' 對象沒有屬性 '客戶' ' –

相關問題