2017-07-28 70 views
0

我想構建一個聊天演示,但我無法接收服務器端發送的東西,除了第一次啓動,任何人都知道爲什麼? 代碼從https://docs.python.org/3.4/library/asyncio-protocol.html#tcp-echo-client-protocolpython3.5 asyncio協議

Server.py

import asyncio 

class EchoServerClientProtocol(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): 
     message = data.decode() 
     print('Data received: {!r}'.format(message)) 
     print('Send: {!r}'.format(message)) 
     self.transport.write(data) 


loop = asyncio.get_event_loop() 
# Each client connection will create a new protocol instance 
coro = loop.create_server(EchoServerClientProtocol, '127.0.0.1', 8888) 
server = loop.run_until_complete(coro) 

# Serve requests until Ctrl+C is pressed 
print('Serving on {}'.format(server.sockets[0].getsockname())) 
try: 
    loop.run_forever() 
except KeyboardInterrupt: 
    pass 

# Close the server 
server.close() 
loop.run_until_complete(server.wait_closed()) 
loop.close() 

Client.py

class EchoClientProtocol(asyncio.Protocol): 
    def __init__(self, message, loop): 
     self.message = message 
     self.loop = loop 
     self.transport = None 

    def connection_made(self, transport): 
     self.transport = transport 

     transport.write(self.message.encode()) 
     print('Data sent: {!r}'.format(self.message)) 

     # while 1: 
     #  message=input('please input the message:') 
     #  transport.write(message.encode()) 
     #  print('Data sent: {!r}'.format(message)) 

    def data_received(self, data): 
     # print('data_received') 
     print('Data received: {!r}'.format(data.decode())) 
     while 1: 
      message = input('please input the message:') 
      self.transport.write(message.encode()) 
      print('Data sent: {!r}'.format(message)) 

    def connection_lost(self, exc): 
     print('The server closed the connection') 
     print('Stop the event loop') 
     self.loop.stop() 

loop = asyncio.get_event_loop() 
message = 'Hello World!' 
coro = loop.create_connection(lambda: EchoClientProtocol(message, loop), 
           '127.0.0.1', 8888) 
loop.run_until_complete(coro) 
loop.run_forever() 
loop.close() 

結果顯示: 斜面不顯示 '收到的數據: '#####' 像' DEF data_received(self,data)'僅用於onece 任何人都有解決方案嗎? [結果] [1] [1]:https://i.stack.imgur.com/IoqA9.png

回答

0

所創建所謂的從EchoClientProtocol.data_received()阻斷功能。只有當事件循環可以處理它時,每個從服務器傳遞的消息都可以傳遞到EchoClientProtocol.data_received(),但阻止函數可以阻止它。

此代碼從用戶

while 1: # More Pythonic way is While True 
    message = input('please input the message:') 
    self.transport.write(message.encode()) 

獲取消息,並將其發送到服務器,直到這一刻這一切都很好。在下一步中,它會啓動另一個循環,但代碼不會進入事件循環(所以傳入的消息無法處理)。

您可以修改客戶端的代碼是這樣的:當你從服務器接收Hello World!

def data_received(self, data): 
     print('Data received: {!r}'.format(data.decode())) 
     message = input('please input the message:') 
     self.transport.write(message.encode()) 

在客戶端中的data_received首次調用(它的Hello World!connection_made發送)。現在,處理以下內容:

  1. 它打印接收到的信息(在第一次調用它的Hello World!
  2. 從用戶那裏得到新的消息
  3. 它發送到服務器
  4. 該函數返回和控制給予事件循環。
  5. 服務器接收到新郵件併發送回客戶端
  6. 在客戶端調用data_received
  7. 轉到步驟1
+0

我也建議使用'aioconsole'事件循環(和移動它out of data_received to independent,「background」future loop)以異步方式等待用戶輸入。因爲即使使用@Qeek修補程序,通信也是同步的 - 您將無法在輸入中接收數據。 – kwarunek