zoukankan      html  css  js  c++  java
  • NIO Socket

    NIO non-blocking ,Sun官方标榜的特征是:为原始的数据类型提供缓存服务

    Channel 一个新的原始IO抽象

    缓存区Buffer

    一个存储原始数据类型的容器,它的底层就是一个数组,它用4个核心属性对数组进行了封装限制。

    缓冲区的4个核心技术

    capacity limit position mark

    缓冲区可以用两个静态方法创建 wrap allocate

    capacity代表了这个底层数组的长度大小,从1开始

    limit 表示返回一个 index,从0开始,表示从这个index开始,后面的元素都是不可读不可写的。 即如果index=3,那么访问array[3]会返回异常。

    position 表示返回下一个可读可写的index,也是从0开始。

    mark标记,它记录当前position的位置,源码是 this.marl=position

    获取缓冲区剩余空间的大小,remaining() ,源代码是 return limit - position ;

    reset()方法前,标识mark必须不等于-1,它会让position = mark ;

    直接缓存区

    一般而言,在JVM会缓存硬盘的内容,然后再传递给Buffer ;而直接缓存区 就是省去JVM的中间缓存 ,直接把硬盘的内容读取到 Buffer 中。

    isDirect()

    还原缓存区的内容   一般这个方法用在往缓存区写入内容前使用

    clear()  

    {

    position=0; limit=capacity ; mark =-1;

    }

    缩小缓存区,一般用在写完缓存区后,要读取之前调用

    flip()

    {

    limit=position ; position=0 ; mark =-1;

    }

    判断缓存区是否有底层实现数组

    hasArray()

    判断是否还有剩余的元素读取

    hasRemaining { position <limit}

    一般用在重写写入缓存区

    rewind()  

    position=0 ; mark =-1;

    }

    arrayOffset  返回缓存区第一个元素在 底层数组的偏移量,即第一个缓存元素在数组的下标index。

    List.toArray(T[])

    ByteBuffer CharBuffer

    slice方法,是创建新的缓存区,不过它还是共用底层数组,它的position是 原来的缓存区的limit 的下标

    使用ByteBuffer CharBuffer处理中文输入

    ByteBuffer默认使用的是utf8,CharBuffer使用的是utf-16BE

    如果读取中文的时候,使用的编码格式是utf8,或者GBK,那么就需要经过特殊的转换。

      使用获取 字节数组 getBytes("utf-16BE")  ; 用byteBuffer.asCharBuffer() 将UTF-16BE的ByteBuffer对象转换成CharBuffer对象

      使用Charset.forName("UTF-8").decode(bytebuffer)

    order() 定义CPU读取字符的顺序,默认是从高位读取,但是有的CPU可能会从地位读取。

    通道Channel

      传输 数据 的 通路。

    Channel接口  它的父接口是 Closeable接口,而Closeable接口 的父接口是 AutoCloseable接口

    AutoCloseable接口的close方法,具有自动关闭资源的功能,强调在try块中使用。

    而 Closeable接口重写的close方法,具有幂等性,用于关闭I/O流。

    AsynchronousChannel子接口

    具有异步I/O操作,它的方法是operation , 这个方法具有两个重载,能与异步的线程进行交流,返回值是 Future接口

    NetworkChannel 接口,主要用于和Socket交互

    AbstractInterruptibleChannel 接口,是提供一个可以被中断的通道实现类

    FileChannel 类

    该个通道永远是阻塞的。

    它在内部一个当前文件的position,可以对其进行查询和修改,该个文件本身包含一个可读,可写的字节序列

    不太常用的方法

    truncate(long size )  通道的文件截取给定大小,如果文件的大小大于 size ,那么丢弃 多余的。

    transferTo() transferFrom()

    FileLock  lock(long position , long size , boolean shared )

    共享锁,只能进行读操作;独占锁,自己能进行读写操作。

    force(boolean meta) 强制所有对此通道的文件更新重新写入包含该文件的存储设备,如果传入值是true ,那么对文件内容和元数据进行更新。

    MappedByteBuffer map(FileChannel.MapMode mode ,long position , long size )

    将文件区域直接映射到内存。

    open 打开一个文件

    ioOpen

    获取网络设备信息

    NetworkInterface 类 表示一个有名称和分配给这个接口的IP列表的网络接口

    getName

    getDisplayName

    getIndex

    isUp  网卡是否开启

    isLoopback  回调/回环接口 ,它是一个虚拟的,永远工作的虚拟接口

    getMTU

    获取子接口

    getSubInterfaces

    isVirtural

    getParent

    getHardwareAddress 硬件地址

    getInetAddress 获取IP地址

    InetAddress类的方法

    getCanonicalHostName 

    getHostName

    getHostAddress

    getAddress 

    getLocalHost 返回主机的IP 如果有多个,返回第一个IP

    getAllByName 通过名字放回主机IP

    InetAddress  getByName(host )

    InterfaceAddress 类 可以获取网络接口的IP,子网掩码,广播地址等信息,对于IP6还能得到网络前缀

    判断设备是否为点对点设备,支持多播等方法

    基于TCP的 Socket通信

    ServerSocket类 

    accept 方法具有阻塞性

    三次握手的 时机 创建ServerSocket 对象,并且绑定指定的端口和IP地址

    ServerSocket类的使用

    设置超时时间 setSoTimeout(ms)客户端在超时时间之内没有 成果连接,那么会发生异常

    构造函数的 参数 backlog , 接受客户端的连接的个数,默认是50,多余的请求会被忽略

    bind(SocketAddress )  服务端绑定指定的socket地址

    SocketAddress  和 InetAddress  是两个不同的类,前面的类是socket地址,包括了IP地址和端口号,而后面的地址仅有IP地址。

    SocketAddress 的子类是 InetSocketAddress

    获取服务端本地绑定的socket地址 getLocalSocketAddress   getLocalPort

    获取主机名

    getHostName 如果是IP地址创建的,那么它会通过DNS反向查找,返回主机的名字

    getHostString  直接返回主机名或者IP地址

    isUnresolved 如果域名无法解析,那么返回true,解析成功,返回false

    Socket 的ReuseAddress选项

    setReuseAddress() 端口是否允许复用

    在TCP发起关闭请求后,一端进入TIME_WAIT 状态后,等待一段时间才关闭连接,在等待时间内,可以允许端口进行使用。

    Socket 的ReceiveBuffer选项

     ServerSocket接受套接字的SO_RCVBUF选项设置新值, 即服务端的接收缓存区的大小

    Socket类的使用

    bind  绑定本地的套接字

    connect(SocketAddress ) 连接远程服务端的套接字

    getPort获取远程端口

    getLocalPort获取本地接口

    Socket TcpNoDelay选项

    控制是否采用Nagle算法,会将数据压缩到一个大包后,再传输。

    Socket SendBufferSize选项

    设置发生缓存区的大小 SO_SNDBUF

     Socket Linger选项

    控制socket关闭close行为,close后,但是底层套接字可能还没有关闭,因为留在缓存区的数据还没有发生完成。

    Socket OOBinline

    开启这个选项,套接字将接收所以TCP紧急数据,通过输入流接收。

    关闭这个选项,紧急数据将会被丢弃

    Socket KeepAlive选项

    设置true时,如果某个端长时间内没有数据传输,那么就会发送一个ACK探测包,如果没有接收到ACK包,那么这个连接将会被关闭。

    Socket TrafficClass选项

    定性描述TCP连接的传输质量

    UDP

    客户端和服务端使用的是 DatagramSocket类 ,数据发送使用的是DatagramPacket类

    UDP理论上的最大一个包只能传输 2的16次方 -1 =65535字节,但实际上 65535-20-8 =65507字节

    组播 MulticastSocket 

    选择器

    Selector 多路复用选择器

    SelectorKey  register方法后,返回的注册凭借

    SelectableChannel  通道,使用regster方法,向选择器注册

    一个通道可以向多个选择器注册,一个通道对一个选择器多次注册返回的凭借是 一样的。

    一个多路选择器可以 处理1023个通道

    SelectableChannel  是一个抽象类,它的平行类是FileChannel , 它有三个实现子类

    分别是ServerSocketChannel SocketChannel DatagramChannel

    这些子类都是通过静态的open方法创建实例对象

    register(selector, int pos) 返回的是一个SelectorKey 代表该个通道已经向选择器注册了,返回凭证。  服务端的操作是接收,而客户端的可选操作,是可连接,可读,可写。

    可以通过SelectorKey cancel方法显示地取消注册

    新创建的ServerSocketChannel 都是非阻塞的,需要调用configureBlocking(true) 设置成阻塞的。

    非阻塞模式下,accept方法如果没有客户端连接,返回null

    如果accept方法,返回了一个 SocketChannel ,那么需要将它注册到 Selector上,实现多路复用。

    注意:如果要注册到选择器,那么需要将通道设置成非阻塞模式

    判断通道的状态

    isRegister

    isOpen

    blockingLock 获取阻塞锁对象

    supportOptions 返回通道支持的Socket Option 

    isBlocking

    SelectionKey keyFor(selector ) 返回通道向选择器注册的凭证

    validOps 返回一个通道支持的操作集

    SelectorProvider provider() 

    SelectorProvider 用于选择器和可选择通道的服务提供者

    执行connect

    connect(SocketAddress )

    如果通道处于非阻塞模式,发起连接后,随后某个时间点发起连接;如果是阻塞的,那么立即发起连接,如果连接成功返回真,不成功返回假;

    如果连接时立即建立的,说明是阻塞的,返回true,而且连接不成功出现异常

    如果连接不是立即建立但,返回fasle,那么说明是非阻塞模式,随后必须通过 finishConnect 验证

    在非阻塞通道下,read和 write 也具有非阻塞特性

    Selector类

    多路复用选择器

    通过SelectionKey对象 表示通道的注册

    选择器维护了三个集合

    1. 键集,本身不可修改,通过注册方法注册一个通道,就会增加一个元素,通过keys() 方法返回
    2. 已选择键集,首先 先调用select()方法查看 键集代表的通道是否已经做好了 相关操作准备,如果准备好了 通过 selectedKeys() 方法返回一个 就绪键集,就绪键集始终是键集的一个子集
    3. 已取消键集, 表示已被取消 但通道尚未注销的键 的集合,不可直接访问,在select()方法期间,从键集 中 移除 已取消的键

    通过已选择键集,或者迭代器的  remove 方法,可以将键 从已选择器中移出。

    使用cancel方法能将 键 取消,键会被添加到 已取消键集,在下一次select 操作期间,这个已取消键集中的所有键 会从 全部的键集中移出,并注销该个通道。

    select () select(long) selectNow()

     选择器是线程安全的,但是 选择器的键 和 已选择键集不是线程安全的。

    select方法一般是阻塞的,它会返回已经就绪的键集数量

    面对重复消费的问题,一般采用remove方法 将 键 从 已选择键集 中移出。

    唤醒操作

    wakeup

    SelectionKey的使用

    isValid 方法 测试这个键 是否还有用

    选择键包含两个集

    interest

    ready 表示就绪

    isAccptable

    isConnectable

    isReadable

    isWritable

    设置attach 附加

    Pipe.SinkChannel

    Pipe.SourceChannel

    AIO

    AsynchronousFileChannel 是一个读取,写入和操作文件的异步通道

    通过open方法打开一个文件

    异步文件通道在文件没有当前位置,而是将文件位置指定给启动异步操作的每个读取,写入方法

    ComletionHandler 被指定为参数,被调用以消耗I/O操作的结果

    AsynchronousFileChannel.open(path, StandardOpenOption.ENUM)

    使用lock() 方法获取文件锁 , 这个方法有 多个重载 

    Future <FileLock > future =channel.lock()

    FileLock lock=future.lock()

    lock(A attchment , CompletionHandler<Future ,  ? super A > handler>

    CompletionHandler 需要实现两个方法,一个是成功的completed方法,这个方法内需要释放锁;一个是失败的falied方法

  • 相关阅读:
    8.9_java_35
    8.8_java_34
    8.7_java_33
    8.6_java_32
    8.5_java_31
    8.4_java_30
    8.3_java_29
    2020年春季学期《软件工程》教学总结
    json的标准格式
    详解 【Vue】 生命周期
  • 原文地址:https://www.cnblogs.com/lin7155/p/13714975.html
Copyright © 2011-2022 走看看