Java NIO server and Python asyncore client
Question: I have the following java NIO server and further below a python asyncore
client. The server prints "Accepted...\n", however, the client's
handle_connect is never called. Could someone help me with what's wrong with
the server and help me connect to the server with the client?

Java NIO Server:

    
    
    import java.net.InetAddress;
    import java.net.InetSocketAddress;
    import java.nio.channels.SelectionKey;
    import java.nio.channels.ServerSocketChannel;
    import java.nio.channels.SocketChannel;
    import java.nio.channels.SelectableChannel;
    import java.nio.channels.Selector;
    import java.nio.ByteBuffer;
    import java.util.ArrayList;
    import java.util.Iterator;
    import java.util.Set;
    
    class Server
    {
        public Selector sel;
        public ServerSocketChannel ssc;
        public SocketChannel channel;
        public static void main(String[] args) throws Exception
        {
            Server s = new Server();
            s.openSocket(12000);
            s.run();
        }
    
        private void openSocket(int port) throws Exception
        {
            InetSocketAddress address = new InetSocketAddress("0.0.0.0", port);
            ssc = ServerSocketChannel.open();
            ssc.configureBlocking(false);
            ssc.socket().bind(address);
            sel = Selector.open();
            ssc.register(sel, SelectionKey.OP_ACCEPT);
        }
    
        public void run() throws Exception
        {
            while (true)
            {
                sel.select();
                Set<SelectionKey> keys = sel.selectedKeys();
                Iterator<SelectionKey> i = keys.iterator();
                while (i.hasNext())
                {
                    SelectionKey key = (SelectionKey) i.next();
                    i.remove();
                    if (!key.isValid())
                    {
                        continue;
                    }
                    if (key.isAcceptable())
                    {
                        channel = ssc.accept();
                        channel.configureBlocking(false);
                        System.out.println("Accepted...\n");
                        channel.register(sel, SelectionKey.OP_READ);
                    }
                    if (key.isReadable())
                    {
                        if (channel == key.channel())
                        {
                            System.out.println("Readable\n");
                            ByteBuffer buffer = ByteBuffer.wrap(new byte[1024]);
                            int pos = channel.read(buffer);
                            buffer.flip();
                            System.out.println(new String(buffer.array(), 0, pos));
                        }
                    }
                }
            }
        }   
    }
    

Python asyncore client:

    
    
    import socket
    import select
    import asyncore
    
    class Connector(asyncore.dispatcher):
        def __init__(self, host, port):
            asyncore.dispatcher.__init__(self)
            self.buffer = "hi"
            self.create_socket()
            self.connect((host, port))
    
        def handle_connect(self):
            print("[]---><---[]") # not called <------------------
    
        def handle_read(self):
            pass
    
        def writable(self):
            len(self.buffer) > 0
    
        def handle_write(self):
            sent = self.send(self.buffer)
            print("[]--->" + self.buffer[0:sent])
            self.buffer = self.buffer[sent:]
    
        def handle_close(self):
            print("[]...x...[]")
            self.close()
    
    
    connector = Connector("localhost", 12000, Handler())
    asyncore.loop()
    

Python normal working client:

    
    
    # Echo client program
    import socket
    import sys
    
    HOST = 'localhost'    # The remote host
    PORT = 12000              # The same port as used by the server
    s = None
    for res in socket.getaddrinfo(HOST, PORT, socket.AF_UNSPEC, socket.SOCK_STREAM):
        af, socktype, proto, canonname, sa = res
        try:
            s = socket.socket(af, socktype, proto)
            print("socket")
        except OSError as msg:
            s = None
            continue
        try:
            s.connect(sa)
            print("connected")
        except OSError as msg:
            s.close()
            s = None
            continue
        break
    if s is None:
        print('could not open socket')
        sys.exit(1)
    print("Sending")
    s.sendall(bytes("Hey server", "UTF-8"))
    data = s.recv(1024)
    #    s.close()
    print('Received', repr(data))
    

**EDIT** Added isReadable to Java and added working normal python client.


Answer: You made two mistakes in implementing one of the tedious asyncore methods:

    
    
    def writable(self):
        len(self.buffer) > 0
    

This method returns `None` (because you forgot the `return` part of that
statement). The first mistake is that `None` has a false boolean value, so
`Connector` is never considered writeable. The second mistake is that you need
to check for writeability during the attempt to establish the connection.
Since `writable` always returns false, including during the connection
attempt, no progress is ever made to establish the connection.

I recommend checking out [Twisted](http://twistedmatrix.com/) instead. It
doesn't make you implement low-level buffer management yourself and connection
setup code yourself and as a result actually produces more efficient code
that's shorter and easier to write.

asyncore should really be considered a historical artifact and never actually
used.

