SocketChannel
1 定义和特点
selectable channel for stream-oriented connecting sockets.
SocketChannel是一种面向流的连接socket套接字的可选择通道。
具有以下特点:
-
SocketChannel是用来连接Socket套接字的;
-
SocketChannel主要用途用来处理网络I/O的通道;
-
SocketChannel是基于TCP连接传输;
-
SocketChannel实现了可选择通道,可以被多路复用的。
ServerSocketChannel的属性:
参数名 | 作用描述 |
---|---|
SO_SNDBUF | 套接字发送缓冲区大小 |
SO_RCVBUF | 套接字接收缓冲区大小 |
SO_KEEPALIVE | 保活连接 |
O_REUSEADDR | 复用地址 |
SO_LINGER | 有数据传输时延缓关闭Channel (只有在非阻塞模式下有用) |
TCP_NODELAY | 禁用Nagle算法 |
2 使用与相关API
SocketChannel 作为网络 IO 通道,具体负责进行读写操作。NIO
把缓冲区的数据写入通道,或者把通道里的数据读到缓冲区。
1.创建SocketChannel
//方式1
SocketChannel socketChannel = SocketChannel.open(new InetSocketAddress("127.0.0.1", 6666));
//方式2
SocketChannel socketChannel = SocketChannel.open();
socketChannel.connect(new InetSocketAddress("127.0.0.1", 6666));
方式1是有参构造,构造的同时进行了tcp连接
方式2是无参构造,先创建SocketChannel对象,再tcp连接到服务器。
2.连接校验
// 测试SocketChannel是否为open状态
socketChannel.isOpen();
//测试SocketChannel是否已经被连接
socketChannel.isConnected();
//测试SocketChannel是否正在进行连接
socketChannel.isConnectionPending();
//校验正在进行套接字连接的SocketChannel是否已经完成连接
socketChannel.finishConnect();
3.读写模式
SocketChannel支持阻塞和非阻塞两种模式:
socketChannel.configureBlocking(false);
主要是通过以上方法设置SocketChannel的读写模式。false表示非阻塞,true表示阻塞。
4.设置和获取属性
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获取相关参数的值。
-
使用注意点:
-
对于已经存在的socket不能创建SocketChannel
-
SocketChannel支持两种I/O模式:阻塞式和非阻塞式
-
SocketChannel支持异步关闭。如果SocketChannel在一个线程上read阻塞,另一个线程对该SocketChannel调用shutdownInput,则读阻塞的线程将返回-1表示没有读取任何数据;如果SocketChannel在一个线程上write阻塞,另一个线程对该SocketChannel调用shutdownWrite,则写阻塞的线程将抛出AsynchronousCloseException。
3 SocketChannel和Socket
Socket(套接字)是对网络中不同主机上的应用进程之间进行双向通信的端点的抽象,Socket对象中封装了连接节点的IP地址、端口、协议等信息,是TCP连接的主要API。
socketChannel 套接字通道类(如DatagramChannel、SocketChannel 和ServerSocketChannel)在被实例化时都会创建一个对等 socket 对象(来自 java.net 的类Socket、ServerSocket 和 DatagramSocket),它们已经被更新以识别通道。Socket和Channel之间可以相互得到。
Socket socket = socketChannel.socket();
SocketChannel socketChannel = socket.getChannel();