static void client_server_closes() {
    final TCPClientLoop client_loop = new TCPClientLoop();
                        client_loop.start();
    
    Callback.TCPClient client = new Callback.TCPClient() {

      public void onConnect (TCPClientLoop l, SocketChannel sc) {
        assert(l == client_loop);
        byte [] bytes = new byte[NUM2];
        bytes[0] = 0x02;

        numWritten = 0;
        client_loop.write(sc, this, bytes);
      }

      public void onData (TCPClientLoop l, SocketChannel c, ByteBuffer b) {
        assert(l == client_loop);
        fail("client_s_close received data");
      }

      public void onWrite (TCPClientLoop l, SocketChannel sc, ByteBuffer b, int pos, int num) {
        assert(l == client_loop);
        assert(num <= NUM2);
        numWritten += num;
      }

      public void onClose (TCPClientLoop l, SocketChannel c) {
        pass("'server close' onClose");
        l.stopLoop();
        clientShutdown();
      }

      public void onEOF (TCPClientLoop l, SocketChannel sc) {
        pass("'server close' onEOF");
      }

      int errNo = 0;
      public void check (String mes) {
        switch (errNo) {
          case 0:
            if ("Connection reset by peer".equals(mes) || "Broken pipe".equals(mes)) {
              pass("'server close' : "+errNo+" : "+mes);
            } else {
              fail ("'server close' : "+errNo+" : "+mes);
            }
            break;
          case 1:
          case 2:
            if ("Socket is not connected".equals(mes)){
              pass("'server close' : "+errNo+" : "+mes);
            } else {
              fail ("'server close' : "+errNo+" : "+mes);
            }
            break;
          default:
            fail ("'server close' : "+errNo+" : "+mes);
        }
        errNo++;
      }

      public void onError (TCPClientLoop l, SocketChannel sc, Throwable ioe) {
        // behaviour is weird if the server closes socket unexpectantly
        // read will fail and not return -1 (Connection reset)
        // write will fail (broken pipe)
        //
        // socket.closed, connected, shutdown won't indicate the proper state.

        check(ioe.getMessage());

        l.shutdown(sc, this, TCPClientLoop.Shutdown.SHUT_RDWR);
        l.close(sc, this);
      }
    };

    client_loop.createTCPClient(client, "127.0.0.1", PORT);
  }