NIO通信代码示例

NIO通信架构图

在这里插入图片描述

1.Client

NioClient

package nio;import constant.Constant;import java.io.IOException;
import java.util.Scanner;public class NioClient {private static NioClientHandle nioClientHandle;public static void start() {nioClientHandle = new NioClientHandle(Constant.DEFAULT_SERVER_IP, Constant.DEFAULT_PORT);new Thread(nioClientHandle, "Client").start();}// 向服务器发送消息public static boolean sendMsg(String msg) throws IOException {nioClientHandle.sendMsg(msg);return true;}public static void main(String[] args) throws IOException {start();Scanner scanner = new Scanner(System.in);while (NioClient.sendMsg(scanner.next()));}
}

NioClientHandle

package nio;import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
import java.util.Set;public class NioClientHandle implements Runnable {private String host;private int port;private volatile boolean started;private Selector selector;private SocketChannel socketChannel;public NioClientHandle(String ip, int port) {this.host = ip;this.port = port;try {// 创建选择器的实例selector = Selector.open();// 创建ServerSocketChannel的实例socketChannel = SocketChannel.open();// 设置通道为非阻塞模式socketChannel.configureBlocking(false);started = true;} catch (Exception e) {e.printStackTrace();}}public void stop() {started = false;}@Overridepublic void run() {try {doConnect();} catch (Exception e) {e.printStackTrace();System.exit(1);}// 循环遍历selectorwhile (started) {try {// 无论是否有读写事件发生,selector每隔1s被唤醒一次selector.select(1000);// 获取当前有哪些事件可以使用Set<SelectionKey> keys = selector.selectedKeys();// 转换为迭代器Iterator<SelectionKey> it = keys.iterator();SelectionKey key = null;while (it.hasNext()) {key = it.next();// 我们必须受限将处理过的SelectionKey从选定的集合中删除// 如果我们没有删除处理过的键,那么它仍然会在主集合中以一个激活的键// 出现,这会导致我们尝试再次处理它it.remove();try {handleInput(key);} catch (Exception e) {if (key != null) {key.cancel();if (key.channel() != null) {key.channel().close();}}}}} catch (Exception e) {e.printStackTrace();System.exit(1);}}// selector关闭后会自动释放里面管理的资源if (selector != null) {try {selector.close();} catch (Exception e) {e.printStackTrace();}}}/*** 具体的事件处理方法* @param key*/private void handleInput(SelectionKey key) throws IOException {if (key.isValid()) {// 获得关心当前事件的channelSocketChannel sc = (SocketChannel)key.channel();// 连接事件if (key.isConnectable()) {if (sc.finishConnect()) {socketChannel.register(selector, SelectionKey.OP_READ);} else {System.exit(1);}}// 有数据可读事件if (key.isReadable()) {// 创建ByteBuffer,并开启一个1M的缓冲区ByteBuffer buffer = ByteBuffer.allocate(1024);// 读取数据码流 返回读取到的字节数int readBytes = sc.read(buffer);// 读取到字节 对字节进行编解码if (readBytes > 0) {//将缓冲区当前的limit设置为position, position = 0;// 用于后续对缓冲区的读取操作buffer.flip();// 根据缓冲区可读字节数创建字节数组byte[] bytes = new byte[buffer.remaining()];// 将缓冲区可读字节数组复制到新建的数组中buffer.get(bytes);String result = new String(bytes, "UTF-8");System.out.println("客户端收到消息:" + result);} else if (readBytes < 0) {key.cancel();sc.close();}}}}public void sendMsg(String msg) throws IOException {doWrite(socketChannel, msg);}private void doWrite(SocketChannel socketChannel, String request) throws IOException {// 将消息编码为字节数组byte[] bytes = request.getBytes();// 根据数组容量创建ByteBufferByteBuffer writeBuffer = ByteBuffer.allocate(bytes.length);// 将字节数组复制到缓冲区writeBuffer.put(bytes);// flip操作writeBuffer.flip();// 发送缓冲区的字节数组// 关心事件和读写网络不冲突socketChannel.write(writeBuffer);}private void doConnect() throws IOException {// 非阻塞的连接if (socketChannel.connect(new InetSocketAddress(host, port))) {socketChannel.register(selector, SelectionKey.OP_READ);} else {socketChannel.register(selector, SelectionKey.OP_CONNECT);}}
}

2.Server

NioServer

package nio;import constant.Constant;public class NioServer {private static NioServerHandle nioServerHandle;public static void main(String[] args) {nioServerHandle = new NioServerHandle(Constant.DEFAULT_PORT);new Thread(nioServerHandle, "Server").start();}
}

NioServerHandle

package nio;import constant.Constant;import java.io.IOException;
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.util.Iterator;
import java.util.Set;public class NioServerHandle implements Runnable {private volatile boolean started;private ServerSocketChannel serverSocketChannel;private Selector selector;public NioServerHandle(int port) {try {// 创建选择器实例selector = Selector.open();// 创建ServerSocketChannel的实例serverSocketChannel = ServerSocketChannel.open();// 设置通道为非阻塞模式serverSocketChannel.configureBlocking(false);// 绑定端口serverSocketChannel.socket().bind(new InetSocketAddress(port));// 注册事件,表示关心客户端连接serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);// started = true;System.out.println("服务器已启动, 端口号为:" + port);} catch (Exception e) {e.printStackTrace();}}@Overridepublic void run() {while (started) {try {// 获取当前有哪些事件selector.select(1000);// 获取事件的集合Set<SelectionKey> selectionKeys = selector.selectedKeys();Iterator<SelectionKey> iterator = selectionKeys.iterator();while (iterator.hasNext()) {SelectionKey key = iterator.next();// 我们必须首先将处理过的SelectionKey 从选定的键集合中删除// 如果我们没有删除处理过的键,那么它仍然会在主集合中以// 一个激活的键出现,这回导致我们尝试再次处理它iterator.remove();handleInput(key);}} catch (Exception e) {}}}/*** 处理事件的发生* @param key*/private void handleInput(SelectionKey key) throws IOException {if (key.isValid()) {// 处理新接入的客户端的请求if (key.isAcceptable()) {// 获取关心当前事件的ChannelServerSocketChannel ssc = (ServerSocketChannel)key.channel();// 接受连接SocketChannel sc = ssc.accept();System.out.println("=========建立连接=========");sc.configureBlocking(false);// 关注读事件sc.register(selector, SelectionKey.OP_READ);}// 处理对端的发送的数据if (key.isReadable()) {SocketChannel sc = (SocketChannel) key.channel();// 创建ByteBuffer, 开辟一个缓冲区ByteBuffer buffer = ByteBuffer.allocate(1024);// 从通道里读取数据,然后写入bufferint readBytes = sc.read(buffer);if (readBytes > 0) {// 将缓冲区当前的limit设置为position, position = 0// 用于后续对缓冲区的读取操作buffer.flip();// 根据缓冲区可读字节数创建字节数组byte[] bytes = new byte[buffer.remaining()];// 将缓冲区可读字节数组复制到新建的数组中buffer.get(bytes);String message = new String(bytes, "UTF-8");System.out.println("服务器收到消息:" + message);// 处理数据String result = Constant.response(message);// 发送应答消息doWrite(sc, result);}}}}private void doWrite(SocketChannel sc, String response) throws IOException {byte[] bytes = response.getBytes();ByteBuffer buffer = ByteBuffer.allocate(bytes.length);buffer.put(bytes);buffer.flip();sc.write(buffer);}
}

3.代码运行实例

先启动server再启动client
在这里插入图片描述
在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

MongoDB快速实战与基本原理

MongoDB 介绍 什么是 MongoDB MongoDB 是一个文档数据库&#xff08;以 JSON 为数据模型&#xff09;&#xff0c;由 C 语言编写&#xff0c;旨在为 WEB 应用提供可扩展的高性能数据存储解决方案。文档来自于“JSON Document”&#xff0c;并非我们一般理解的 PDF、WORD 文档…

【数据采集与预处理】流数据采集工具Flume

目录 一、Flume简介 &#xff08;一&#xff09;Flume定义 &#xff08;二&#xff09;Flume作用 二、Flume组成架构 三、Flume安装配置 &#xff08;一&#xff09;下载Flume &#xff08;二&#xff09;解压安装包 &#xff08;三&#xff09;配置环境变量 &#xf…

python高校舆情分析系统+可视化+情感分析 舆情分析+Flask框架(源码+文档)✅

毕业设计&#xff1a;2023-2024年计算机专业毕业设计选题汇总&#xff08;建议收藏&#xff09; 毕业设计&#xff1a;2023-2024年最新最全计算机专业毕设选题推荐汇总 &#x1f345;感兴趣的可以先收藏起来&#xff0c;点赞、关注不迷路&#xff0c;大家在毕设选题&#xff…

适用于 Windows 的 12 个最佳免费磁盘分区管理器软件

分区是与其他部分分开的硬盘驱动器部分。它使您能够将硬盘划分为不同的逻辑部分。分区软件是一种工具&#xff0c;可帮助您执行基本选项&#xff0c;例如创建、调整大小和删除物理磁盘的分区。许多此类程序允许您更改磁盘片的标签以便于识别数据。 适用于 Windows 的 12 个最佳…

【PaperReading】3. PTP

Category Content 论文题目 Position-guided Text Prompt for Vision-Language Pre-training Code: ptp 作者 Alex Jinpeng Wang (Sea AI Lab), Pan Zhou (Sea AI Lab), Mike Zheng Shou (Show Lab, National University of Singapore), Shuicheng Yan (Sea AI Lab) 另一篇…

爬虫01-爬虫原理以及爬虫前期准备工作

文章目录 1 爬虫基本原理什么是爬虫爬虫功能详解爬虫基本流程两个概念&#xff1a;request和response 2 一些问题爬虫能抓取什么样的数据&#xff1f;抓取的数据怎么提取部分内容&#xff1f;数据解析方式。为什么我爬虫抓取的数据和浏览器看到的不一样怎样解决JavaScript渲染的…

计算数学表达式的程序(Java课程设计)

1. 课设团队介绍 团队名称 团队成 员介绍 任务分配 团队成员博客 XQ Warriors 徐维辉 负责计算器数据的算法操作&#xff0c;如平方数、加减乘除&#xff0c;显示历史计算记录 无 邱良厦&#xff08;组长&#xff09; 负责计算器的图形设计&#xff0c;把输入和结果显…

公共用例库计划--个人版(二)主体界面设计

1、任务概述 计划内容&#xff1a;完成公共用例库的开发实施工作&#xff0c;包括需求分析、系统设计、开发、测试、打包、运行维护等工作。 1.1、 已完成&#xff1a; 需求分析、数据库表的设计&#xff1a;公共用例库计划–个人版&#xff08;一&#xff09; 1.2、 本次待完…

2024新年烟花代码完整版

文章目录 前言烟花效果展示使用教程查看源码HTML代码CSS代码JavaScript 新年祝福 前言 在这个充满希望和激动的2024年&#xff0c;新的一年即将拉开帷幕&#xff0c;而数字科技的创新与发展也如火如荼。烟花绚丽多彩的绽放&#xff0c;一直以来都是新年庆典中不可或缺的元素。…

微信小程序 组件component ts用法

还在为 使用了ts 但是组件内显示this.setData/this.data.xxx ts报错 觉得难看吗&#xff1f; 还在为明明定义了applyInfo&#xff0c;明明应该有setData为何报错&#xff1f; 还在为不知道如何写类型而烦心吗&#xff1f; 不如转变思路将methods看成为一个对象 增加断言 as a…

实现多级缓存(Redis+Caffeine)

文章目录 多级缓存的概述多级缓存的优势 多级缓存的概述 在高性能的服务架构设计中&#xff0c;缓存是一个不可或缺的环节。在实际的项目中&#xff0c;我们通常会将一些热点数据存储到Redis或MemCache这类缓存中间件中&#xff0c;只有当缓存的访问没有命中时再查询数据库。在…

公网环境使用移动端设备+cpolar远程访问本地群晖nas上的影视资源

文章目录 1.使用环境要求&#xff1a;2.下载群晖videostation&#xff1a;3.公网访问本地群晖videostation中的电影&#xff1a;4.公网条件下使用电脑浏览器访问本地群晖video station5.公网条件下使用移动端&#xff08;搭载安卓&#xff0c;ios&#xff0c;ipados等系统的设备…

小家电应用解决方案以及选型指南

电磁炉是现代厨房中常见的一种小家电产品&#xff0c;它利用电磁感应加热原理&#xff0c;可以快速、高效地进行烹饪。在电磁炉的设计和制造过程中&#xff0c;功率开关芯片的选择对于产品的性能和成本有着重要的影响。 针对电磁炉的应用需求&#xff0c;推荐采用LED驱动芯片S…

蓝桥杯省赛无忧 STL 课件12 vector

01 vector的定义和特性 02 vector的常用函数 03 vector排序去重 示例&#xff1a; #include<bits/stdc.h> using namespace std; int main(){vector<int> vec {5,2,8,1,9};sort(vec.begin(),vec.end());for(const auto& num : vec){cout<<num<<&q…

Centos7升级openssl到openssl1.1.1

Centos7升级openssl到openssl1.1.1 1、先查看openssl版本&#xff1a;openssl version 2、Centos7升级openssl到openssl1.1.1 升级步骤 #1、更新所有现有的软件包列表并安装最新的软件包&#xff1a; $sudo yum update #2、接下来&#xff0c;我们需要从源代码编译和构建OpenS…

【原生部署】SpringBoot+Vue前后端分离项目

本次主要讲解SpringBootVue前后端完全分离项目在CentOS云服务器上的环境搭建与部署过程&#xff0c;我们主要讲解原生部署。 一.原生部署概念 原生部署是指将应用程序&#xff08;一般是指软件、应用或服务&#xff09;在底层的操作系统环境中直接运行和部署&#xff0c;而不…

微软Office 2019 批量授权版

软件介绍 微软办公软件套件Microsoft Office 2019 专业增强版2024年1月批量许可版更新推送&#xff01;Office2019正式版2018年10月份推出&#xff0c;主要为多人跨平台办公与团队协作打造。Office2019整合对过去三年在Office365里所有功能&#xff0c;包括对Word、Excel、Pow…

Docker的介绍及安装基本操作命令

前言 Docker 是一个开源的应用容器引擎&#xff0c;基于 Go 语言 并遵从 Apache2.0 协议开源。 Docker 可以让开发者打包他们的应用以及依赖包到一个轻量级、可移植的容器中&#xff0c;然后发布到任何流行的 Linux 机器上&#xff0c;也可以实现虚拟化。 容器是完全使用沙箱…

基于Selenium+Python的web自动化测试框架

一、什么是Selenium&#xff1f; Selenium是一个基于浏览器的自动化测试工具&#xff0c;它提供了一种跨平台、跨浏览器的端到端的web自动化解决方案。Selenium主要包括三部分&#xff1a;Selenium IDE、Selenium WebDriver 和Selenium Grid。 Selenium IDE&#xff1a;Firefo…

阿里云和AWS之间的应用程序防火墙比较及选择建议!

对于大多数开发人员来说&#xff0c;托管在云中的 Web 应用程序或 REST API 是一种常见方案。但是&#xff0c;并非每个应用程序都具有相同的安全级别。将 Web 应用程序防火墙 &#xff08;WAF&#xff09; 添加到 Web 应用程序是提高安全性的有用方法。 在本文中&#xff0c;…