title: Python - non-blocking sockets using selectors
body: <p>My Problem in short:
  I dont know how the selector knows which socket should read or write first.</p>
  
  <p>It is a Server that can handle multi connections and its flow should be:</p>
  
  <ol>
  <li>Server creates listening socket </li>
  <li>Client creates 2 sockets and connects them to the server</li>
  <li>Client 2 sockets send the messages</li>
  <li>Server 2 sockets echo those messages, client and server closing
  connection</li>
  </ol>
  
  <p>which is what happens, but if the created server sockets would write first, the connection would be closed immediately or throw an exception(?), since it doesn't even call send and the client socket would recv nothing. So how does the selector know which sockets should be ready to write/read first? Which information do i miss to understand this?</p>
  
  <p>Server:</p>
  
  <pre><code>import socket
  import selectors
  import types
  
  host = "127.0.0.1"
  port = 63210
  
  def accept_wrapper(sock):
      conn, addr = sock.accept()
      print('accepted connection from', addr)
      conn.setblocking(False)
      data = types.SimpleNamespace(addr=addr, inb=b'', outb=b'')
      events = selectors.EVENT_READ | selectors.EVENT_WRITE
      sel.register(conn, events, data=data)
  
  def service_connection(key, mask):
      sock = key.fileobj
      data = key.data
      if mask &amp; selectors.EVENT_READ:
          recv_data = sock.recv(1024)
          if recv_data:
              data.outb += recv_data
          else:
              print('closing connection to', data.addr)
              sel.unregister(sock)
              sock.close()
      if mask &amp; selectors.EVENT_WRITE:
          if data.outb:
              print('echoing', repr(data.outb), 'to', data.addr)
              sent = sock.send(data.outb)
              data.outb = data.outb[sent:]
  
  sel = selectors.DefaultSelector()
  
  lsock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  lsock.bind((host, port))
  lsock.listen()
  print('listening on', (host, port))
  lsock.setblocking(False)
  sel.register(lsock, selectors.EVENT_READ, data=None)
  
  while True:
      events = sel.select(timeout=None)
      for key, mask in events:
          if key.data is None:
              accept_wrapper(key.fileobj)
          else:
              service_connection(key, mask)
  </code></pre>
  
  <p>Client:</p>
  
  <pre><code>import socket
  import selectors
  import types
  
  host = "127.0.0.1"
  port = 63210
  num_conns = 2
  messages = [b'Message 1 from client.', b'Message 2 from client.']
  
  def start_connections(host, port, num_conns):
      server_addr = (host, port)
      for i in range(0, num_conns):
          connid = i + 1
          print('starting connection', connid, 'to', server_addr)
          sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
          sock.setblocking(False)
          sock.connect_ex(server_addr)
          events = selectors.EVENT_READ | selectors.EVENT_WRITE
          data = types.SimpleNamespace(connid=connid,
                                       msg_total=sum(len(m) for m in messages),
                                       recv_total=0,
                                       messages=list(messages),
                                       outb=b'')
          sel.register(sock, events, data=data)
  
  def service_connection(key, mask):
      sock = key.fileobj
      data = key.data
      if mask &amp; selectors.EVENT_READ:
          recv_data = sock.recv(1024)
          if recv_data:
              print('received', repr(recv_data), 'from connection', data.connid)
              data.recv_total += len(recv_data)
          if not recv_data or data.recv_total == data.msg_total:
              print('closing connection', data.connid)
              sel.unregister(sock)
              sock.close()
      if mask &amp; selectors.EVENT_WRITE:
          if not data.outb and data.messages:
              data.outb = data.messages.pop(0)
          if data.outb:
              print('sending', repr(data.outb), 'to connection', data.connid)
              sent = sock.send(data.outb)
              data.outb = data.outb[sent:]
  
  sel = selectors.DefaultSelector()
  start_connections(host, port, num_conns)
  
  while True:
      events = sel.select(timeout=None)
      for key, mask in events:
          service_connection(key, mask)
  </code></pre>