2017-07-28 3 views
0

Je veux construire une démo de chat, mais je ne peux pas recevoir les choses côté serveur envoyées, en plus de la première fois pour commencer, quelqu'un sait pourquoi? Code de https://docs.python.org/3.4/library/asyncio-protocol.html#tcp-echo-client-protocolpython3.5 asyncio Protocole

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() 

résultat show: ne peux pas montrer pas 'Les données reçues: '#####' comme' def data_received (self, data) 'est seulement utilisé onece quelqu'un at-il une solution? [résultat] [1] [1]: https://i.stack.imgur.com/IoqA9.png

Répondre

0

Vous avez créé ce qu'on appelle la fonction de blocage de EchoClientProtocol.data_received(). Chaque message délivré par le serveur peut être remis au EchoClientProtocol.data_received() uniquement lorsque la boucle d'événement peut le traiter mais que la fonction de blocage l'empêche.

Ce code

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

message get de l'utilisateur et l'envoyer au serveur, jusqu'à ce moment, il est tout beau. À l'étape suivante, il commence une autre boucle, mais le code ne pénètre jamais dans la boucle d'événements (le message entrant ne peut donc pas être traité).

Vous pouvez modifier le code client comme ceci:

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

Le data_received dans le client est d'abord appelé lorsque vous avez reçu Hello World! du serveur (il est le Hello World! envoie de connection_made). Maintenant, le traitement est le suivant:

  1. Il imprime un message reçu (dans le premier appel, il est Hello World!)
  2. Obtenir un nouveau message d'un utilisateur
  3. Envoyer au serveur
  4. La fonction retourne et le contrôle est donné à la boucle d'événement.
  5. Le serveur a reçu un nouveau message et le renvoyer au client
  6. La boucle d'événement sur appel client data_received
  7. Passez à l'étape 1
+0

Je recommande également d'utiliser 'aioconsole' (et déplacez sur data_received à une boucle future "background" indépendante) pour attendre l'entrée de l'utilisateur de manière asynchrone. Parce que même avec le correctif @Qeek, la communication est synchrone - vous ne pourrez pas recevoir de données alors que vous êtes dans 'l'entrée'. – kwarunek