我的编程空间,编程开发者的网络收藏夹
学习永远不晚

Java中怎么使用NIO实现网络编程

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

Java中怎么使用NIO实现网络编程

本篇文章为大家展示了Java中怎么使用NIO实现网络编程,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。

为什么需要NIO

使用Java编写过Socket程序的同学一定都知道Socket和SocketServer。当调用某个调用的时候,调用的地方就会阻塞,等待响应。这种方式对于小规模的程序非常方便,但是对于大型的程序就有点力不从心了,当有大量的连接的时候,我们可以为每一个连接建立一个线程来操作。但是这种做法带来的缺陷也是显而易见的:

  1. 硬件能够支持大量的并发。

  2. 并发的数量始终有一个上限。

  3. 各个线程之间的优先级不好控制。

  4. 各个Client之间的交互与同步困难。

我们也可以使用一个线程来处理所有的请求,使用不阻塞的IO,轮询查询所有的Client。这种做法同样也有缺陷:无法迅速响应Client端,同时会消耗大量轮询查询的时间。

所以,我们需要一种poll的模式来处理这种情况,从大量的网络连接中找出来真正需要服务的Client。这正是NIO诞生的原因:提供一种Poll的模式,在所有的Client中找到需要服务的Client。

回到我们刚刚说到的3个最最重要的Class:java.nio.channels中Selector和Channel,以及java.nio中的Buffer。

Channel代表一个可以被用于Poll操作的对象(可以是文件流也可以使网络流),Channel能够被注册到一个Selector中。通过调用Selector的select方法可以从所有的Channel中找到需要服务的实例(Accept,read ..)。

Buffer对象提供读写数据的缓存。相对于我们熟悉的Stream对象,Buffer提供更好的性能以及更好的编程透明性(人为控制缓存的大小以及具体的操作)。

配合BUFFER使用CHANNEL

与传统模式的编程不用,Channel不使用Stream,而是Buffer。我们来实现一个简单的非阻塞Echo Client:

package com.cnblogs.gpcuster;  import java.net.InetSocketAddress; import java.net.SocketException; import java.nio.ByteBuffer; import java.nio.channels.SocketChannel;  public class TCPEchoClientNonblocking { public static void main(String args[]) throws Exception { if ((args.length < 2) || (args.length > 3))// Testforcorrect#ofargs throw new IllegalArgumentException( "Parameter(s): <Server> <Word> [<Port>]"); String server = args[0];// ServernameorIPaddress // ConvertinputStringtobytesusingthedefaultcharset byte[] argument = args[1].getBytes(); int servPort = (args.length == 3) ? Integer.parseInt(args[2]) : 7; // Createchannelandsettononblocking SocketChannel clntChan = SocketChannel.open(); clntChan.configureBlocking(false); // Initiateconnectiontoserverandrepeatedlypolluntilcomplete if (!clntChan.connect(new InetSocketAddress(server, servPort))) { while (!clntChan.finishConnect()) { System.out.print(".");// Dosomethingelse } } ByteBuffer writeBuf = ByteBuffer.wrap(argument); ByteBuffer readBuf = ByteBuffer.allocate(argument.length); int totalByteclass="lazy" data-srcvd = 0;// Totalbytesreceivedsofar int byteclass="lazy" data-srcvd;// Bytesreceivedinlastread while (totalByteclass="lazy" data-srcvd < argument.length) { if (writeBuf.hasRemaining()) { clntChan.write(writeBuf); } if ((byteclass="lazy" data-srcvd = clntChan.read(readBuf)) == -1) { throw new SocketException("Connection closed prematurely"); } totalByteclass="lazy" data-srcvd += byteclass="lazy" data-srcvd; System.out.print(".");// Dosomethingelse } System.out.println("Received:" + // converttoStringperdefaultcharset new String(readBuf.array(), 0, totalByteclass="lazy" data-srcvd)); clntChan.close(); } }

这段代码使用ByteBuffer来保存读写的数据。通过clntChan.configureBlocking(false); 设置后,其中的connect,read,write操作都不回阻塞,而是立刻放回结果。

使用SELECTOR

Selector的可以从所有的被注册到自己Channel中找到需要服务的实例。

我们来实现Echo Server。

首先,定义一个接口:

package com.cnblogs.gpcuster;  import java.nio.channels.SelectionKey; import java.io.IOException;  public interface TCPProtocol { void handleAccept(SelectionKey key) throws IOException;  void handleRead(SelectionKey key) throws IOException;  void handleWrite(SelectionKey key) throws IOException; } 我们的Echo Server将使用这个接口。然后我们实现Echo Server: import java.io.IOException; import java.net.InetSocketAddress; import java.nio.channels.SelectionKey; import java.nio.channels.Selector; import java.nio.channels.ServerSocketChannel; import java.util.Iterator;  public class TCPServerSelector { private static final int BUFSIZE = 256;// Buffersize(bytes) private static final int TIMEOUT = 3000;// Waittimeout(milliseconds)  public static void main(String[] args) throws IOException { if (args.length < 1) {// Testforcorrect#ofargs throw new IllegalArgumentException("Parameter(s):<Port>..."); } // Createaselectortomultiplexlisteningsocketsandconnections Selector selector = Selector.open(); // Createlisteningsocketchannelforeachportandregisterselector for (String arg : args) { ServerSocketChannel listnChannel = ServerSocketChannel.open(); listnChannel.socket().bind( new InetSocketAddress(Integer.parseInt(arg))); listnChannel.configureBlocking(false);// mustbenonblockingtoregister // Registerselectorwithchannel.Thereturnedkeyisignored listnChannel.register(selector, SelectionKey.OP_ACCEPT); } // Createahandlerthatwillimplementtheprotocol TCPProtocol protocol = new EchoSelectorProtocol(BUFSIZE); while (true) {// Runforever,processingavailableI/Ooperations // Waitforsomechanneltobeready(ortimeout) if (selector.select(TIMEOUT) == 0) {// returns#ofreadychans System.out.print("."); continue; } // GetiteratoronsetofkeyswithI/Otoprocess Iterator<SelectionKey> keyIter = selector.selectedKeys().iterator(); while (keyIter.hasNext()) { SelectionKey key = keyIter.next();// Keyisbitmask // Serversocketchannelhaspendingconnectionrequests? if (key.isAcceptable()) { protocol.handleAccept(key); } // Clientsocketchannelhaspendingdata? if (key.isReadable()) { protocol.handleRead(key); } // Clientsocketchannelisavailableforwritingand // keyisvalid(i.e.,channelnotclosed)? if (key.isValid() && key.isWritable()) { protocol.handleWrite(key); } keyIter.remove();// removefromsetofselectedkeys } } } }

我们通过listnChannel.register(selector, SelectionKey.OP_ACCEPT); 注册了一个我们感兴趣的事件,然后调用selector.select(TIMEOUT)等待订阅的时间发生,然后再采取相应的处理措施。

***我们实现EchoSelectorProtocol

package com.cnblogs.gpcuster;  import java.nio.channels.SelectionKey; import java.nio.channels.SocketChannel; import java.nio.channels.ServerSocketChannel; import java.nio.ByteBuffer; import java.io.IOException;  public class EchoSelectorProtocol implements TCPProtocol { private int bufSize;// SizeofI/Obuffer  public EchoSelectorProtocol(int bufSize) { this.bufSize = bufSize; }  public void handleAccept(SelectionKey key) throws IOException { SocketChannel clntChan = ((ServerSocketChannel) key.channel()).accept(); clntChan.configureBlocking(false);// Mustbenonblockingtoregister // Registertheselectorwithnewchannelforreadandattachbytebuffer clntChan.register(key.selector(), SelectionKey.OP_READ, ByteBuffer .allocate(bufSize)); }  public void handleRead(SelectionKey key) throws IOException { // Clientsocketchannelhaspendingdata SocketChannel clntChan = (SocketChannel) key.channel(); ByteBuffer buf = (ByteBuffer) key.attachment(); long bytesRead = clntChan.read(buf); if (bytesRead == -1) {// Didtheotherendclose? clntChan.close(); } else if (bytesRead > 0) { // Indicateviakeythatreading/writingarebothofinterestnow. key.interestOps(SelectionKey.OP_READ | SelectionKey.OP_WRITE); } }  public void handleWrite(SelectionKey key) throws IOException {  // Retrievedatareadearlier ByteBuffer buf = (ByteBuffer) key.attachment(); buf.flip();// Preparebufferforwriting SocketChannel clntChan = (SocketChannel) key.channel(); clntChan.write(buf); if (!buf.hasRemaining()) {// Buffercompletelywritten? // Nothingleft,sonolongerinterestedinwrites key.interestOps(SelectionKey.OP_READ); } buf.compact();// Makeroomformoredatatobereadin } }

上述内容就是Java中怎么使用NIO实现网络编程,你们学到知识或技能了吗?如果还想学到更多技能或者丰富自己的知识储备,欢迎关注编程网行业资讯频道。

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

Java中怎么使用NIO实现网络编程

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

Java中怎么使用NIO实现网络编程

本篇文章为大家展示了Java中怎么使用NIO实现网络编程,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。为什么需要NIO使用Java编写过Socket程序的同学一定都知道Socket和SocketSe
2023-06-17

Java网络编程和NIO详解7:浅谈 Linux 中NIO Selector 的实现原理

本文转自互联网本系列文章将整理到我在GitHub上的《Java面试指南》仓库,更多精彩内容请到我的仓库里查看https://github.com/h3pl/Java-Tutorial喜欢的话麻烦点下Star哈文章将同步到我的个人博客:www
2023-06-02

Python中怎么使用Socket实现网络编程

本篇文章为大家展示了Python中怎么使用Socket实现网络编程,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。Socket:套接字套接字好比电话的插口,主机和端口就好比区号和电话号码,主机:是你要
2023-06-17

Java网络编程与NIO详解11:Tomcat中的Connector源码分析(NIO)

本文转载 https://www.javadoop.com本系列文章将整理到我在GitHub上的《Java面试指南》仓库,更多精彩内容请到我的仓库里查看https://github.com/h3pl/Java-Tutorial喜欢的话麻烦点
2023-06-02

Java网络编程与NIO详解4:浅析NIO包中的Buffer、Channel 和 Selector

本文转载自互联网本系列文章将整理到我在GitHub上的《Java面试指南》仓库,更多精彩内容请到我的仓库里查看https://github.com/h3pl/Java-Tutorial喜欢的话麻烦点下Star哈文章将同步到我的个人博客:ww
2023-06-02

Qt中网络编程怎么实现

这篇文章主要介绍“Qt中网络编程怎么实现”,在日常操作中,相信很多人在Qt中网络编程怎么实现问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”Qt中网络编程怎么实现”的疑惑有所帮助!接下来,请跟着小编一起来学习吧
2023-06-29

使用NIO实现一个Netty网络框架

使用NIO实现一个Netty网络框架?相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。Netty是一个高性能、异步事件驱动的NIO框架,它提供了对TCP、UDP和文件传输的支持,N
2023-05-31

BIO、NIO、IO多路复用模型详细介绍&Java NIO 网络编程

文章目录 前言基本概念BIO过程NIO过程IO多路复用过程Java NIO编程Java NIO 核心概念Java NIO 示例 总结 前言 上文介绍了网络编程的基础知识,并基于 Java 编写了 BIO 的网络编程。我们知道
2023-08-16

Java网络编程中线程的使用

本篇内容介绍了“Java网络编程中线程的使用”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!目录运行线程回调同步方法同步块死锁优先级暂停可以对
2023-06-20

Java网络编程怎么实现多线程聊天

这篇文章将为大家详细讲解有关Java网络编程怎么实现多线程聊天,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。聊天程序如果是单线程,会导致没人只能说一句,并且说了以后,必须等到另一个人的回复,才能说第二句。
2023-06-20

C#中怎么实现异步网络编程

这期内容当中小编将会给大家带来有关C#中怎么实现异步网络编程,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。C#异步网络编程两大方法一、Asynchronous Sockets的方法Socket类的很多连接
2023-06-17

怎么使用Java NIO实现多人聊天室

本篇内容主要讲解“怎么使用Java NIO实现多人聊天室”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“怎么使用Java NIO实现多人聊天室”吧!NIO服务端public class NioSe
2023-06-21

JAVA中怎么利用socket进行网络编程

本篇文章给大家分享的是有关JAVA中怎么利用socket进行网络编程,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。一、建立服务器类Java中有一个专门用来建立Socket服务器
2023-06-17

Java NIO怎么实现聊天室程序

本文小编为大家详细介绍“Java NIO怎么实现聊天室程序”,内容详细,步骤清晰,细节处理妥当,希望这篇“Java NIO怎么实现聊天室程序”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。服务端:package t
2023-06-17

Java网络编程TCP怎么实现文件上传功能

这篇文章给大家分享的是有关Java网络编程TCP怎么实现文件上传功能的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。具体内容如下客户端:package com.kuang.lesson02;import java.
2023-06-20

java NIO怎么实现简单聊天程序

这篇文章主要为大家展示了“java NIO怎么实现简单聊天程序”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“java NIO怎么实现简单聊天程序”这篇文章吧。具体内容如下服务端功能:1、接受客户
2023-06-21

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录