为什么80%的码农都做不了架构师?>>>   

JAVA NIO的服务器端实现

package com.flyer.cn.javaIO;import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
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.charset.Charset;
import java.util.Date;
import java.util.Iterator;
import java.util.Set;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;public class EchoServer {public static SelectorLoop connectionBell;public static SelectorLoop readBell;public boolean isReadBellRunning=false;private ExecutorService thdPool=Executors.newCachedThreadPool();public static void main(String[] args) throws IOException {new EchoServer().startServer();}// 启动服务器public void startServer() throws IOException {// 准备好一个闹钟.当有链接进来的时候响.connectionBell = new SelectorLoop();// 准备好一个闹装,当有read事件进来的时候响.readBell = new SelectorLoop();// 开启一个server channel来监听ServerSocketChannel ssc = ServerSocketChannel.open();// 开启非阻塞模式ssc.configureBlocking(false);ServerSocket socket = ssc.socket();socket.bind(new InetSocketAddress("localhost",7878));// 给闹钟规定好要监听报告的事件,这个闹钟只监听新连接事件.ssc.register(connectionBell.getSelector(), SelectionKey.OP_ACCEPT);new Thread(connectionBell,"connectionBell").start();}// Selector轮询线程类public class SelectorLoop implements Runnable {private Selector selector;private ByteBuffer temp = ByteBuffer.allocate(1024);public SelectorLoop() throws IOException {this.selector = Selector.open();}public Selector getSelector() {return this.selector;}@Overridepublic void run() {while(true) {try {// 阻塞,只有当至少一个注册的事件发生的时候才会继续.this.selector.select();Set<SelectionKey> selectKeys = this.selector.selectedKeys();Iterator<SelectionKey> it = selectKeys.iterator();while (it.hasNext()) {SelectionKey key = it.next();it.remove();if (key.isAcceptable()) {// 这是一个connection accept事件, 并且这个事件是注册在serversocketchannel上的.ServerSocketChannel ssc = (ServerSocketChannel) key.channel();// 接受一个连接.SocketChannel sc = ssc.accept();// 对新的连接的channel注册read事件. 使用readBell闹钟.sc.configureBlocking(false);sc.register(readBell.getSelector(), SelectionKey.OP_READ);// 如果读取线程还没有启动,那就启动一个读取线程.synchronized(EchoServer.this) {if (!EchoServer.this.isReadBellRunning) {EchoServer.this.isReadBellRunning = true;new Thread(readBell,"readBell").start();}}} else if (key.isReadable()){// 这是一个read事件,并且这个事件是注册在socketchannel上的.SocketChannel sc = (SocketChannel) key.channel();// 写数据到bufferint count = sc.read(temp);if (count < 0) {// 客户端已经断开连接.key.cancel();sc.close();return;}// 切换buffer到读状态,内部指针归位.temp.flip();String msg = Charset.forName("UTF-8").decode(temp).toString();System.out.println(new Date().toLocaleString()+"Server received ["+msg+"] from client address:" + sc.getRemoteAddress());// 清空buffertemp.clear();thdPool.submit(new Dispatch(sc,msg));}}} catch (IOException e) {e.printStackTrace();}}}public class Dispatch implements Runnable{private SocketChannel sc;private String msg;public Dispatch(SocketChannel _sc,String _msg){this.sc=_sc;this.msg=_msg;}public void run() {try{Thread.sleep(1000);// echo back.sc.write(ByteBuffer.wrap(msg.getBytes(Charset.forName("UTF-8"))));}catch(Exception ex){ex.printStackTrace();}}}}}

JAVA NIO的客户端实现

package com.flyer.cn.javaIO;import java.io.IOException;
import java.net.InetSocketAddress;
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.Date;
import java.util.Iterator;
import java.util.Set;public class Client implements Runnable {// 空闲计数器,如果空闲超过10次,将检测server是否中断连接.private String clientName;private static int idleCounter = 0;private Selector selector;private SocketChannel socketChannel;private ByteBuffer temp = ByteBuffer.allocate(1024);public static void main(String[] args) throws IOException {for(int i=0;i<100;i++){Client client= new Client("client"+i);new Thread(client).start();//client.sendFirstMsg();}}public Client(String name) throws IOException {this.clientName=name;// 同样的,注册闹钟.this.selector = Selector.open();// 连接远程serversocketChannel = SocketChannel.open();// 如果快速的建立了连接,返回true.如果没有建立,则返回false,并在连接后出发Connect事件.Boolean isConnected = socketChannel.connect(new InetSocketAddress("localhost", 7878));socketChannel.configureBlocking(false);SelectionKey key = socketChannel.register(selector, SelectionKey.OP_READ);if (isConnected) {this.sendFirstMsg();} else {// 如果连接还在尝试中,则注册connect事件的监听. connect成功以后会出发connect事件.key.interestOps(SelectionKey.OP_CONNECT);}}public void sendFirstMsg() throws IOException {String msg = "Hello NIO.From "+this.clientName;socketChannel.write(ByteBuffer.wrap(msg.getBytes(Charset.forName("UTF-8"))));}@Overridepublic void run() {while (true) {try {// 阻塞,等待事件发生,或者1秒超时. num为发生事件的数量.int num = this.selector.select(1000);if (num ==0) {idleCounter ++;if(idleCounter >10) {// 如果server断开了连接,发送消息将失败.try {this.sendFirstMsg();} catch(ClosedChannelException e) {e.printStackTrace();this.socketChannel.close();return;}}continue;} else {idleCounter = 0;}Set<SelectionKey> keys = this.selector.selectedKeys();Iterator<SelectionKey> it = keys.iterator();while (it.hasNext()) {SelectionKey key = it.next();it.remove();if (key.isConnectable()) {// socket connectedSocketChannel sc = (SocketChannel)key.channel();if (sc.isConnectionPending()) {sc.finishConnect();}// send first message;this.sendFirstMsg();}if (key.isReadable()) {// msg received.SocketChannel sc = (SocketChannel)key.channel();this.temp = ByteBuffer.allocate(1024);int count = sc.read(temp);if (count<0) {sc.close();continue;}// 切换buffer到读状态,内部指针归位.temp.flip();String msg = Charset.forName("UTF-8").decode(temp).toString();System.out.println("Client received ["+msg+"] from server address:" + sc.getRemoteAddress()+new Date().toLocaleString());Thread.sleep(1000);// echo back.sc.write(ByteBuffer.wrap(msg.getBytes(Charset.forName("UTF-8"))));// 清空buffertemp.clear();}}} catch (IOException e) {e.printStackTrace();} catch (InterruptedException e) {e.printStackTrace();}}}}

这个实例在高并发下会产生粘包和段包的问题,解决方法参考下一篇

转载于:https://my.oschina.net/u/1774673/blog/808085

JAVA NIO 实例相关推荐

  1. java NIO及NIO聊天室

    参考链接: java NIO实例1:http://blog.chinaunix.net/uid-25808509-id-3346228.html java NIO教程之selector(一系列): h ...

  2. java nio 事件_Java NIO原理及实例

    Java NIO是在jdk1.4开始使用的,它既可以说成"新I/O",也可以说成非阻塞式I/O.下面是java NIO的工作原理: 1. 由一个专门的线程来处理所有的 IO 事件, ...

  3. Java NIO SocketChannel+Buffer+Selector 详解(含多人聊天室实例)

    一.Java NIO 的核心组件 Java NIO的核心组件包括:Channel(通道),Buffer(缓冲区),Selector(选择器),其中Channel和Buffer比较好理解  简单来说 N ...

  4. Java NIO Socket编程实例

    各I/O模型优缺点 BIO通信模型 BIO主要的问题在于每当有一个新的客户端请求接入时,服务端必须创建一个新的线程处理新接入的客户端链路,一个线程只能处理一个客户端连接 线程池I/O编程 假如所有可用 ...

  5. Java NIO Selector详解(含多人聊天室实例)

    一.Java NIO 的核心组件 Java NIO的核心组件包括:Channel(通道),Buffer(缓冲区),Selector(选择器),其中Channel和Buffer比较好理解 简单来说 NI ...

  6. java NIO详解

    http://zalezone.cn/2014/09/17/NIO%E7%B2%BE%E7%B2%B9/ 1. 前言 我们在写java程序的时候,为了进行优化,把全部的精力用在了处理效率上,但是对IO ...

  7. 11 Java NIO Non-blocking Server-翻译

    尽管你对Java NIO的工作原理很了解,但是设计一个非阻塞的服务器仍然困难.与阻塞的IO相比,非阻塞的IO也包含一些挑战.这里将会讨论一些非阻塞服务器所面临的一些挑战,以及一些可行的方案. 查找关于 ...

  8. Java NIO系列教程(六) Selector

    Selector(选择器)是Java NIO中能够检测一到多个NIO通道,并能够知晓通道是否为诸如读写事件做好准备的组件.这样,一个单独的线程可以管理多个channel,从而管理多个网络连接. 下面是 ...

  9. java nio 写事件_Java NIO

    java Nio Selector 选择器 Buffer 缓冲器 Channel 通道 Selector是NIO的核心,是channel的管理者,通过执行select()阻塞方式,监听是否有chann ...

最新文章

  1. shopnc 发票项目
  2. Android colorPrimary、colorPrimaryDark、colorAccent详解
  3. 006 - node.js
  4. JavaScript:变量提升作用域
  5. GridView 中如何给删除按钮添加提示
  6. java 种子填充算法_种子填充算法
  7. 爬虫--爬取雪球网数据
  8. [转]4款手机音乐播放器对比
  9. JavaScript:实现PigeonHoleSort鸽巢排序算法(附完整源码)
  10. 【小河今学 | Javascript】鼠标拖拽方块运动
  11. Android 图形架构 之三—— 创建Layer、Surface、SurfaceControl
  12. win2008服务器蓝屏如何修复,win2008r2 老是蓝屏重启。
  13. 电脑端上有哪些免费好用的思维导图软件?
  14. 面向对象程序设计(c++)面试常问——for考研复试面试
  15. 软件项目方案模板~!
  16. CTF压缩包加密破解总结
  17. 睡眠质量不好的解决方法,每个年龄段的睡眠时间
  18. 手机APP试玩赚钱平台真实性及其技术论证
  19. 使用预训练语言模型预测阶段:GPU、CPU性能差别【Pegasus】
  20. RTthread-线程的创建

热门文章

  1. ServiceMix中文教程
  2. 使用PreloadJS加载图片资源
  3. C++中delete和delete[]的区别
  4. Android 常用框架集合
  5. 远程debug Tomcat工程
  6. C#中的cookie编程
  7. @Validated和@Valid区别:Spring validation验证框架对入参实体进行嵌套验证必须在相应属性(字段)加上@Valid而不是@Validated...
  8. TensorFlow基础笔记(5) VGGnet_test
  9. 如何使用PHP自动备份数据库
  10. ByteBuffer