当前位置: 首页 > news >正文

【Android】Java NIO(New I/O)的`Selector`类来实现非阻塞的Socket监听

如果你不想使用循环来监听客户端的连接和数据,你可以使用Java NIO(New I/O)的Selector类来实现非阻塞的Socket监听。Selector类提供了一种选择一组已经就绪的通道的机制,这样你就不需要使用循环来等待连接和数据。

以下是使用Selector类的示例代码:

private ServerSocketChannel serverSocketChannel;
private Selector selector;private void startServer() throws IOException {serverSocketChannel = ServerSocketChannel.open();serverSocketChannel.configureBlocking(false);serverSocketChannel.socket().bind(new InetSocketAddress(8888));selector = Selector.open();serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);while (true) {int readyChannels = selector.select();if (readyChannels == 0) {continue;}Set<SelectionKey> selectedKeys = selector.selectedKeys();Iterator<SelectionKey> keyIterator = selectedKeys.iterator();while (keyIterator.hasNext()) {SelectionKey key = keyIterator.next();if (key.isAcceptable()) {handleAcceptableKey(key);} else if (key.isReadable()) {handleReadableKey(key);}keyIterator.remove();}}
}private void handleAcceptableKey(SelectionKey key) throws IOException {ServerSocketChannel serverChannel = (ServerSocketChannel) key.channel();SocketChannel clientChannel = serverChannel.accept();clientChannel.configureBlocking(false);clientChannel.register(selector, SelectionKey.OP_READ);Log.d("Server", "设备已连接");
}private void handleReadableKey(SelectionKey key) throws IOException {SocketChannel channel = (SocketChannel) key.channel();ByteBuffer buffer = ByteBuffer.allocate(1024);int bytesRead = channel.read(buffer);if (bytesRead == -1) {channel.close();Log.d("Server", "设备已断开连接");return;}buffer.flip();byte[] data = new byte[buffer.limit()];buffer.get(data);String receivedData = new String(data);Log.d("Server", "接收到数据:" + receivedData);// 处理接收到的数据// 回复客户端ByteBuffer responseBuffer = ByteBuffer.wrap(("已接收到数据:" + receivedData).getBytes());channel.write(responseBuffer);
}

在上面的代码中,我们首先创建一个ServerSocketChannel对象,并将其配置为非阻塞模式。然后,我们将ServerSocketChannel绑定到指定的端口,并将其注册到Selector中,以便监听客户端连接。

while循环中,我们使用selector.select()方法来选择已经就绪的通道。如果没有就绪的通道,我们可以继续等待。一旦有通道就绪,我们使用selector.selectedKeys()方法获取已选择的键集合,并使用迭代器遍历这些键。

在迭代器循环中,我们根据键的类型判断通道是否可接受连接或可读取数据。如果是可接受连接的通道,我们使用handleAcceptableKey()方法处理。如果是可读取数据的通道,我们使用handleReadableKey()方法处理。

handleAcceptableKey()方法中,我们使用serverChannel.accept()方法来接受客户端连接,并将客户端通道注册到Selector中,以便监听客户端发送的数据。

handleReadableKey()方法中,我们首先读取客户端发送的数据,并将其存储在ByteBuffer中。如果读取到的字节数为-1,表示客户端断开连接,我们关闭通道并在日志中打印出"设备已断开连接"。如果读取到有效的数据,我们可以在代码中处理这些数据,并通过通道向客户端发送回复。

请注意,这只是一个使用Selector的简单示例代码。你需要根据你的实际需求进行适当的修改和优化。

希望这可以解决你的问题!

http://www.lryc.cn/news/255545.html

相关文章:

  • 『亚马逊云科技产品测评』在当前飞速发展的AI人工智能时代云服务技术哪家强?
  • 经典神经网络——ResNet模型论文详解及代码复现
  • OpenCV-Python:DevCloud CodeLab介绍及学习
  • 如何在Linux环境搭建本地SVN服务器并结合cpolar实现公网访问
  • C语言入门课程之课后习题之折半查找法
  • 【CSP】202209-1_如此编码Python实现
  • std::function
  • SQL Server——权限管理
  • 实例解析关于兔鲜登录tab栏切换案例详细讲解!
  • 制作一个RISC-V的操作系统三-编译与链接
  • tmux工具--程序部署在服务器上持久化执行
  • C语言精选——选择题Day39
  • React 笔记 jsx
  • QMenu风格设计qss+阴影
  • temu防窒息警示语贴哪里
  • Maven——坐标和依赖
  • Python中事务的常见用法
  • 蛮力法最大值连续子序问题
  • 多功能智能遥测终端机 5G/4G+北斗多信道 视频采集传输
  • 1.查看表的基本结构,表的详细结构和修改表名
  • Mybatis实用教程之XML实现动态sql
  • 混合App开发实现页面跳转(更新中)
  • 【FPGA】Verilog:BCD 加法器的实现
  • 机器学习第15天:GBDT模型
  • STM32F407-14.3.9-01输出比较模式
  • LeetCode题:174. 地下城游戏
  • CSS、JS文件无法正确加载至页面问题与解决
  • ftp的服务安装配置
  • 原码,补码,反码(极简版)
  • uniapp监听wifi连接状态