Netty学习

SocketChannel 使用open或connect/fin

2021-03-01  本文已影响0人  tracy_668

使用connect效果

首先给出一个通用的服务端代码:

package NonBlocking;

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

public class TestOpenAndConnectServer {
    static ServerSocketChannel serverSocketChannel = null;
    static Selector selector = null;

    public static void main(String[] args) throws IOException {
        serverSocketChannel = ServerSocketChannel.open();
        serverSocketChannel.configureBlocking(false);
        serverSocketChannel.bind(new InetSocketAddress(8888));

        selector = Selector.open();
        serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);

        int result = 0; int i = 1;
        while ((result = selector.select()) > 0) {
            System.out.println(String.format("selector %dth loop, ready event number is %d", i++, result));
            Iterator<SelectionKey> iterator = selector.selectedKeys().iterator();
            while(iterator.hasNext()){
                SelectionKey sk = iterator.next();

                if (sk.isAcceptable()) {
                    ServerSocketChannel ss = (ServerSocketChannel)sk.channel();
                    SocketChannel socketChannel = ss.accept();
                    socketChannel.configureBlocking(false);  //也切换非阻塞
                    socketChannel.register(selector, SelectionKey.OP_READ);  //注册read事件
                    System.out.println("接受到新的客户端连接");
                } else if (sk.isReadable()) {
                    System.out.println("有数据可读");
                }

                iterator.remove();
            }
        }
    }
}

使用connect效果

package NonBlocking;

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;
import java.util.Date;
import java.util.Iterator;
import java.util.Scanner;

public class TestOpenAndConnectClient {
    static SocketChannel socketChannel = null;
    static Selector selector = null;

    public static void main(String[] args) throws IOException {
        socketChannel = SocketChannel.open();
        socketChannel.configureBlocking(false);
        boolean connected = socketChannel.connect(new InetSocketAddress("127.0.0.1",8888));
        System.out.println(connected);
        selector = Selector.open();

        socketChannel.register(selector, SelectionKey.OP_CONNECT);
        int result = 0; int i = 1;
        while((result = selector.select()) > 0) {
            System.out.println(String.format("selector %dth loop, ready event number is %d", i++, result));
            Iterator<SelectionKey> iterator = selector.selectedKeys().iterator();
            while (iterator.hasNext()) {
                SelectionKey sk = iterator.next();

                if (sk.isConnectable()) {
                    SocketChannel sc = (SocketChannel)sk.channel();
                    if (sc.finishConnect()) {
                        System.out.println("与服务端建立连接成功");
                    } else {
                        System.out.println("与服务端建立连接失败");
                    }
                    sc.register(selector, SelectionKey.OP_READ);
                } else if (sk.isReadable()) {
                    System.out.println("有数据可读");
                }

                iterator.remove();
            }
        }
    }
}

在服务端已经运行后,再运行客户端,效果如下:

false
selector 1th loop, ready event number is 1
与服务端建立连接成功

如果服务端没有运行,再运行客户端,效果如下:可见在执行sc.finishConnect()抛出了异常。

false
selector 1th loop, ready event number is 1
Exception in thread "main" java.net.ConnectException: Connection refused: no further information
    at sun.nio.ch.SocketChannelImpl.checkConnect(Native Method)
    at sun.nio.ch.SocketChannelImpl.finishConnect(SocketChannelImpl.java:717)
    at NonBlocking.TestOpenAndConnectClient.main(TestOpenAndConnectClient.java:34)

正如connect的api文档所解释:

If this channel is in non-blocking mode then an invocation of this method initiates a non-blocking connection operation. If the connection is established immediately, as can happen with a local connection, then this method returns true. Otherwise this method returns false and the connection operation must later be completed by invoking the finishConnect method.

一个channel在非阻塞模式下执行connect后,如果连接能马上建立好则返回true,否则完成false。如果返回false,那么只能通过之后调用finishConnect来判断连接是否完成。

finishConnect的api文档:

If the connection operation failed then invoking this method will cause an appropriate IOException to be thrown.


如果连接操作已经失败了,那么将会抛出异常。

If this channel is in non-blocking mode then this method will return false if the connection process is not yet complete.


如果连接操作还未完成好,那么将返回false。

但由于我们是通过Selector来触发事件,所以connect事件到来时,这个连接要么已经成功,要么已经失败(抛出异常的形式告诉我们)。

就算是目标地址不可连接 在connect不会抛异常,只会在fininshConnect抛异常

上一篇 下一篇

猜你喜欢

热点阅读