Frage

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.

War es hilfreich?

Lösung

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 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.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top