java的。 NIO。将多个通道连接到一个选择器

时间:2014-07-29 20:05:23

标签: java client-server selector nio channel

我试图了解如何使用一个选择器和多个通道编写最简单的应用程序。

经过不可思议的努力,我能够编写以下代码:

服务器:

private static byte[] data = new byte[255];

    public static void main(String[] args) throws IOException {
        for (int i = 0; i < data.length; i++)
            data[i] = (byte) i;

        ServerSocketChannel server = ServerSocketChannel.open();
        server.configureBlocking(false);

        server.socket().bind(new InetSocketAddress(9000));
        Selector selector = Selector.open();
        server.register(selector, SelectionKey.OP_ACCEPT);

        while (true) {
            selector.select();
            Set readyKeys = selector.selectedKeys();
            Iterator iterator = readyKeys.iterator();
            while (iterator.hasNext()) {
                SelectionKey key = (SelectionKey) iterator.next();
                iterator.remove();
                if (key.isAcceptable()) {
                    SocketChannel client = server.accept();
                    System.out.println("Accepted connection from " + client);
                    client.configureBlocking(false);
                    ByteBuffer source = ByteBuffer.wrap(data);
                    SelectionKey key2 = client.register(selector, SelectionKey.OP_WRITE);
                    key2.attach(source);
                } else if (key.isWritable()) {
                    SocketChannel client = (SocketChannel) key.channel();
                    ByteBuffer output = (ByteBuffer) key.attachment();
                    if (!output.hasRemaining()) {
                        output.rewind();
                    }
                    client.write(output);
                }
                key.channel().close();
            }
        }
    }

客户端(发送者):

public static void main(String[] argv) throws Exception {
        SocketChannel sChannel = SocketChannel.open();
        sChannel.configureBlocking(false);
        sChannel.connect(new InetSocketAddress("localhost", 9000));

        ByteBuffer buf = ByteBuffer.allocateDirect(1024);
        buf.put((byte) 0xFF);

        buf.flip();

        int numBytesWritten = sChannel.write(buf);
    }

我的步骤:

  
      
  1. 运行服务器
  2.   
  3. 运行客户端
  4.   

在服务器控制台中执行此步骤之后,我会看到以下内容:

Accepted connection from java.nio.channels.SocketChannel[connected local=/127.0.0.1:9000 remote=/127.0.0.1:49184]

在客户端控制台中,我看到以下内容:

Exception in thread "main" java.nio.channels.NotYetConnectedException
    at sun.nio.ch.SocketChannelImpl.ensureWriteOpen(SocketChannelImpl.java:269)
    at sun.nio.ch.SocketChannelImpl.write(SocketChannelImpl.java:474)
    at io.nio.SocketSender.main(SocketSender.java:25)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:606)
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:120)

请帮助理解堆栈跟踪的原因。

1 个答案:

答案 0 :(得分:0)

信息很清楚。我会以阻塞模式进行客户端连接:然后它完成或失败。否则你必须使用Selector,选择OP_CONNECT,使用finishConnect(),测试它的返回值等。实际上我会通过客户端使用阻塞模式,我可能根本不会使用NIO。