java.nio.channels.NotYetConnectedException

问题描述:

服务端已启动,端口9999。
客户端通过Channel方式实现,功能一切正常。
客户端通过Selector+Channel方式实现,程序报错。
哪位兄台遇到过此问题,请赐教
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 demo.nio.SelectorDemo.run(SelectorDemo.java:55)
    at demo.nio.SelectorDemo.main(SelectorDemo.java:24)

服务端代码:

package demo.nio;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;

/**  
 * @ClassName: ServerSocketChannel  
 * @Description: 
 * @author 
 * @date 2018年1月24日 下午9:53:15  
 *    
 */
public class ServerSocketChannelDemo implements Runnable {
    public static void main(String[] args) {
        ServerSocketChannelDemo serverSocketChannelDemo = new ServerSocketChannelDemo();
        serverSocketChannelDemo.run();
    }
    
    public void run() {
        try {
            ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
            serverSocketChannel.socket().bind(new InetSocketAddress(9999));
            serverSocketChannel.configureBlocking(false);
            
            while(true){
                SocketChannel socketChannel = serverSocketChannel.accept();
                if(socketChannel != null){
                    //do something with socketChannel...
                    ByteBuffer buf1 = ByteBuffer.allocate(10000);
                    socketChannel.read(buf1);
                    buf1.flip();
                    if(buf1.hasRemaining())
                        System.out.println(">>>服务端收到数据:"+new String(buf1.array()));
                    buf1.clear();
                    
                    ByteBuffer buf2 = ByteBuffer.allocate(10000);
                    buf2.put("A word from server!".getBytes());
                    buf2.flip();
                    socketChannel.write(buf2);
                    
                    socketChannel.close();
                }else{
                    Thread.sleep(3000);
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

客户端代码(Channel实现):

package demo.nio;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.SocketChannel;

/**  
 * @ClassName: SocketChannelDemo  
 * @Description: 
 * @author 
 * @date 2018年1月11日 下午10:01:40  
 *    
 */
public class SocketChannelDemo implements Runnable{
    public static void main(String[] args) {
        SocketChannelDemo socketChannelDemo = new SocketChannelDemo();
        socketChannelDemo.run();
    }

    public void run() {
        try {
            //通道
            SocketChannel socketChannel = SocketChannel.open();
            socketChannel.connect(new InetSocketAddress("127.0.0.1", 9999));
            while(!socketChannel.finishConnect()){
                wait(1000);
            }
            //缓冲区
            ByteBuffer buf1 = ByteBuffer.allocate(10000);
            buf1.put("A word from client!".getBytes());
            buf1.flip();
            if(buf1.hasRemaining())
                socketChannel.write(buf1);
            buf1.clear();
            
            ByteBuffer buf2 = ByteBuffer.allocate(10000);
            socketChannel.read(buf2);
            if(buf2.hasRemaining())
                System.out.println(">>>客户端接收数据:"+new String(buf2.array()));
            buf2.clear();
            
            socketChannel.close();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

客户端代码(Selector+Channel实现):

package demo.nio;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectableChannel;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Set;
import java.util.Iterator;

/**  
 * @ClassName: SelectorDemo  
 * @Description:  
 * @author 
 * @date 2018年1月12日 下午9:06:21  
 *    
 */
public class SelectorDemo implements Runnable{
    public static void main(String[] args) {
        SelectorDemo selectorDemo = new SelectorDemo();
        selectorDemo.run();
    }

    public void run() {
        try {
            //选择器
            Selector selector = Selector.open();
            //通道
            SocketChannel socketChannel1 = SocketChannel.open();
            socketChannel1.configureBlocking(false);
            SelectionKey key1 = socketChannel1.register(selector, SelectionKey.OP_CONNECT);
            socketChannel1.connect(new InetSocketAddress("127.0.0.1", 9999));
            
            while(true){
                int readyChannels = selector.selectNow();//selectNow()非阻塞,select(timeout)和select()阻塞
                if(readyChannels == 0)
                    continue;
                //selector.wakeup();//第一个线程调用select后,需要执行此方法,阻塞在select上的线程会立马返回。
                Set<?> selectedKeys = selector.selectedKeys();
                Iterator<?> keyIterator = selectedKeys.iterator();
                while(keyIterator.hasNext()){
                    SelectionKey key = (SelectionKey) keyIterator.next();
                    if(key.isAcceptable()){
                        // a connection was accepted by a ServerSocketChannel.
                        ServerSocketChannel socketchannel = (ServerSocketChannel) key.channel();
                    }else if(key.isConnectable()){
                        // a connection was established with a remote server.
                        SocketChannel socketchannel = (SocketChannel) key.channel();
                        ByteBuffer buf1 = ByteBuffer.allocate(10000);
                        buf1.put("A word from client!".getBytes());
                        buf1.flip();
                        socketchannel.write(buf1);
                        buf1.clear();
                        
                        ByteBuffer buf2 = ByteBuffer.allocate(10000);
                        socketchannel.read(buf2);
                        buf2.flip();
                        System.out.println(">>>客户端接收数据:"+new String(buf2.array()));
                        buf2.clear();
                    }else if(key.isReadable()){
                        // a channel is ready for reading.
                        SelectableChannel fileChannel = key.channel();
                    }else if(key.isWritable()){
                        // a channel is ready for writing.
                        SelectableChannel fileChannel = key.channel();
                    }
                    keyIterator.remove();
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
阅读 8.9k
1 个回答
package demo.nio;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectableChannel;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Set;
import java.util.Iterator;

/**  
 * @ClassName: SelectorDemo  
 * @Description:  
 * @author 
 * @date 2018年1月12日 下午9:06:21  
 *    
 */
public class SelectorDemo implements Runnable{
    public static void main(String[] args) {
        SelectorDemo selectorDemo = new SelectorDemo();
        selectorDemo.run();
    }

    public void run() {
        try {
            //选择器
            Selector selector = Selector.open();
            //通道
            SocketChannel socketChannel1 = SocketChannel.open();
            socketChannel1.configureBlocking(false);
            SelectionKey key1 = socketChannel1.register(selector, SelectionKey.OP_CONNECT);
            socketChannel1.connect(new InetSocketAddress("127.0.0.1", 9999));
            
            while(true){
                int readyChannels = selector.selectNow();//selectNow()非阻塞,select(timeout)和select()阻塞
                if(readyChannels == 0)
                    continue;
                //selector.wakeup();//第一个线程调用select后,需要执行此方法,阻塞在select上的线程会立马返回。
                Set<?> selectedKeys = selector.selectedKeys();
                Iterator<?> keyIterator = selectedKeys.iterator();
                while(keyIterator.hasNext()){
                    SelectionKey key = (SelectionKey) keyIterator.next();
                    if(key.isAcceptable()){
                        // a connection was accepted by a ServerSocketChannel.
                        ServerSocketChannel socketchannel = (ServerSocketChannel) key.channel();
                    }else if(key.isConnectable()){
                        // a connection was established with a remote server, false.
                        //Now is Connectable(可连接,但是未必已经连接完成)
                         try {
                           socketchannel.finishConnect();//如果是非阻塞模式,可能要循环询问
                        } catch (Exception e) {}
                        
                        
                        SocketChannel socketchannel = (SocketChannel) key.channel();
                        ByteBuffer buf1 = ByteBuffer.allocate(10000);
                        buf1.put("A word from client!".getBytes());
                        buf1.flip();
                        socketchannel.write(buf1);
                        buf1.clear();
                        
                        ByteBuffer buf2 = ByteBuffer.allocate(10000);
                        socketchannel.read(buf2);
                        buf2.flip();
                        System.out.println(">>>客户端接收数据:"+new String(buf2.array()));
                        buf2.clear();
                    }else if(key.isReadable()){
                        // a channel is ready for reading.
                        SelectableChannel fileChannel = key.channel();
                    }else if(key.isWritable()){
                        // a channel is ready for writing.
                        SelectableChannel fileChannel = key.channel();
                    }
                    keyIterator.remove();
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

题主的英文好像不错,可以点进SocketChannel.finishConnect()方法里面看下注释

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题