Hello everyone. I've been working for the past few days on a particular problem that I have been struggling greatly with.
In theory, it should be simple: - I have three files: client.py, serverone.py, servertwo.py - I launch both servers in separate terminal windows - I run client.py which then calls serverone.py, the client waits until it receives the server's response, then client returns control to my terminal. That much I have done successfully, as you can read in more detail on my stackoverflow question I made and answered here: http://stackoverflow.com/questions/25691062/how-do-i-get-my-asyncio-client-to-call-a-socket-server-and-waiting-for-response The problem arises when I want my client to call the serverone.py, which in turn calls servertwo.py and waits for its response, before sending the client back servertwo.py's response (through serverone.py). In the real world, I would use a mixture of both server responses to return the result back to client. I got the code working to the point where client calls serverone.py --> serverone.py calls servertwo.py *BUT* ---> client receives the serverone.py response back and --> returns control *before* servertwo responds back to serverone.py. In some cases, client.py just hangs when I try a different approach. servertwo.py DOES communicate to serverone.py and vice versa, the problem here is synchronization I believe. I've been close to pulling my hair out. Any help or opinions are greatly appreciated. Here is the code, I'll describe the problem in more detail below: *client.py* #!/usr/bin/env python3.4 import asyncio class EchoClient(asyncio.Protocol): message = 'Client Echo' def connection_made(self, transport): self.transport = transport transport.write(self.message.encode()) print('data sent: {}'.format(self.message)) def data_received(self, data): print('data received: {}'.format(data.decode())) def connection_lost(self, exc): print('server closed the connection') asyncio.get_event_loop().stop() loop = asyncio.get_event_loop() coro = loop.create_connection(EchoClient, '127.0.0.1', 8888) result = asyncio.async(coro) asyncio.wait_for(result, 60) loop.run_forever() loop.close() *serverone.py* #!/usr/bin/env python3.4 import asyncio class EchoClient(asyncio.Protocol): message = 'Server One Client Echo' def connection_made(self, transport): self.transport = transport self.data = None transport.write(self.message.encode()) print('client data sent: {}'.format(self.message)) def data_received(self, data): print('client data received: {}'.format(data.decode())) self.data = data.decode() def connection_lost(self, exc): print('client connection finished') #asyncio.get_event_loop().stop() 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): print('server data received: {}'.format(data.decode())) fut = asyncio.async(self.callservertwo()) result = asyncio.wait_for(fut, 60) # "result" is a generator object when it should be the result self.transport.write(str(fut).encode()) self.transport.close() @asyncio.coroutine def callservertwo(self): coro = loop.create_connection( EchoClient, '127.0.0.1', 8889) fut = yield from asyncio.async(coro) return asyncio.wait_for(fut, 60) 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() *servertwo.py* #!/usr/bin/env python3.4 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): print('data received: {}'.format(data.decode())) fut = asyncio.async(self.server_two_says_hello()) asyncio.wait_for(fut, 60) @asyncio.coroutine def server_two_says_hello(self): self.transport.write("Hello - ServerTwo".encode()) # close the socket self.transport.close() loop = asyncio.get_event_loop() coro = loop.create_server(EchoServer, '127.0.0.1', 8889) 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() *Problem:* When I run the code, client.py immediately returns. This is what is returned from serverone.py: data received: Task(<callservertwo>)<PENDING> I've tried yield from's, putting things to @asyncio.coroutine decorated methods, but either it tries to return generators, tasks, or client.py hangs. TL;DR: I need to run client.py and have it print out the string "Hello - ServerTwo" Thanks for reading!
