• ServerSocketChannel

  • ServerSocketChannel作用?就是专职干什么的?

        1、监听新进来的TCP链接通道,

        2、创建新的SocketChannel

  • ServerSocketChannel 不具备 什么能力

    ServerSocketChannel并不能进行数据传输的能力

  • 如何创建ServerSocketChannel实例

    ServerSocketChannel socketChannel =ServerSocketChannel.open();

    该对象关联了一个未绑定ServerSocket的通道,

  • 为ServerSocketChannel绑定监听端口号

    JDK1.7前,需要调用ServerSocketChannel的socket方法,再调用bind()来进行关联

    JDK1.7后,就可以直接调用ServerSocketChannel的bind()来进行端口绑定了。

  • ServerSocketChannel如何监听新进来的连接

    通过 ServerSocketChannel.accept() 方法监听新进来的连接。

    ServerSocketChannel 默认是 阻塞模式,可以查看JDK源码

    如下,所示:

通过ServerSocketChannel.configureBlocking(true)来设定阻塞模式

 1、在阻塞模式下,

    如果有新的连接进来,那么accept()方法返回的是一个包含新进来的连接的SocketChannel,

        如果没有新的连接,那么accept()方法,就会一直阻塞在这里,直到有的新连接进来

   

 2、在非阻塞模式下ServerSocketChannel. configureBlocking(false)

    如果有连接进来,那么accept()方法返回的是一个包含新进来的连接的SocketChannel

    如果没有新的连接,那么accept()方法会立即返回null

 3、阻塞模式与非阻塞模式的根本区别?

    其实,就是在没有新的连接的情况下,如何处理的?不返回,一直等待的话,就是阻塞;

    如果立即返回的话,就是非阻塞了。

    

  • SocketChannel

  • 创建SocketChannel的方式?

    方式一:在客户端创建

        SocketChannel socketChannel = SocketChannel.open();

    方式二:在服务器端创建

        ServerSocketChannel接受一个连接请求后得到,如

        SocketChannel socketChannel = serverSocketChannel.accept();

  • 将管道中的数据读到缓存里,用的是socketChannel的read方法

        int read = socketChannel.read(sizeBuffer);

  • 将缓存里的数据写到管道中,用的是socketChannel的write方法

        socketChannel.write(sizeBuffer);

 

例子如下:

服务端:

package xingej.channel;import java.io.IOException;import java.net.InetSocketAddress;import java.nio.ByteBuffer;import java.nio.channels.ServerSocketChannel;import java.nio.channels.SocketChannel;public class ServerSocketChannelTest {    public void initChannel() throws IOException {        //服务器端,通过open方法,来创建ServerSocketChannel        //注意,此时,服务器端,还没有进行绑定端口呢        ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();        //设置为非阻塞模式//        serverSocketChannel.configureBlocking(false);        //绑定端口号        //JDK1.7版本之后的写法        serverSocketChannel.bind(new InetSocketAddress(8081));        //JDK1.7版本之前的写法//        serverSocketChannel.socket().bind(new InetSocketAddress(8081));        //创建字节缓存区        //缓存区的大小是1024字节,这个可以自己调试,如改成64,128....        ByteBuffer byteBuffer = ByteBuffer.allocate(1024);        while (true) {            System.out.println("-------服务器端-----开始接收-----客户端的连接---------");            //在服务器端,接收客户端的链接,如果存在客户端的话,就返回一个            //SocketChannel对象            //如果是阻塞模式的话,没有新的链接进来,就会阻塞在这里,否则,往下执行            //如果是非阻塞模式的话,没有新的链接进来,就会立马返回一个null,程序不会阻塞在这里,            //会立马往下进行的            SocketChannel socketChannel = serverSocketChannel.accept();            if (null != socketChannel) {                while (true) {                    //清楚缓存区的数据,可以接收新的数据                    byteBuffer.clear();                    //将管道socketChannel的数据读取到 缓存byteBuffer里                    //readSize 表示 读取的字节数                    int readSize = socketChannel.read(byteBuffer);                    if (readSize == -1) {                        break;                    }                    //再从 字节缓存里,进行其他 业务逻辑操作,\                    // 注意,这里的缓存区使用的字节类型                    // 因此,如果需要其他类型的话,需要进行转换                    System.out.println(new String(byteBuffer.array()));                }            }            try {                Thread.sleep(1000);            } catch (InterruptedException e) {                e.printStackTrace();            }        }    }    public static void main(String[] args) throws IOException {        new ServerSocketChannelTest().initChannel();    }}

 客户端如下:

package xingej.channel;import java.io.IOException;import java.net.InetSocketAddress;import java.nio.ByteBuffer;import java.nio.channels.SocketChannel;public class SocketChannelTest {    public void connectServer() throws IOException{        // 创建一个 SocketChannel对象,        // 请注意,并没有进行 链接服务器端哦        SocketChannel socketChannel = SocketChannel.open();        //开始链接服务器端        socketChannel.connect(new InetSocketAddress("localhost", 8081));        //在客户端创建 字节缓存区        ByteBuffer byteBuffer = ByteBuffer.allocate(1024);        String msg = "\nhello, nio, hello ,spark, hello ,hadoop, flume, mesos, marathon, netty, mina, stream, inputstream, outputstream \n" +                "hello, nio, hello ,spark, hello ,hadoop, flume, mesos, marathon, netty, mina, stream, inputstream, outputstream \n" +                "hello, nio, hello ,spark, hello ,hadoop, flume, mesos, marathon, netty, mina, stream, inputstream, outputstream 北京\n";        //往字节缓存区,添加数据        byteBuffer.put(msg.getBytes());        // 针对是更新limit值,将此值更新为position了,用于接下来的读操作        byteBuffer.flip();        while(byteBuffer.hasRemaining()) {            //将字节缓存里的数据,写到管道中去            socketChannel.write(byteBuffer);        }        socketChannel.close();    }    public static void main(String[] args) throws IOException{        new SocketChannelTest().connectServer();    }}

启动方式:

先启动服务器端,然后再启动客户端