SocketChannel简述
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具有以下的特征:
对于已经存在的socket不能创建SocketChannel
SocketChannel中提供的open接口创建的Channel并没有进行网络级联,需要使用connect接口连接到指定地址
未进行连接的SocketChannle执行I/O操作时,会抛出
NotYetConnectedException
SocketChannel支持两种I/O模式:阻塞式和非阻塞式
SocketChannel支持异步关闭。如果SocketChannel在一个线程上read阻塞,另一个线程对该SocketChannel调用shutdownInput,则读阻塞的线程将返回-1表示没有读取任何数据;如果SocketChannel在一个线程上write阻塞,另一个线程对该SocketChannel调用shutdownWrite,则写阻塞的线程将抛出
AsynchronousCloseException
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注册到通道上,多路复用的使用,在接下来文章中会介绍。