code: async def zmq_tcp_pipe_end(ctx, side, *, host=None, port=0, serializer: Optional[Serializer]=None, initialize=True):
          
  
          if side == 'a':
              host = host or '*'
              result = ZmqPipeEnd(ctx, zmq.ROUTER, f'tcp://{host}', port=port, bind=True, serializer=serializer)
          elif side == 'b':
              host = host or '127.0.0.1'
              if port == 0:
                  raise ValueError("b side requires port argument")
              result = ZmqPipeEnd(ctx, zmq.DEALER, f'tcp://{host}', port=port, serializer=serializer)
          else:
              raise ValueError("side must be 'a' or 'b'")
  
          if initialize:
              await result.initialize()
          return result
docs: Returns a `ZmqPipeEnd` backed by a TCP connection.
          If both ends of the connection are created on the same thread/task, to avoid a deadlock,
          it's necessary to first create both ends, then initialize `'b'` then `'a'`, such as this:
  
              a = await zmq_tcp_pipe_end(ctx, 'a', port=port, initialize=False)
              b = await zmq_tcp_pipe_end(ctx, 'b', port=a.port)
              await a.initialize()
  
          In that case, prefer `zmq_tcp_pipe` for creating both ends.
  
          Side `'a'` will bind a `ROUTER` socket on the given or a random port (host defaults to `*`);
          side `'b'` will connect a `DEALER` socket to the given port (host defaults to `127.0.0.1`).