title: How to close python asyncio transport?
body: <p>I'm working on a project which uses python asyncio socket server. The problem is that the implementation of the server doesn't call .close() on the transport when the server stops. This seems to leave clients connected and causes crashes in other parts of the code.</p>
  
  <p>Python documents say that transports need to be closed explicitly, but in this project I don't know where I can close them because there is no reference to the transports that are created for each client.
  <a href="https://docs.python.org/3/library/asyncio-dev.html#close-transports-and-event-loops" rel="nofollow">https://docs.python.org/3/library/asyncio-dev.html#close-transports-and-event-loops</a></p>
  
  <p>Here is the code:</p>
  
  <pre><code>"""
  Socket server forwarding request to internal server
  """
  import logging
  try:
      # we prefer to use bundles asyncio version, otherwise fallback to trollius
      import asyncio
  except ImportError:
      import trollius as asyncio
  
  
  from opcua import ua
  from opcua.server.uaprocessor import UaProcessor
  
  logger = logging.getLogger(__name__)
  
  
  class BinaryServer(object):
  
      def __init__(self, internal_server, hostname, port):
          self.logger = logging.getLogger(__name__)
          self.hostname = hostname
          self.port = port
          self.iserver = internal_server
          self.loop = internal_server.loop
          self._server = None
          self._policies = []
  
      def set_policies(self, policies):
          self._policies = policies
  
      def start(self):
  
          class OPCUAProtocol(asyncio.Protocol):
  
              """
              instanciated for every connection
              defined as internal class since it needs access
              to the internal server object
              FIXME: find another solution
              """
  
              iserver = self.iserver
              loop = self.loop
              logger = self.logger
              policies = self._policies
  
              def connection_made(self, transport):
                  self.peername = transport.get_extra_info('peername')
                  self.logger.info('New connection from %s', self.peername)
                  self.transport = transport
                  self.processor = UaProcessor(self.iserver, self.transport)
                  self.processor.set_policies(self.policies)
                  self.data = b""
  
              def connection_lost(self, ex):
                  self.logger.info('Lost connection from %s, %s', self.peername, ex)
                  self.transport.close()
                  self.processor.close()
  
              def data_received(self, data):
                  logger.debug("received %s bytes from socket", len(data))
                  if self.data:
                      data = self.data + data
                      self.data = b""
                  self._process_data(data)
  
              def _process_data(self, data):
                  buf = ua.utils.Buffer(data)
                  while True:
                      try:
                          backup_buf = buf.copy()
                          try:
                              hdr = ua.Header.from_string(buf)
                          except ua.utils.NotEnoughData:
                              logger.info("We did not receive enough data from client, waiting for more")
                              self.data = backup_buf.read(len(backup_buf))
                              return
                          if len(buf) &lt; hdr.body_size:
                              logger.info("We did not receive enough data from client, waiting for more")
                              self.data = backup_buf.read(len(backup_buf))
                              return
                          ret = self.processor.process(hdr, buf)
                          if not ret:
                              logger.info("processor returned False, we close connection from %s", self.peername)
                              self.transport.close()
                              return
                          if len(buf) == 0:
                              return
                      except Exception:
                          logger.exception("Exception raised while parsing message from client, closing")
                          self.transport.close()
                          break
  
          coro = self.loop.create_server(OPCUAProtocol, self.hostname, self.port)
          self._server = self.loop.run_coro_and_wait(coro)
          print('Listening on {}:{}'.format(self.hostname, self.port))
  
      def stop(self):
          self.logger.info("Closing asyncio socket server")
          self.loop.call_soon(self._server.close)
          self.loop.run_coro_and_wait(self._server.wait_closed())
  </code></pre>
  
  <p>As you can see when we call stop() on this server class the asyncio server calls it's close method. However if clients are connected the created transports never get closed.</p>
  
  <p>The project repository is here <a href="https://github.com/FreeOpcUa/python-opcua/" rel="nofollow">https://github.com/FreeOpcUa/python-opcua/</a> , you can take a look at Issue 137.</p>
  
  <p>What is the correct way to close the transport object?</p>