Java NIO 之 Socket Channel

  在Java NIO中用Channel来对程序与进行I/O操作主体的连接关系进行抽象,这些IO主体包括如文件、Socket或其他设备。简而言之,指代了一种与IO操作对象间的连接关系。

  按照Channel接口的定义,Channel只有open和closed两种状态,只有在channel处于open状态下对其操作时才有效,而对closed的channel进行操作会导致抛出异常。相应的Channel接口也仅有isOpen()和close()两种方法。

  在Socket编程中,常用的Channel类是ServerSocketChannel和SocketChannel。ServerSocketChannel表示作为Socket服务端,处于监听状态的Socket连接。而SocketChannel表示一个已经建立的Socket连接。

  ServerSocketChannel具有accept()方法,当该方法成功返回时,会返回一个已经建立的SocketChannle对象,这也表示了这两种代表不同状态的Socket Channel间的联系和区别。ServerSocketChannel通过bind()方法绑定到本地地址,并且可以通过setOption()方法设置SO_RCVBUF(Socket接收缓冲区大小)和SO_REUSEADDR(是否重用Socket地址,由于Socket在关闭时需要经过多个状态的变迁,这个选项通常在需要快速重启的场景下有用)两个Socket选项。

  SocketChannel采用connet()方法建立连接,并且支持非阻塞式建立,在非阻塞状态下连接的最终建立状态通过isConnetionPending()和finishConnect()进行组合判断。SocketChannel同时支持异步关闭,若写线程主动关闭了Channel,则并发的读操作将读取不到内容;若读线程主动关闭了Channel,则并发的写操作将得到AsynchronousCloseException。同样的对SocketChannle可以通过setOption()方法设置若干选项,包括:SO_SNDBUF(发送缓冲区), SO_RCVBUF, SO_KEEPALIVE(是否采用协议栈实现的保活机制,默认为FALSE), SO_REUSEADDR, SO_LINGER(阻塞式连接下的关闭等待时长), TCP_NODELAY(是否禁用Nagle算法)。

  这两个类涉及的相关类图如下图所示:

  可见,ServerSocketChannel和SocketChannel均继承了SelectableChannel以支持与Selector配合实现非阻塞式IO。SocketChannel继承了若干支持读写操作的Channel以支持读写操作。

  另外,Channel的读写需要借助于Buffer,可见在NIO中Buffer是程序中其他对象与Channel交互的中介,通过Buffer和Channel的配合实现对I/O对象的读写操作。

  几个关键的接口定义如下

  

public interface Channel {

	/**
	 * 判断是否开启
	 * @return
	 */
	public boolean isOpen();

	public void close() throws IOException;

}

/**
 * 可中断Channel</p>
 * 1. 可被异步关闭. 若当前线程阻塞于Channel的读写操作,</l>
 * 当另一线程调用close操作后,当前线程会收到一个AsynchronousCloseException</p>
 *
 * 2. 可中断. 若当前线程阻塞于Channel,当其他线程触发interrupt方法时</l>
 * 会导致Channel Close,当前线程收到一个ClosedByInterruptException,
 * 其interrupt状态被设置</p>
 *
 * 3. 若当前线程interrupt状态已被设置,当调用当前Channel的阻塞IO操作时,</l>
 * channel会被close,线程会收到ClosedByInterruptException. </l>
 * 其interrupt状态保持不变.</p>
 *
 * @author luojiahu
 *
 */
public interface InterruptibleChannel extends Channel{

	public void close() throws IOException;

}

/**
 * 可读Byte Channel
 * 可对当前Channel阻塞读. 若有其他线程正对当前Channel进行读操作,</l>
 * 调用read会一直阻塞至其他上一读操作完成。
 *
 * @author luojiahu
 *
 */
public interface ReadableByteChannel extends Channel {

	/**
	 * 从当前Channel中读取内容写入Buffer</l>
	 * 是否能够读入内容,取决于当前Channel的状态.</l>
	 * 如,对于一个非阻塞的Socket Channel,如果当前socket的</l>
	 * 接收缓冲区没有任何内容,则不能写入任何内容到src
	 * @param src
	 * @return
	 * @throws IOException
	 */
	public int read(ByteBuffer src) throws IOException;

}

/**
 * 可写Byte Channel
 * 可对当前Channel阻塞写.</l>
 * @author luojiahu
 *
 */
public interface WritableByteChannel extends Channel {

	/**
	 * 从dst buffer中读取内容写入当前Channel</l>
	 * 是否能够写入内容取决于当前Channel的状态</l>
	 * 如对于非阻塞 Socket Channel,只能写入不大于</l>
	 * 对应写入缓冲区可写大小的内容
	 *
	 * @param dst
	 * @throws IOException
	 */
	public void write(ByteBuffer dst) throws IOException;

}

/**
 * 网络socket channel</l>
 * @author luojiahu
 *
 */
public interface NetWorkChannel extends Channel{

	/**
	 * 绑定到本地地址</l>
	 * 一旦绑定,则绑定直至通道关闭</l>
	 * 如果参数未空,则绑定至自动分配的地址
	 * @param local
	 * @return
	 * @throws IOException
	 */
	NetWorkChannel bind(SocketAddress local) throws IOException;

	/**
	 * 获取绑定的本地地址
	 * @return
	 * @throws IOException
	 */
	SocketAddress getLocalAddress() throws IOException;

	/**
	 * 设定socket 选项
	 * @param name
	 * @param value
	 * @return
	 * @throws IOException
	 */
	<T> NetworkChannel setOption(SocketOption<T> name, T value) throws IOException;

}

  

原文地址:https://www.cnblogs.com/luojiahu/p/8413780.html

时间: 2025-01-13 01:59:58

Java NIO 之 Socket Channel的相关文章

5. 彤哥说netty系列之Java NIO核心组件之Channel

你好,我是彤哥,本篇是netty系列的第五篇. 简介 上一章我们一起学习了如何使用Java原生NIO实现群聊系统,这章我们一起来看看Java NIO的核心组件之一--Channel. 思维转变 首先,我想说的最重要的一个点是,学习NIO思维一定要从BIO那种一个连接一个线程的模式转变成多个连接(Channel)共用一个线程来处理的这种思维. 1个Connection = 1个Socket = 1个Channel,这几个概念可以看作是等价的,都表示一个连接,只不过是用在不同的场景中. 如果单从阻塞

基于Java NIO的Socket通信

Java NIO模式的Socket通信,是一种同步非阻塞IO设计模式,它为Reactor模式实现提供了基础. 下面看看,Java实现的一个服务端和客户端通信的例子. NIO模式的基本原理描述如下: 服务端打开一个通道(ServerSocketChannel),并向通道中注册一个选择器(Selector),这个选择器是与一些感兴趣的操作的标识(SelectionKey,即通过这个标识可以定位到具体的操作,从而进行响应的处理)相关联的,然后基于选择器(Selector)轮询通道(ServerSock

Java NIO系列(三) - Channel

前言 上文讲到Java NIO一些基本概念.在标准的IO中,都是基于字节流/字符流进行数据操作的,而在NIO中则是是基于Channel和Buffer进行操作,其中的Channel的虽然模拟了流的概念,实则大不相同. 本文将详细阐述NIO中的通道Channel的概念和具体的用法. Channel和Stream的区别 区别 Stream Channel 是否支持异步 不支持 支持 是否支持双向数据传输 不支持,只能单向 支持,既可以从通道读取数据,也可以向通道写入数据 是否结合Buffer使用 不

Java NIO之通道Channel

channel与流的区别: 流基于字节,且读写为单向的. 通道基于快Buffer,可以异步读写.除了FileChannel之外都是双向的.   channel的主要实现: FileChannel DatagramChannel:UDP读写 SocketChannel:TCP读写 ServerSocketChannel 支持scatter/gather(分散和聚集) 分散(scatter)从Channel中读取是指在读操作时将读取的数据写入多个buffer中.因此,Channel将从Channel

Java NIO中的Channel接口

Channel  通道,可以将指定文件的部分或全部直接映射成Buffer. 不能直接读写Channel中的数据,Channel只能与ByteBuffer交互. 读数据时,把Channel中的数据映射到ByteBuffer中取出数据使用. 写数据时,把数据放到Buffer中,再把ByteBuffer中的数据写到Channel中. Channel是一个接口,常用的实现类有: FileChannel    用于文件读写 DatagramChannel    用于UDP通信的Channel Server

JAVA NIO 之Channel

缓冲区本质上是一块可以写入数据,然后可以从中读取数据的内存.Channel 通道就是将数据传输给 ByteBuffer 对象或者从 ByteBuffer 对象获取数据进行传输. Channel 用于在字节缓冲区和位于通道另一侧的实体(通常是一个文件或套接字)之间有效地传输数据.常用Channel有FileChannel.SocketChannel.DatagramChannel.ServerSocketChannelSocket 可以通过socket 通道的工厂方法直接创建.但是FileChan

学习 java netty (一) -- java nio

前言:最近在研究java netty这个网络框架,第一篇先介绍java的nio. java nio在jdk1.4引入,其实也算比较早的了,主要引入非阻塞io和io多路复用.内部基于reactor模式. nio核心: - buffer - channel - selector buffer: 类似网络编程中的缓冲区,有 ByteBuffer 字节 CharBuffer 字符 IntBuffer DoubleBuffer- 常用的有ByteBuffer和CharBuffer java nio buf

Java多线程:Linux多路复用,Java NIO与Netty简述

JVM的多路复用器实现原理 Linux 2.5以前:select/poll Linux 2.6以后: epoll Windows: IOCP Free BSD, OS X: kqueue 下面仅讲解Linux的多路复用. Linux中的IO Linux的IO将所有外部设备都看作文件来操作,与外部设备的操作都可以看做文件操作,其读写都使用内核提供的系统调用,内核会返回一个文件描述符(fd, file descriptor),例如socket读写使用socketfd.描述符是一个索引,指向内核中一个

6. 彤哥说netty系列之Java NIO核心组件之Buffer

--日拱一卒,不期而至! 你好,我是彤哥,本篇是netty系列的第六篇. 简介 上一章我们一起学习了Java NIO的核心组件Channel,它可以看作是实体与实体之间的连接,而且需要与Buffer交互,这一章我们就来学习一下Buffer的特性. 概念 Buffer用于与Channel交互时使用,通过上一章的学习我们知道,数据从Channel读取到Buffer,或者从Buffer写入Channel. Buffer本质上是一个内存块,可以向里面写入数据,或者从里面读取数据,在Java中它被包装成了