Java NIO编程示例

news/2024/9/21 1:02:41

服务端:

package org.example;import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.nio.channels.spi.SelectorProvider;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.Iterator;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;public class NIOServer {static ExecutorService executorService = Executors.newFixedThreadPool(10);public static void main(String[] args) {try {// 打开一个选择器Selector selector = SelectorProvider.provider().openSelector();// 打开一个服务器套接字通道ServerSocketChannel serverChannel = ServerSocketChannel.open();serverChannel.configureBlocking(false);// 绑定到指定端口serverChannel.socket().bind(new InetSocketAddress(8081));// 将服务器通道注册到选择器上,并指定关注的事件为接收连接
            serverChannel.register(selector, SelectionKey.OP_ACCEPT);System.out.println("服务器已启动,监听端口8080...");while (true) {// 选择器等待就绪的通道
                selector.select();// 获取就绪的选键集合Iterator<SelectionKey> keyIterator = selector.selectedKeys().iterator();while (keyIterator.hasNext()) {SelectionKey key = keyIterator.next();keyIterator.remove();// 检查选键的状态并进行相应的处理if (key.isAcceptable()) {handleAccept(key);} else if (key.isReadable()) {processMsg(key);} else if (key.isWritable()) {// 通常这里不会处理写就绪,因为写操作通常由应用逻辑触发} else if (key.isConnectable()) {// 这是客户端连接的情况,对于服务器来说通常不会遇到
                    }}}} catch (IOException e) {e.printStackTrace();System.err.println("服务器发生异常,已关闭。");} finally {executorService.shutdown();}}private static void handleAccept(SelectionKey key) throws IOException {ServerSocketChannel serverChannel = (ServerSocketChannel) key.channel();SocketChannel clientChannel = serverChannel.accept();clientChannel.configureBlocking(false);// 注册到选择器并关注读事件
        clientChannel.register(key.selector(), SelectionKey.OP_READ);System.out.println("接受到新的客户端连接:" + clientChannel.getRemoteAddress());}private static void sendData(SocketChannel socketChannel, String message) {ByteBuffer buffer = ByteBuffer.wrap(message.getBytes());while (buffer.hasRemaining()) {try {socketChannel.write(buffer);} catch (IOException e) {throw new RuntimeException(e);}}}public static void processMsg(SelectionKey key) {SocketChannel clientChannel = (SocketChannel) key.channel();ByteBuffer buffer = ByteBuffer.allocate(2);StringBuilder sb = new StringBuilder();try {while (true) {int bytesRead = clientChannel.read(buffer);if (bytesRead == -1) { // 客户端关闭连接
                    clientChannel.close();break;} else if (bytesRead == 0) { // 消息读取结束break;}buffer.flip();byte[] bytes = new byte[buffer.remaining()];buffer.get(bytes);sb.append(new String(bytes, StandardCharsets.UTF_8));buffer.clear();}if (!clientChannel.isOpen()) return;executorService.submit(() -> {System.out.println("收到消息:" + sb);sendData(clientChannel, "abcdaaaaaaaaaaaaaaabbbbbbbbccccccccccccccccccccccccccccd");});} catch (Exception e) {// 发生读错误,关闭连接并打印错误信息System.err.println("读错误:" + e.getMessage());try {clientChannel.close();} catch (IOException ex) {ex.printStackTrace();}}}
}

客户端:

package org.example;import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SocketChannel;public class NIOClient {public static void main(String[] args) {// 服务器的地址和端口String serverAddress = "localhost";int serverPort = 8081;try {// 打开一个套接字通道SocketChannel socketChannel = SocketChannel.open();// 配置为非阻塞模式socketChannel.configureBlocking(false);// 尝试连接到服务器if (socketChannel.connect(new InetSocketAddress(serverAddress, serverPort))) {// 连接成功,可以直接发送数据(但在非阻塞模式下,这通常不会发生)sendData(socketChannel, "Hello, Server!");} else {// 连接可能需要时间,等待连接完成(在实际应用中,这通常是在一个循环中完成的)while (!socketChannel.finishConnect()) {// 可以在这里执行其他任务,比如更新用户界面等// 但在这个简单的例子中,我们只是空转等待连接完成
                }// 连接完成,发送数据for (int index = 1; index <= 5; index++) {sendData(socketChannel, "Hello, Server!");}}// 读取服务器的响应(在非阻塞模式下,这可能需要多次尝试)StringBuilder sb = new StringBuilder();ByteBuffer buffer = ByteBuffer.allocate(1024);while (socketChannel.read(buffer) <= 0) {// 如果没有数据可读,可以在这里执行其他任务// 但在这个简单的例子中,我们只是空转等待数据到来
            }// 服务器发送过来的所有数据
            buffer.flip();String response = new String(buffer.array(), 0, buffer.limit());sb.append(response);while (socketChannel.read(buffer) > 0) {buffer.flip();response = new String(buffer.array(), 0, buffer.limit());sb.append(response);}System.out.println("Received from server: " + sb);// 关闭连接
            socketChannel.close();} catch (Exception e) {e.printStackTrace();System.err.println("Client failed to connect to server or read response.");}System.out.println("finish");}private static void sendData(SocketChannel socketChannel, String message) throws Exception {ByteBuffer buffer = ByteBuffer.wrap(message.getBytes());while (buffer.hasRemaining()) {socketChannel.write(buffer);}}
}

执行效果:

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.ryyt.cn/news/62786.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈,一经查实,立即删除!

相关文章

基于双闭环PI的SMO无速度控制系统simulink建模与仿真

1.课题概述基于双闭环PI的SMO无速度控制系统simulink建模与仿真,基于双闭环PI的SMO无速度控制系统主要由两个闭环组成:一个是电流环,另一个是速度环。电流环作为内环,主要负责电流的快速跟踪控制;速度环作为外环,负责速度的精确控制。这种双闭环结构可以有效提高系统的动…

基于ACO蚁群优化的UAV最优巡检路线规划算法matlab仿真

1.程序功能描述 基于ACO蚁群优化法的UAV最优巡检路线规划。蚁群优化算法源于对自然界蚂蚁寻找食物路径行为的模拟。在无人机巡检路线规划问题中,无人机被认为是“蚂蚁”,巡检点视为“食物源”,目标是找到一条总距离(或总能耗、总时间等)最短的巡检路线。 2.测试软件…

痞子衡嵌入式:如果i.MXRT离线无法启动,试着分析ROM启动日志

大家好,我是痞子衡,是正经搞技术的痞子。今天痞子衡给大家介绍的是恩智浦i.MXRT系列MCU的ROM启动日志。关于 i.MX RT 启动问题解决的文章,痞子衡写过非常多,其中大部分都是具体到某一类启动设备下的具体问题分析,比较依赖经验,这些经验当然是非常有用的。此外也有一篇 《…

基于A律压缩的PCM脉冲编码调制通信系统simulink建模与仿真

1.算法运行效果图预览 (完整程序运行后无水印) 2.算法运行软件版本 matlab2022a3.部分核心程序 (完整版代码包含详细中文注释和操作步骤视频)4.算法理论概述脉冲编码调制(Pulse Code Modulation, PCM)是一种将模拟信号转换为数字信号的通信技术,广泛应用于电话通信、音频…

室内导航的界面该如何设计

室内导航的界面该如何设计?发点例子你看看

【笔记】机器学习算法在异常网络流量监测中的应用

这段时间在找方向,又看不懂文章,只能先从一些相对简单的综述类看起,顺便学学怎么写摘要相关工作的。机器学习算法在异常网络流量监测中的应用 原文:Detecting Network Anomalies in NetFlow Traffic with Machine Learning Algorithms 原文链接:Detecting Network Anomali…

画5.0

chino 最近摆烂过头了,博客都没有好好更新。 这位想必人尽皆知。