服务端:
public class NoBlockServer {public static void main(String[] args) throws IOException {
// 1. 获取通道
ServerSocketChannel server = ServerSocketChannel.open();
// 2. 切换成非阻塞模式
server.configureBlocking(false);
// 3. 绑定连贯
server.bind(new InetSocketAddress(6666));
// 4. 获取选择器
Selector selector = Selector.open();
// 4.1 将通道注册到选择器上,指定接管“监听通道”事件
server.register(selector, SelectionKey.OP_ACCEPT);
// 5. 轮训地获取选择器上已“就绪”的事件 ---> 只有 select()>0,阐明已就绪
while (selector.select() > 0) {// 6. 获取以后选择器所有注册的“选择键”(已就绪的监听事件)
Iterator<SelectionKey> iterator = selector.selectedKeys().iterator();
// 7. 获取已“就绪”的事件,(不同的事件做不同的事)
while (iterator.hasNext()) {SelectionKey selectionKey = iterator.next();
// 接管事件就绪
if (selectionKey.isAcceptable()) {
// 8. 获取客户端的链接
SocketChannel client = server.accept();
// 8.1 切换成非阻塞状态
client.configureBlocking(false);
// 8.2 注册到选择器上 --> 拿到客户端的连贯为了读取通道的数据(监听读就绪事件)
client.register(selector, SelectionKey.OP_READ);
} else if (selectionKey.isReadable()) { // 读事件就绪
// 9. 获取以后选择器读就绪状态的通道
SocketChannel client = (SocketChannel) selectionKey.channel();
// 9.1 读取数据
ByteBuffer buffer = ByteBuffer.allocate(1024);
// 9.2 失去文件通道,将客户端传递过去的图片写到本地我的项目下(写模式、没有则创立)
FileChannel outChannel = FileChannel.open(Paths.get("2.png"), StandardOpenOption.WRITE, StandardOpenOption.CREATE);
while (client.read(buffer) > 0) {
// 在读之前都要切换成读模式
buffer.flip();
outChannel.write(buffer);
// 读完切换成写模式,能让管道持续读取文件的数据
buffer.clear();}
}
// 10. 勾销选择键(曾经解决过的事件,就应该勾销掉了)
iterator.remove();}
}
}
}
客户端:
public class NoBlockClient {public static void main(String[] args) throws IOException {
// 1. 获取通道
SocketChannel socketChannel = SocketChannel.open(new InetSocketAddress("127.0.0.1", 6666));
// 1.1 切换成非阻塞模式
socketChannel.configureBlocking(false);
// 1.2 获取选择器
Selector selector = Selector.open();
// 1.3 将通道注册到选择器中,获取服务端返回的数据
socketChannel.register(selector, SelectionKey.OP_READ);
// 2. 发送一张图片给服务端吧
FileChannel fileChannel = FileChannel.open(Paths.get("X:\\Users\\ozc\\Desktop\\ 面试造火箭 \\1.png"), StandardOpenOption.READ);
// 3. 要应用 NIO,有了 Channel,就必然要有 Buffer,Buffer 是与数据打交道的呢
ByteBuffer buffer = ByteBuffer.allocate(1024);
// 4. 读取本地文件(图片),发送到服务器
while (fileChannel.read(buffer) != -1) {
// 在读之前都要切换成读模式
buffer.flip();
socketChannel.write(buffer);
// 读完切换成写模式,能让管道持续读取文件的数据
buffer.clear();}
// 5. 轮训地获取选择器上已“就绪”的事件 ---> 只有 select()>0,阐明已就绪
while (selector.select() > 0) {// 6. 获取以后选择器所有注册的“选择键”(已就绪的监听事件)
Iterator<SelectionKey> iterator = selector.selectedKeys().iterator();
// 7. 获取已“就绪”的事件,(不同的事件做不同的事)
while (iterator.hasNext()) {SelectionKey selectionKey = iterator.next();
// 8. 读事件就绪
if (selectionKey.isReadable()) {
// 8.1 失去对应的通道
SocketChannel channel = (SocketChannel) selectionKey.channel();
ByteBuffer responseBuffer = ByteBuffer.allocate(1024);
// 9. 晓得服务端要返回响应的数据给客户端,客户端在这里接管
int readBytes = channel.read(responseBuffer);
if (readBytes > 0) {
// 切换读模式
responseBuffer.flip();
System.out.println(new String(responseBuffer.array(), 0, readBytes));
}
}
// 10. 勾销选择键(曾经解决过的事件,就应该勾销掉了)
iterator.remove();}
}
}
}
文章以纯面试的角度去解说,所以有很多的细节是未铺垫的。
鉴于很多同学反馈没看懂【对线面试官】系列,根底相干的常识我的确写过文章解说过啦,但有的同学就是不爱去翻。
为了让大家有更好的体验,我把根底文章也找进去(重要的知识点我还整顿过 电子书,比如说像多线程、汇合这种面试必考的早就曾经转成 PDF 格局啦)
我把这些 上传到网盘 ,你们有须要间接下载就好了。做到这份上了, 不会还想白嫖吧 ? 点赞 和转发 又不必钱。
链接:https://pan.baidu.com/s/1pQTuKBYsHLsUR5ORRAnwFg 明码:3wom
欢送关注我的微信公众号【Java3y】来聊聊 Java 面试