ServerSocketChannel简述

一.前言

前篇文章中了解了SocketChannel:提供了连接到套接字通道,从某种层面而言,NIO中提供了类似于java.net包中对于网络操作的api的功能。既然已经有连接到Socket套接字的通道,可以主动发起连接、传输数据,还缺少接收连接(client端)。不言而喻,还缺少接收连接,接收数据的通道(server端)。这篇文章就主要介绍监听套接字的通道ServerSocketChannel。

二.ServerSocketChannel

A selectable channel for stream-oriented listening sockets.

上述摘自java docs中定义:ServerSocketChannel是面向流的监听socket套接字的可选择性通道。从定义中可以看出以下几点:

  • 具有阻塞和非阻塞两种模式
  • 可以注册到多路复用器上
  • 基于TCP连接
  • 需要绑定到特定端口上

ServerSocketChannel可以被无参的open()方法创建。但是改方法只是创建了一个ServerSocketChannel对象,并没有进行绑定操作,仍需要调用bind()方法进行绑定,使之监听某个套接字。未进行绑定的ServerSocketChannel调用accept(),将会抛出NotYetBoundException异常。

ServerSocketChannel支持的可选参数:

参数名 作用描述
SO_RCVBUF 套接字接收缓冲区大小
SO_REUSEADDR 重新使用地址

ServerSocketChannel支持两种模式:阻塞模式和非阻塞模式。且是线程安全的

三.ServerSocketChannel使用

1.创建ServerSocketChannel
ServerSocketChannel channel = ServerSocketChannel.open();  //创建ServerSocketChannel 
2.绑定到本机网络接口
channel.bind(new InetSocketAddress(8091));  //绑定至8091端口
3.接收连接
SocketChannel socketChannel = channel.accept();

ServerSocketChannel的accept方法返回SocketChannel套接字通道,用于读取请求数据和写入响应数据。
ServerSocketChannel的阻塞和非阻塞体现在这里:

  • 阻塞模式:在调用accept方法后,将阻塞知道有新的socket连接时返回SocketChannel对象,代表新建立的套接字通道。
  • 非阻塞模式:在调用accept方法后,如果无连接建立,则返回null;如果有连接,则返回SocketChannel。

四.简单的client-server

创建简单的server:

public void createServerSocketChannel() throws IOException {
    ServerSocketChannel channel = ServerSocketChannel.open();
    channel.bind(new InetSocketAddress(8091));
    while (true) {
        SocketChannel socketChannel = channel.accept();
        ByteBuffer byteBuffer = ByteBuffer.allocate(16);
        int count = socketChannel.read(byteBuffer);
        while(count != -1) {
            byteBuffer.flip();
             while (byteBuffer.hasRemaining()) {
                 System.out.print((char) byteBuffer.get());
             }
             byteBuffer.clear();
            count = socketChannel.read(byteBuffer);
        }
        System.out.println();
    }
}

创建简单client:

public void client() throws IOException {
    SocketChannel socketChannel = SocketChannel.open(
        new InetSocketAddress("10.17.83.11", 8091));
    String msg = "ok";
    socketChannel.write(ByteBuffer.wrap(msg.getBytes()));

    SocketChannel socketChannel3 = SocketChannel.open(
        new InetSocketAddress(8091));
    socketChannel3.write(ByteBuffer.wrap(msg.getBytes()));
    System.out.println("s3");

    SocketChannel socketChannel4 = SocketChannel.open(
        new InetSocketAddress(8091));
    socketChannel4.write(ByteBuffer.wrap(msg.getBytes()));
    System.out.println("s4");

    socketChannel4.close();
    socketChannel3.close();
    socketChannel.close();
}

ServerSocketChannel基本上不会单独使用绝大多数情况下都是配合多路复用Selector选择器共同使用。这里只关注ServerSocketChannel本身,关于其与多路复用混合使用,后面再介绍Selector时再做详细介绍!

参考

本机ip、127.0.0.1和0.0.0.0区别

扫描二维码关注公众号,回复: 1754255 查看本文章

猜你喜欢

转载自www.cnblogs.com/lxyit/p/9224248.html