最近看了《netty in action》,关于netty的线程模型不太理解,于是学习了一下java nio的知识,利用java nio写个简单的服务器便于理解。

java nio有3个重要的概念, Channels ,Buffers ,Selectors。通过他们我们可以用单个的线程监听多个数据通道。
java nio可以进行阻塞的io操作,也可以进行非阻塞的io操作,我们更多是用非阻塞式的操作。

参考文章

Java NIO 系列教程

NIO 入门

完整代码.码云

测试工具

USR-TCP232
SocketTool2

服务器端使用两个线程,一个线程负责 accept 连接,另一个线程负责处理 接收到的数据

accept代码

package me.zingon.nioserver;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.nio.channels.SocketChannel;
import java.util.Iterator;
import java.util.concurrent.BlockingQueue;/*** Created by zhidi on 2018-6-29.*/
public class SocketAccepter implements Runnable{private Integer port = 9999;private ServerSocketChannel server=null;//接受到的连接private BlockingQueue<SocketChannel> queue=null;Selector acceptSelector=Selector.open();public SocketAccepter(Integer port, BlockingQueue<SocketChannel> queue) throws IOException {this.port = port;this.queue = queue;}@Overridepublic void run() {try {this.server = ServerSocketChannel.open();//配置为非阻塞this.server.configureBlocking(false);//注册accept事件this.server.register(acceptSelector, SelectionKey.OP_ACCEPT);this.server.bind(new InetSocketAddress(port));System.out.println("服务器在 "+port +"端口启动");} catch (IOException e) {e.printStackTrace();}try {SocketChannel socketChannel=this.server.accept();} catch (IOException e) {e.printStackTrace();}while (true){int count = 0;try {count = acceptSelector.selectNow();} catch (IOException e) {e.printStackTrace();}if(count ==0 ){continue;}Iterator<SelectionKey> iterator = acceptSelector.selectedKeys().iterator();while (iterator.hasNext()){SelectionKey key = iterator.next();ServerSocketChannel ssc = (ServerSocketChannel) key.channel();try {//接受连接SocketChannel sc = ssc.accept();queue.add(sc);System.out.println("服务器接收连接 :" + sc);} catch (IOException e) {e.printStackTrace();}iterator.remove();}}}
}

处理线程

package me.zingon.nioserver;import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.ClosedChannelException;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.SocketChannel;
import java.nio.charset.Charset;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.Queue;
import java.util.concurrent.BlockingQueue;/*** Created by zhidi on 2018-6-29.*/
public class SocketLoop implements Runnable {//已接受连接private BlockingQueue<SocketChannel> queue;//读selectorprivate Selector readSelector=Selector.open();//写selectorprivate Selector writeSelector=Selector.open();private ByteBuffer readBuf=ByteBuffer.allocate(1024*64);private Queue<String> msgQueue=new LinkedList<>();public SocketLoop(BlockingQueue<SocketChannel> queue) throws IOException {this.queue = queue;}@Overridepublic void run() {System.out.println("服务器处理线程启动");while (true){//处理已接收连接registerNewChannel();try {readFromChannels();writeToChannels();} catch (IOException e) {e.printStackTrace();}}}//给socketChannel注册读/写时间private void registerNewChannel(){SocketChannel sc=null;while( (sc = queue.poll()) != null){try {sc.configureBlocking(false);sc.register(readSelector, SelectionKey.OP_READ);sc.register(writeSelector,SelectionKey.OP_WRITE);} catch (ClosedChannelException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}}}//从读就绪的channel中读取数据,添加到msgQueue中private void readFromChannels() throws IOException {int count = readSelector.selectNow();if(count == 0){return;}Iterator<SelectionKey> iterator = readSelector.selectedKeys().iterator();while (iterator.hasNext()){SelectionKey key =  iterator.next();if(!key.isValid()){continue;}SocketChannel channel = (SocketChannel) key.channel();try {channel.read(readBuf);readBuf.flip();StringBuilder sb=new StringBuilder();while(readBuf.hasRemaining()) {sb.append((char)readBuf.get());}readBuf.compact();System.out.println(sb.toString());msgQueue.add(sb.toString());} catch (IOException e) {e.printStackTrace();key.cancel();channel.socket().close();channel.close();}iterator.remove();}}//当写就绪并且msgQueue不为空时,将msgQueue中的数据发送给所有写就绪channelprivate void writeToChannels() throws IOException {int count = writeSelector.selectNow();if(count == 0){return;}Iterator<SelectionKey> iterator = writeSelector.selectedKeys().iterator();String msg=msgQueue.poll();while (iterator.hasNext()){SelectionKey key =  iterator.next();if(!key.isValid()){continue;}if(msg == null){iterator.remove();return;}SocketChannel channel = (SocketChannel) key.channel();byte[] asd=(Thread.currentThread().getName()+msg).getBytes();ByteBuffer bf=ByteBuffer.allocate(asd.length);bf.put(asd);bf.flip();while(bf.hasRemaining()) {try {channel.write(bf);} catch (IOException e) {key.cancel();channel.socket().close();channel.close();e.printStackTrace();}}bf.clear();iterator.remove();}}
}

转载于:https://www.cnblogs.com/A-yes/p/9894145.html

java nio广播服务器相关推荐

  1. java nio connect_服务器或客户端上的Java NIO套接字在什么时...

    Do we need to bind here? Or is that just for if we want to refer to a local port? 您不需要绑定客户端SocketCha ...

  2. 基于 Java NIO 实现简单的 HTTP 服务器

    1.简介 本文是上一篇文章实践篇,在上一篇文章中,我分析了选择器 Selector 的原理.本篇文章,我们来说说 Selector 的应用,如标题所示,这里我基于 Java NIO 实现了一个简单的 ...

  3. java nio ssl_java连接MQTT+SSL服务器

    java用ssl加密方式连接mqtt服务器.其它ssl加密的也可以参考,SSLSocketFactory获取部分都是一样的.踩了很多坑,根据生成工具不同(openssl和keytool)以及秘钥文件编 ...

  4. Java NIO编写Socket服务器的一个例子

    最近一直在忙着JAVA NIO的知识,花了一下午的时间,总算写出了一个可以运行的程序,废话少说,上代码! Java代码: import java.io.IOException; import java ...

  5. java nio 强制关闭_Java NIO服务器:远程主机强迫关闭了一个现有的连接

    Java NIO聊天室 中,若客户端强制关闭,服务器会报"java.io.IOException: 远程主机强迫关闭了一个现有的连接.",并且服务器会在报错后停止运行,错误的意思就 ...

  6. 解决服务器报错java.nio.file.AccessDeniedException: /opt/jeecg-boot/upload

    文章长了点,着急解决问题的朋友可以直接看最后(三). 解决java.nio.file.AccessDeniedException: /opt/jeecg-boot/upload 一.查看报错日志 二. ...

  7. 并发型服务器响应方式,Java NIO 在并发型服务器设计中的应用.pdf

    Java NIO 在并发型服务器设计中的应用 丁辉 北京邮电大学PCN&CAD 中心,北京(100876 ) E-mail :lvsehaier@ 摘 要:本文分析了应用传统阻塞型网络I/O ...

  8. 并发型服务器响应方式,基于Java NIO 开发高性能并发型服务器程序的研究

    基于Java NIO 开发高性能并发型服务器程序的研究 第8卷%第5期 软件导刊 2009年5月SoftwareGuide Vol.8No.5May.2009 基于JavaNIO开发高性能并发型服务器 ...

  9. 源码分析netty服务器创建过程vs java nio服务器创建

    1.Java NIO服务端创建 首先,我们通过一个时序图来看下如何创建一个NIO服务端并启动监听,接收多个客户端的连接,进行消息的异步读写. 示例代码(参考文献[2]): import java.io ...

  10. 基于事件的 NIO 多线程服务器--转载

    JDK1.4 的 NIO 有效解决了原有流式 IO 存在的线程开销的问题,在 NIO 中使用多线程,主要目的已不是为了应对每个客户端请求而分配独立的服务线程,而是通过多线程充分使用用多个 CPU 的处 ...

最新文章

  1. 关于MSSQL导入导出时主键与约束丢失的问题解决
  2. 锅都不敢背,凭什么让大家跟着你干?
  3. 谷歌提出“T5” 新NLP模型,突破迁移学习局限,多基准测试达SOTA!
  4. git push时如果不再弹出用户和密码的输入提示框该怎么办
  5. gpl可以商用吗_一文看懂开源许可证,能不能商用再也不抓瞎
  6. 未来是Apache Karaf上的微服务架构
  7. php 随机在文章中添加锚文本_SEO站长布局锚文本时的7大注意事项
  8. Codeforces 709E. Centroids 树形DP
  9. c++11 string转ing_pdfkit | 利用python实现html文件转pdf
  10. excel loc() python_python pandas df.loc[]的典型用法
  11. python可以做什么-Python简直就是万能的,你用Python都做过哪些事?
  12. C# winform 跨线程修改界面
  13. Python3按编号创建文件夹并在文件夹下创建对应编号的txt文件
  14. Bridge(桥接)-对象结构型模式
  15. error LNK2019: 无法解析的外部符号 _WinMain@16
  16. 找出2n+1个数中不成对的那个
  17. 市政管网检测机器人收费标准_疏通市政管道 市政管网检测 机器人管道检测价格...
  18. 怎样用计算机算出54188,计算机应用技术练习题.doc
  19. word2016撤销无效解决办法
  20. php设置时区的两种方法

热门文章

  1. 最流行6种微服务RPC技术,你一定要知道
  2. 「收藏」其实是欺骗自己
  3. python 删除第三方库_python中通过pip安装的第三方库在哪里
  4. 转【es中数据节点和主机】
  5. CSS3_线性渐变(linear-gradient)+ 盒子阴影(box-shadow)
  6. 汉诺塔问题(递归之路)
  7. 多个表结果的并列显示
  8. Django+MySQLDB配置
  9. 水土不服的SNS,落地生根的网游
  10. C# 判断字符中是否包含中文