BIO、NIO、selector、Netty代码Demo示例

文章目录

    • (一)BIO(Blocking I/O 阻塞I/O)
    • (二)NIO(Non-Blocking I/O 非阻塞I/O)
    • (三)IO多路复用--Selector
    • (四)Netty

(一)BIO(Blocking I/O 阻塞I/O)

阻塞I/O的连接accept()方法及数据读取的read()方法都是阻塞的,也就是说没有客户端发起连接时会阻塞,客户端发起连接后不发送数据也会阻塞。

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.nio.charset.StandardCharsets;/**
* 阻塞IO
*/
public class BioServerDemo {public static void main(String[] args) throws IOException {ServerSocket serverSocket = new ServerSocket(9000);while(true){System.out.println("等待连接。。");//阻塞方法//可以通过控制台输入命令进行连接:telnet localhost 9000,CTRL+]进入Telnet指令Socket clientSocket = serverSocket.accept();System.out.println("有客户端连接了。。");//虽然采用多线程可以支持多个线程同时访问,但是会引发C10K问题//C10K->connection=1w,C10M->connection=1000w,就是连接数很多的意思//new Thread(new Runnable() {//	@Override//	public void run() {//		try {handler(clientSocket);//		} catch (IOException e) {//			e.printStackTrace();//		}//	}//}).start();}}private static void handler(Socket clientSocket) throws IOException {byte[] bytes = new byte[1024];System.out.println("准备read。。");//接收客户端的数据,阻塞方法,客户端没有发送数据,服务端就会没有数据可读时就阻塞int read  = clientSocket.getInputStream().read(bytes);System.out.println("read完毕。。");if (read !=-1){System.out.println("接收客户端的数据:"+new String(bytes,0,read));}//clientSocket.getOutputStream().write("HelloClint".getBytes(StandardCharsets.UTF_8));//clientSocket.getOutputStream().flush();}
}

(二)NIO(Non-Blocking I/O 非阻塞I/O)

非阻塞I/O在客户端连接方法accept()和read()方法中都不会阻塞,我们可以通过返回值判断是否有客户端发起连接或者发送数据,进行相应的处理。
简单的NIO因为是通过遍历的方式,会有大量的空循环

import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.nio.ByteBuffer;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;/***初版- NIO(非阻塞)编程*/
public class NioServer {static List<SocketChannel> channelList = new ArrayList<>();public static void main(String[] args) throws IOException {ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();serverSocketChannel.socket().bind(new InetSocketAddress(9000));//这里可选非阻塞和阻塞,如果选择阻塞true,下面的accept()方法会阻塞线程serverSocketChannel.configureBlocking(false);System.out.println("服务启动成功");while (true){SocketChannel socketChannel = serverSocketChannel.accept();if(socketChannel!=null){System.out.println("连接成功");//这里可选非阻塞和阻塞,如果选择阻塞true,下面的read()方法会阻塞线程socketChannel.configureBlocking(false);//将所有连接channel交给一个集合进行管理channelList.add(socketChannel);}//问题点: 空循环时间耗时太久Iterator<SocketChannel> iterator = channelList.iterator();//遍历访问所有channel集合获取客户端发送的数据,如果有任何一个连接客户端发送了数据,那么就处理当前channel里的数据while (iterator.hasNext()){SocketChannel sc = iterator.next();ByteBuffer byteBuffer = ByteBuffer.allocate(128);int len = sc.read(byteBuffer);if (len>0){System.out.println("接收到消息:"+new String(byteBuffer.array()));}else if(len ==-1){iterator.remove();System.out.println("客户端断开连接");}}}}
}

(三)IO多路复用–Selector

通过一个多路复用器selector对channel进行管理,这样
在这里插入图片描述

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;
/***进阶版- NIO(非阻塞)编程* 这是netty和Redis的雏形*/
public class NioSelectorServer {public static void main(String[] args) throws IOException {ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();serverSocketChannel.socket().bind(new InetSocketAddress(9000));serverSocketChannel.configureBlocking(false);//启用epoll模型,这个对应epoll_create()方法Selector selector = Selector.open();//注册阻塞事件:创建连接,这个对应epoll模型的epoll_ctl()方法SelectionKey selectionKey = serverSocketChannel.register(selector,SelectionKey.OP_ACCEPT);System.out.println("服务启动成功");while (true){//阻塞等待需要处理的事件发生,包括连接事件和数据读取事件,如果没有客户端发起连接或者客户端发送数据,这里会一直阻塞。这个对应epoll模型的epoll_wait()方法selector.select();//获取阻塞的事件Set<SelectionKey> selectionKeys = selector.selectedKeys();//对阻塞事件进行遍历Iterator<SelectionKey> iterator = selectionKeys.iterator();if(iterator.hasNext()){SelectionKey key =iterator.next();if(key.isAcceptable()){//这里只针对连接事件,ServerSocketChannel server = (ServerSocketChannel) key.channel();SocketChannel socketChannel = server.accept();socketChannel.configureBlocking(false);//连接建立后,注册阻塞事件:读取数据SelectionKey selKey = socketChannel.register(selector,SelectionKey.OP_READ);}else if(key.isReadable()){//这里只针对read事件,有需要可以针对write事件处理SocketChannel socketChannel = (SocketChannel) key.channel();ByteBuffer byteBuffer = ByteBuffer.allocate(128);socketChannel.configureBlocking(false);int len  = socketChannel.read(byteBuffer);if(len >0 ){System.out.println("接收到消息:"+new String(byteBuffer.array()));}else if(len ==-1 )//关闭socketsocketChannel.close();System.out.println("接收完成");}}//把处理完的阻塞事件移除iterator.remove();}}}
}

(四)Netty

Netty核心组件

  • Bootstrap和ServerBootstrap:当需要连接客户端或者服务器绑定指定端口时需要使用Bootstrap,ServerBootstrap有两种类型,一种是用于客户端的Bootstrap,一种是用于服务端 的ServerBootstrap。
  • Channel:相当于socket,与另一端进行通信的通道,具备bind、connect、read、write等IO操作的能力。
  • EventLoop:事件循环,负责处理Channel的IO事件,一个EventLoopGroup包含多个EventLoop,一个EventLoop可被分配至多个Channel,一个Channel只能注册于一个EventLoop,一个EventLoop只能与一个Thread绑定。
  • ChannelFuture:channel IO事件的异步操作结果。
  • ChannelHandler:包含IO事件具体的业务逻辑。
  • ChannelPipeline:ChannelHandler的管道容器。

DEMO
Netty服务端

public class NettyServer {public static void main(String[] args) throws InterruptedException {EventLoopGroup parentGroup = new NioEventLoopGroup();EventLoopGroup childGroup = new NioEventLoopGroup();try {//2.创建服务端启动引导/辅助类:ServerBootstrapServerBootstrap bootstrap = new ServerBootstrap();//3.给引导类配置两大线程组,确定了线程模型bootstrap.group(parentGroup, childGroup)// (非必备)打印日志.handler(new LoggingHandler(LogLevel.INFO))// 4.指定 IO 模型.channel(NioServerSocketChannel.class).childHandler(new ChannelInitializer<SocketChannel>() {@Overrideprotected void initChannel(SocketChannel ch) throws Exception {ChannelPipeline pipeline = ch.pipeline();pipeline.addLast(new StringDecoder());pipeline.addLast(new StringEncoder());/***  服务端添加IdleStateHandler心跳检测处理器,添加自定义处理Handler类实现userEventTriggered()方法作为超时事件的逻辑处理.*  IdleStateHandler心跳检测每十五秒进行一次读检测,如果十五秒内ChannelRead()方法未被调用则触发一次userEventTrigger()方法*  服务端为读IDLE*  pipeline.AddLast(new IdleStateHandler(15, 0, 0));//第一个参数为读,第二个为写,第三个为读写全部*/pipeline.addLast(new IdleStateHandler(15, 0, 0, TimeUnit.SECONDS));//5.可以自定义客户端消息的业务处理逻辑pipeline.addLast(new DemoSocketServerHandler());}});//            ChannelFuture future = bootstrap.bind(8888).sync().addListener(new ChannelFutureListener() {
//                @Override
//                public void operationComplete(ChannelFuture channelFuture) throws Exception {
//                    System.out.println("监听端口已经启动");
//                }
//            });ChannelFuture future = bootstrap.bind(8888).sync().addListener( future1 -> {if (future1.isSuccess()){System.out.println("监听端口已经启动!");} else {System.out.println("监听端口还未启动!");}} );System.out.println("服务器已启动。。。");future.channel().closeFuture().sync();} finally {parentGroup.shutdownGracefully();childGroup.shutdownGracefully();}}
}

Netty客户端

public class NettyClient {public static void main(String[] args) throws InterruptedException {NioEventLoopGroup eventLoopGroup = new NioEventLoopGroup();try {Bootstrap bootstrap = new Bootstrap();bootstrap.group(eventLoopGroup).channel(NioSocketChannel.class).handler(new ChannelInitializer<SocketChannel>() {@Overrideprotected void initChannel(SocketChannel ch) throws Exception {ChannelPipeline pipeline = ch.pipeline();pipeline.addLast(new StringDecoder(CharsetUtil.UTF_8));pipeline.addLast(new StringEncoder(CharsetUtil.UTF_8));pipeline.addLast(new DemoSocketClientHandler());}});ChannelFuture future = bootstrap.connect("localhost", 8888).sync();future.channel().closeFuture().sync();} finally {if(eventLoopGroup != null) {eventLoopGroup.shutdownGracefully();}}}
}

服务端处理handler

public class DemoSocketServerHandler extends ChannelInboundHandlerAdapter {@Overridepublic void channelActive(ChannelHandlerContext ctx) throws Exception {InetSocketAddress inetSocketAddress = (InetSocketAddress) ctx.channel().remoteAddress();String ip = inetSocketAddress.getAddress().getHostAddress();int port = inetSocketAddress.getPort();super.channelActive(ctx);System.out.println(ip+":"+port+" 上线了");}@Overridepublic void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {System.out.println(msg);System.out.println("Client Address ====== " + ctx.channel().remoteAddress());ctx.channel().writeAndFlush("from server:" + UUID.randomUUID());ctx.fireChannelActive();TimeUnit.MILLISECONDS.sleep(500);}@Overridepublic void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {cause.printStackTrace();ctx.close();}@Overridepublic void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {if (evt instanceof IdleStateEvent) {IdleStateEvent idleStateEvent = (IdleStateEvent) evt;if (idleStateEvent.state() == IdleState.READER_IDLE) {InetSocketAddress inetSocketAddress = (InetSocketAddress) ctx.channel().remoteAddress();String ip = inetSocketAddress.getAddress().getHostAddress();System.out.println((ip + ":" + inetSocketAddress.getPort() + "close"));ctx.channel().close();}}}
}

客户端处理handler

public class DemoSocketClientHandler extends ChannelInboundHandlerAdapter {@Overridepublic void channelRead(ChannelHandlerContext ctx, Object msg)throws Exception {System.out.println(msg);ctx.channel().writeAndFlush("from client: " + System.currentTimeMillis());TimeUnit.MILLISECONDS.sleep(5000);}@Overridepublic void channelActive(ChannelHandlerContext ctx) throws Exception {ctx.channel().writeAndFlush("from client:begin talking");}@Overridepublic void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {cause.printStackTrace();ctx.close();}//超时则关闭链路@Overridepublic void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {if (evt instanceof IdleStateEvent) {IdleStateEvent idleStateEvent = (IdleStateEvent) evt;if (idleStateEvent.state() == IdleState.READER_IDLE) {InetSocketAddress inetSocketAddress = (InetSocketAddress) ctx.channel().remoteAddress();String ip = inetSocketAddress.getAddress().getHostAddress();System.out.println((ip + ":" + inetSocketAddress.getPort() + "close"));ctx.channel().close();}}}
}

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

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

相关文章

【hacker送书第5期】SQL Server从入门到精通(第5版)

第5期图书推荐 内容简介作者简介图书目录参与方式 内容简介 SQL Server从入门到精通&#xff08;第5版&#xff09;》从初学者角度出发&#xff0c;通过通俗易懂的语言、丰富多彩的实例&#xff0c;详细介绍了SQL Server开发所必需的各方面技术。全书分为4篇共19章&#xff0c;…

优化机器学习:解析数据归一化的重要性与应用

在机器学习中&#xff0c;数据归一化是一种数据预处理的技术&#xff0c;旨在将数据转换为相似的范围或标准化的分布。这样做的主要目的是消除不同特征之间的量纲差异或数值范围差异&#xff0c;以确保模型在训练时更稳定、更有效地学习特征之间的关系。 通常&#xff0c;机器…

智能优化算法应用:基于水循环算法无线传感器网络(WSN)覆盖优化 - 附代码

智能优化算法应用&#xff1a;基于水循环算法无线传感器网络(WSN)覆盖优化 - 附代码 文章目录 智能优化算法应用&#xff1a;基于水循环算法无线传感器网络(WSN)覆盖优化 - 附代码1.无线传感网络节点模型2.覆盖数学模型及分析3.水循环算法4.实验参数设定5.算法结果6.参考文献7.…

安卓apk抓包

起因 手机&#xff08;模拟器&#xff09;有时候抓不到apk的包&#xff0c;需要借助Postern设置一个代理&#xff0c;把模拟器的流量代理到物理机的burp上。 解决方案 使用Postern代理&#xff0c;把apk的流量代理到burp。 Postern是一个用于代理和网络流量路由的工具&#xf…

C++ day44完全背包问题 零钱兑换Ⅱ 组合总和Ⅳ

完全背包&#xff1a;一个物品可以使用无数次&#xff0c;将01背包中倒序遍历背包变成正序遍历背包 遍历顺序&#xff1a;在完全背包中&#xff0c;对于一维dp数组来说&#xff0c;其实两个for循环嵌套顺序是无所谓的&#xff01; 先遍历物品&#xff0c;后遍历背包可以&#…

win10 下 mvn install 报错:编码GBK不可映射字符

问题背景 由于jenkins需要部署不同的项目&#xff0c;需要使用不同的jdk版本&#xff0c;所以需要配置单独的settings.xml&#xff0c;使用指定的jdk版本进行编译&#xff0c;这里需要单独的maven设置&#xff0c;在配置完后进行mvn的install的时候&#xff0c;由于存在中文注释…

Maven——Maven使用基础

1、安装目录分析 1.1、环境变量MAVEN_HOME 环境变量指向Maven的安装目录&#xff0c;如下图所示&#xff1a; 下面看一下该目录的结构和内容&#xff1a; bin&#xff1a;该目录包含了mvn运行的脚本&#xff0c;这些脚本用来配置Java命令&#xff0c;准备好classpath和相关…

Cytoscape软件下载、安装、插件学习[基础教程]

写在前面 今天分享的内容是自己遇到问题后&#xff0c;咨询社群里面的同学&#xff0c;帮忙解决的总结。 关于Cytoscape&#xff0c;对于做组学或生物信息学的同学基本是陌生的&#xff0c;可能有的同学用这个软件作图是非常溜的&#xff0c;做出来的网络图也是十分的好看&am…

【海思SS528 | VDEC】MPP媒体处理软件V5.0 | VDEC的使用总结

&#x1f601;博客主页&#x1f601;&#xff1a;&#x1f680;https://blog.csdn.net/wkd_007&#x1f680; &#x1f911;博客内容&#x1f911;&#xff1a;&#x1f36d;嵌入式开发、Linux、C语言、C、数据结构、音视频&#x1f36d; &#x1f923;本文内容&#x1f923;&a…

距离“全自动”漏洞挖掘又近了一步!腾讯安全大数据实验室论文入选ACM CCS 2023

计算机领域国际权威学术顶会ACM CCS 2023于11月26日在丹麦哥本哈根开幕。腾讯安全大数据实验室团队论文《Hopper: Interpretative Fuzzing for Libraries》被大会收录&#xff0c;昨天&#xff0c;实验室研究员谢雨轩受邀出席大会进行主题分享。 该论文提出了解释性模糊测试&a…

UCSC基因组浏览器用法

UCSC基因组浏览器用法 UCSC基因组浏览器是一个强大的在线工具&#xff0c;主要用于查看和分析多种生物的基因组数据。这个浏览器最初是由加利福尼亚大学圣克鲁兹分校的生物信息学家和计算生物学家开发的&#xff0c;旨在为科研人员提供一个易于访问和使用的界面&#xff0c;用于…

Java数据结构之《合并线性表》问题

一、前言&#xff1a; 这是怀化学院的&#xff1a;Java数据结构中的一道难度中等偏下的一道编程题(此方法为博主自己研究&#xff0c;问题基本解决&#xff0c;若有bug欢迎下方评论提出意见&#xff0c;我会第一时间改进代码&#xff0c;谢谢&#xff01;) 后面其他编程题只要我…

freertos任务调度机制深度分析(以RISC-V架构为例)

1、前言 本文是以RISC-V架构为例进行讲解&#xff0c;在汇编代码层面和ARM架构不一样&#xff0c;但是整体框架是一样的侧重任务调度底层机制讲解&#xff0c;讲解代码只保留了基本功能&#xff0c;可配置的功能基本都已经删除本文是以可抢占式调度机制进行讲解RISC-V架构只支持…

【ZEDSLAM】Ubuntu18.04系统ZED 2i双目相机SDK安装、联合标定、SLAM测试

0.设备、环境和说明 笔记本电脑i5-8300H、GTX 1060、32GRAM 因为后面要测试Vins-Fusion和ORB-SLAM3&#xff0c;所以推荐安装Ubuntu 18.04&#xff08;或者Ubuntu 20.04&#xff09; ROS 1&#xff08;不建议用比Ubuntu18更低的版本&#xff09; ROS一键安装命令&#xff1a;…

智能监控平台/视频共享融合系统EasyCVR接入RTSP协议视频流无法播放原因是什么?

视频集中存储/云存储/视频监控管理平台EasyCVR能在复杂的网络环境中&#xff0c;将分散的各类视频资源进行统一汇聚、整合、集中管理&#xff0c;实现视频资源的鉴权管理、按需调阅、全网分发、智能分析等。AI智能/大数据视频分析EasyCVR平台已经广泛应用在工地、工厂、园区、楼…

网络入门---网络编程预备知识

目录标题 ifconfigip地址和mac地址的区别端口号pid和端口号UDP和TCP的初步了解网络字节序socket套接字 ifconfig 通过指令ifconfig便可以查看到两个网络接口&#xff1a; 我们当前使用的是一个linux服务器并是一个终端设备&#xff0c;所以他只需要一个接口用来入网即可&…

JVM

图来自JavaGuide 程序计数器 程序计数器是线程私有的&#xff0c;每个线程一份&#xff0c;是线程安全的&#xff1b;内部保存的字节码的行号&#xff0c;用于记录正在执行的字节码指令的地址。 java堆 java堆是线程共享的区域&#xff08;线程不安全&#xff09;&#xff…

ECRS生产工时分析软件:工业效率提升的隐形引擎

降本增效往往是企业开工规划的第一步。那到底降什么本&#xff0c;增什么效呢&#xff0c;对于很多企业来说&#xff0c;都是从采购成本入手&#xff0c;结果采购成本是降下来了&#xff0c;但是整体品质却下降了。实际上&#xff0c;要降本增效&#xff0c;优化现场管理才是企…

leetcode 611. 有效三角形的个数(优质解法)

代码&#xff1a; class Solution {public int triangleNumber(int[] nums) {Arrays.sort(nums);int lengthnums.length;int n0; //三元组的个数//c 代表三角形最长的那条边for (int clength-1;c>2;c--){int left0;int rightc-1;while (left<right){if(nums[left]nums[r…

【JavaEE初阶】 HTTP响应报文

文章目录 &#x1f332;序言&#x1f38d;200 OK&#x1f340;404 Not Found&#x1f384;403 Forbidden&#x1f334;405 Method Not Allowed&#x1f38b;500 Internal Server Error&#x1f333;504 Gateway Timeout&#x1f332;302 Move temporarily&#x1f38d;301 Move…