DatagramChannel和SocketChannel实现了ReadableByteChannel 和 WritableByteChannel接口,而ServerSocketChannel没实现
ServerSocketChannel只负责监听传入的连接,创建新的SocketChannel,它自身从不传输数据
socket类有Socket,ServerSocket,DatagramSocket
socket和socket通道之间的关系:
1 socket位于java.net包下,socket通道位于java.nio
2 Socket通道被创建的时候都会创建一个对等的Socket实例
3 通道的socket()可以调用socket,socket的getChannel()可以调用通道
4 Socket通道都有对应的Socket对象,但直接定义的Socket对象是没有对应的通道
5 Socket通道委派协议操作给对应的Socket对象
要把一个Socket通道置为非阻塞模式,就要依靠所有Socket通道类的父类SelectableChannel
ServerSocketChannel是一个基于通道的Socket监听器,因为增加了通道语意,所以可以在非阻塞模式下运行。
ServerSocketChannel没有bind方法,只能通过其对应的ServerSocket来实现
ServerSocketChannel和其对应的ServerSocket都有accept()方法:
ServerSocketChannel.accept() 返回SocketChannel对象,SocketChannel中包含对应的Socket
ServerSocket.accept() 阻塞并返回一个Socket对象
非阻塞模式下,没有连接传入时,ServerSocketChannel.accept()返回null
SocketChannel使用最频繁
Socket,SocketChannel类封装点对点,有序的网络连接,类似于TCP/IP网络连接
Socket是面向流的
SocketChannel扮演客户端发起一个监听服务器的连接,直到连接成功,才能收到数据,并且只从连接到的地址接收
SocketChannel的connect()方法是阻塞式的,同其对应Scoket的connect()方法一样
在非阻塞模式下调用SocketChannel的finishConnect()方法会返回的结果:
1 connect()方法没调用,产生NoConnectionPendingException异常
2 连接正在建立,尚未完成,立即返回false
3 非阻塞模式下调用connect()后,SocketChannel回到阻塞模式,立即返回false
4 连接已建立后,SocketChannel内部状态会更新为已连接状态,finishConnect()方法会返回true,SocketChannel就可以开始传输数据了
DatagramChannel对应DatagramSocket对象,模拟包导向的无连接协议UDP/IP
DatagramSocket
每个数据报Datagram都包含自己的地址
DatagramChannel可以发送Datagram到不同的地址,同样也可以接收不同地址的Datagram
基于包的吞吐量比基于流的高很多,因为互联网基础设施就是包导向的
TCP这样面向流的协议会产生巨大的开销,并且不能适用所有的情形
选择DatagramSocket而不是流Socket的前提:
1 程序可以承受数据丢失和无序数据
2 发送后不需要知道对方是否已经接收,即fire and forget
3 数据吞吐量比可靠性更重要
4 同时发送数据给多个接收者
5 包导向更适合现在的任务