1

私は次のJavaNIOサーバーを持っており、さらにpythonasyncoreクライアントの下にあります。サーバーは「Accepted...\ n」と出力しますが、クライアントのhandle_connectが呼び出されることはありません。誰かがサーバーの何が問題になっているのかを教えてくれ、クライアントを使ってサーバーに接続するのを手伝ってもらえますか?

Java NIOサーバー:

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非同期クライアント:

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の通常動作するクライアント:

# 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))

編集JavaにisReadableを追加し、動作する通常のPythonクライアントを追加しました。

4

1 に答える 1

1

面倒な非同期メソッドの1つを実装する際に、2つの間違いを犯しました。

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

このメソッドは戻ります(そのステートメントNoneの一部を忘れたため)。return最初の間違いは、Noneブール値が誤っているため、Connector書き込み可能とは見なされないことです。2番目の間違いは、接続を確立するときに書き込み可能性を確認する必要があることです。接続の試行中も含めて、常にfalseが返されるためwritable、接続の確立が進行することはありません。

代わりにTwistedをチェックすることをお勧めします。低レベルのバッファ管理を自分で実装したり、接続設定コードを自分で実装したりすることはありません。その結果、実際には、より短く、より簡単に記述できる、より効率的なコードが生成されます。

asyncoreは実際には歴史的なアーティファクトと見なされるべきであり、実際に使用されることはありません。

于 2013-02-05T16:11:07.230 に答える