先打个小广告,关注辛星教程,我的微信号xinxing0913,该项目源码所在的github地址: https://github.com/xinxing0913/xinxing-nio-guide。
前面我们介绍的操作都是对于本地文件的操作,接下来我们就要进行网络相关的操作了。这里我们经常使用的两个Channel是SocketChannel与ServerSocketChannel。
SocketChannel是用于TCP网络连接的套接字接口,它一般用来作为客户端的套接字,它有点类似于java中的Socket类。我们使用它的一般套路是:
SocketChannel channel = SocketChannel.open();
channel.connect(xxx);
我们可以用它的read方法来读取数据,我们也可以用它的write方法来写入数据,我们可以用它的configureBlocking(false)方法来设置为非阻塞模式。不过需要说明的是,由于真实场景下读取数据可能不是一次性能完成,因此可能需要在一个循环中进行读取。
ServerSocketChannel是用于监听TCP连接的通道,它类似于java网络编程中的ServerSocket,它的一般使用道路是:
ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
serverSocketChannel.bind(xxx);
while (true) {
SocketChannel client = serverSocketChannel.accept();
// 其他操作
client.close();
}
这里我们首先调用它的open方法来打开一个通道,然后我们调用其bind()方法来绑定到某个地址上,然后我们通过accept()方法来每次获取一个客户端的连接,别忘记在操作完客户端之后要关闭。
我们接下来就来编写一个nio的客户端和服务端通信的范例把,首先是client代码的范例:
/**
* 基于nio实现的非阻塞客户端
*/
public class Demo9 {
public static void main(String[] args) throws Exception{
SocketChannel socketChannel = SocketChannel.open();
socketChannel.configureBlocking(false); // 设置为非阻塞
socketChannel.connect(new InetSocketAddress(8080));
socketChannel.finishConnect(); // 等待连接完成
// 向服务端发送一段文本
byte[] bytes = "hello 辛星".getBytes();
ByteBuffer byteBuffer = ByteBuffer.wrap(bytes);
socketChannel.write(byteBuffer);
// 最多只接受服务端的1024个字节
ByteBuffer responseBuffer = ByteBuffer.allocate(1024);
socketChannel.read(responseBuffer);
System.out.println("服务端响应的数据:" + new String(responseBuffer.array()));
}
}
需要特殊说明的是,我们调用了finishConnect()方法来等待连接完成,然后才发的消息,如果连接未完成就发消息的话,可能会抛出NotYetConnectedException异常。
然后我们来编写一个nio的服务端的范例把,如下所示:
/**
* 基于nio实现的非阻塞服务端
*/
public class Demo10 {
private static final byte[] bytes = "received !!".getBytes();
public static void main(String[] args) throws Exception {
ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
serverSocketChannel.bind(new InetSocketAddress(8080));
serverSocketChannel.configureBlocking(false);
System.out.println("服务端已启动,开始接受客户端连接...");
while (true) {
SocketChannel socketChannel = serverSocketChannel.accept();
if (!Objects.isNull(socketChannel)) {
// 最多只接受客户端的1024个字节
ByteBuffer requestBuffer = ByteBuffer.allocate(1024);
socketChannel.read(requestBuffer);
System.out.println("客户端输入的内容:" + new String(requestBuffer.array()));
// 给客户端写入数据,然后关闭连接
// 发送给客户端的文本信息
ByteBuffer responseBuffer = ByteBuffer.wrap(bytes);
socketChannel.write(responseBuffer);
socketChannel.close();
}
}
}
}
然后我们首先启动服务器,我们看到如下所示的效果:
然后我们启动客户端,我们会看到如下效果:
然后我们的服务端就会收到一次处理连接的信息,如下所示:
对于基于TCP的通信操作,我们就介绍到这里啦。