zoukankan      html  css  js  c++  java
  • SocketChannel简述

    前言

    在前面的Channel概述的分类中提到过SocketChannel主要是用来基于TCP通信的通道。这篇文章详细介绍下SocketChannel

    • SocketChannel是什么
    • SocketChannel特点
    • SocketChannel的使用

    SocketChannel

    A selectable channel for stream-oriented connecting sockets.

    以上是Java docs中对于SocketChannel的描述:SocketChannel是一种面向流连接只sockets套接字的可选择通道。从这里可以看出:

    • SocketChannel是用来连接Socket套接字
    • SocketChannel主要用途用来处理网络I/O的通道
    • SocketChannel是基于TCP连接传输
    • SocketChannel实现了可选择通道,可以被多路复用的

    SocketChannel特点

    SocketChannel具有以下的特征:

    1. 对于已经存在的socket不能创建SocketChannel
    2. SocketChannel中提供的open接口创建的Channel并没有进行网络级联,需要使用connect接口连接到指定地址
    3. 未进行连接的SocketChannle执行I/O操作时,会抛出NotYetConnectedException
    4. SocketChannel支持两种I/O模式:阻塞式和非阻塞式
    5. SocketChannel支持异步关闭。如果SocketChannel在一个线程上read阻塞,另一个线程对该SocketChannel调用shutdownInput,则读阻塞的线程将返回-1表示没有读取任何数据;如果SocketChannel在一个线程上write阻塞,另一个线程对该SocketChannel调用shutdownWrite,则写阻塞的线程将抛出AsynchronousCloseException
    6. SocketChannel支持设定参数
    参数名 作用描述
    SO_SNDBUF 套接字发送缓冲区大小
    SO_RCVBUF 套接字接收缓冲区大小
    SO_KEEPALIVE 保活连接
    O_REUSEADDR 复用地址
    SO_LINGER 有数据传输时延缓关闭Channel (只有在非阻塞模式下有用)
    TCP_NODELAY 禁用Nagle算法

    SocketChannel的使用

    1.创建SocketChannel

    方式1.
    SocketChannel socketChannel = SocketChannel.open(new InetSocketAddress("www.baidu.com", 80));
    
    方式2. 
    SocketChannel socketChannel = SocketChannel.open();
    socketChannel.connect(new InetSocketAddress("www.baidu.com", 80));
    

    直接使用有参open api或者使用无参open api,但是在无参open只是创建了一个SocketChannel对象,并没有进行实质的tcp连接。

    2.连接校验

    socketChannel.isOpen();      // 测试SocketChannel是否为open状态
    socketChannel.isConnected();    //测试SocketChannel是否已经被连接
    socketChannel.isConnectionPending();    //测试SocketChannel是否正在进行连接
    socketChannel.finishConnect();    //校验正在进行套接字连接的SocketChannel是否已经完成连接
    

    3.读写模式

    前面提到SocketChannel支持阻塞和非阻塞两种模式:

    socketChannel.configureBlocking(false);
    

    主要是通过以上方法设置SocketChannel的读写模式。false表示非阻塞,true表示阻塞。

    4.读写

    SocketChannel socketChannel = SocketChannel.open(
    new InetSocketAddress("www.baidu.com", 80));
    ByteBuffer byteBuffer = ByteBuffer.allocate(16);
    socketChannel.read(byteBuffer);
    socketChannel.close();
    System.out.println("test end!");
    

    以上为阻塞式读,当执行到read出,线程将阻塞,控制台将无法打印test end!。

    SocketChannel socketChannel = SocketChannel.open(
    new InetSocketAddress("www.baidu.com", 80));
    socketChannel.configureBlocking(false);
    ByteBuffer byteBuffer = ByteBuffer.allocate(16);
    socketChannel.read(byteBuffer);
    socketChannel.close();
    System.out.println("test end!");
    

    以上为非阻塞读,控制台将打印test end!。

    读写都是面向缓冲区,这个读写方式与前文中的FileChannel一样,这里不再赘述。

    5.设置和获取参数

    socketChannel.setOption(StandardSocketOptions.SO_KEEPALIVE, Boolean.TRUE)
        .setOption(StandardSocketOptions.TCP_NODELAY, Boolean.TRUE);
    

    通过setOptions方法可以设置socket套接字的相关参数。

    socketChannel.getOption(StandardSocketOptions.SO_KEEPALIVE)
    socketChannel.getOption(StandardSocketOptions.SO_RCVBUF)
    

    可以通过getOption获取相关参数的值。如默认的接收缓冲区大小是8192byte。

    前面提到SocketChannel还支持多路复用,但是多路复用在后续章节中会介绍到,故此将SocketChannel注册到通道上,多路复用的使用,在接下来文章中会介绍。

  • 相关阅读:
    硬盘参数你都懂吗?(上)-从案例引发的讨论
    Python 面试题(下)
    Python 面试题(上)
    DNS 原理入门
    从硬盘设计思想到RAID改良之道
    (转)短信vs.推送通知vs.电子邮件:app什么时候该用哪种方式来通知用户?
    (转)移动端主动推送消息原理
    (转)OpenFire源码学习之十七:HTTP Service插件
    (转)openfire插件开发(二) 基于web的插件开发
    (转)openfire插件开发(一)
  • 原文地址:https://www.cnblogs.com/lxyit/p/9209407.html
Copyright © 2011-2022 走看看