服务器

  1. package com.java.xiong.Net17;
  2. import java.io.IOException;
  3. import java.net.InetSocketAddress;
  4. import java.nio.ByteBuffer;
  5. import java.nio.channels.Channel;
  6. import java.nio.channels.SelectionKey;
  7. import java.nio.channels.Selector;
  8. import java.nio.channels.ServerSocketChannel;
  9. import java.nio.channels.SocketChannel;
  10. import java.nio.charset.Charset;
  11. public class NServer {
  12. // 用于检测所有的Channel状态的selector
  13. private Selector selector = null;
  14. static final int PORT = 30000;
  15. // 定义实现编码、解码的字符串集对象
  16. private Charset charse = Charset.forName("GBK");
  17. public void init() throws IOException {
  18. selector = Selector.open();
  19. // 通过open方法来打开一个未绑定的ServerSocketChannel是咧
  20. ServerSocketChannel server = ServerSocketChannel.open();
  21. InetSocketAddress isa = new InetSocketAddress("127.0.0.1", PORT);
  22. // 将该ServerSocketChannel绑定到指定的IP地址
  23. server.bind(isa);
  24. // 设置serverSocket已非阻塞方式工作
  25. server.configureBlocking(false);
  26. // 将server注册到指定的selector对象
  27. server.register(selector, SelectionKey.OP_ACCEPT);
  28. while (selector.select() > 0) {
  29. // 一次处理selector上的每个选择的SelectionKey
  30. for (SelectionKey sk : selector.selectedKeys()) {
  31. // 从selector上已选择的Kye集中删除正在处理的SelectionKey
  32. selector.selectedKeys().remove(sk);
  33. // 如果sk对应的Channel包含客户端的连接请求
  34. if (sk.isAcceptable()) {
  35. // 调用accept方法接收连接,产生服务器段的SocketChennal
  36. SocketChannel sc = server.accept();
  37. // 设置采用非阻塞模式
  38. sc.configureBlocking(false);
  39. // 将该SocketChannel注册到selector
  40. sc.register(selector, SelectionKey.OP_READ);
  41. }
  42. // 如果sk对应的Channel有数据需要读取
  43. if (sk.isReadable()) {
  44. // 获取该SelectionKey对银行的Channel,该Channel中有刻度的数据
  45. SocketChannel sc = (SocketChannel) sk.channel();
  46. // 定义备注执行读取数据源的ByteBuffer
  47. ByteBuffer buff = ByteBuffer.allocate(1024);
  48. String content = "";
  49. // 开始读取数据
  50. try {
  51. while (sc.read(buff) > 0) {
  52. buff.flip();
  53. content += charse.decode(buff);
  54. }
  55. System.out.println("读取的数据:" + content);
  56. // 将sk对应的Channel设置成准备下一次读取
  57. sk.interestOps(SelectionKey.OP_READ);
  58. }
  59. // 如果捕获到该sk对银行的Channel出现了异常,表明
  60. // Channel对应的Client出现了问题,所以从Selector中取消
  61. catch (IOException io) {
  62. // 从Selector中删除指定的SelectionKey
  63. sk.cancel();
  64. if (sk.channel() != null) {
  65. sk.channel().close();
  66. }
  67. }
  68. // 如果content的长度大于0,则连天信息不为空
  69. if (content.length() > 0) {
  70. // 遍历selector里注册的所有SelectionKey
  71. for (SelectionKey key : selector.keys()) {
  72. // 获取该key对应的Channel
  73. Channel targerChannel = key.channel();
  74. // 如果该Channel是SocketChannel对象
  75. if (targerChannel instanceof SocketChannel) {
  76. // 将读取到的内容写入该Channel中
  77. SocketChannel dest = (SocketChannel) targerChannel;
  78. dest.write(charse.encode(content));
  79. }
  80. }
  81. }
  82. }
  83. }
  84. }
  85. }
  86. public static void main(String [] args) throws IOException{
  87. new NServer().init();
  88. }
  89. }

客户端

  1. package com.java.xiong.Net17;
  2. import java.io.IOException;
  3. import java.net.InetSocketAddress;
  4. import java.nio.ByteBuffer;
  5. import java.nio.channels.SelectionKey;
  6. import java.nio.channels.Selector;
  7. import java.nio.channels.SocketChannel;
  8. import java.nio.charset.Charset;
  9. import java.util.Scanner;
  10. public class NClient {
  11. //定义检测Sockethannel的Selector对象
  12. private Selector  selector=null;
  13. static final int PORT=30000;
  14. //定义处理编码的字符集
  15. private Charset charset=Charset.forName("GBK");
  16. //客户端SocketChannel
  17. private SocketChannel sc=null;
  18. public void init() throws IOException{
  19. selector=Selector.open();
  20. InetSocketAddress isa=new InetSocketAddress("127.0.0.1", PORT);
  21. //调用open的静态方法创建连接指定的主机的SocketChannel
  22. sc=SocketChannel.open(isa);
  23. //设置该sc已非阻塞的方式工作
  24. sc.configureBlocking(false);
  25. //将SocketChannel对象注册到指定的Selector
  26. sc.register(selector, SelectionKey.OP_READ);
  27. //启动读取服务器数据端的线程
  28. new ClientThread().start();
  29. //创建键盘输入流
  30. Scanner scan=new Scanner(System.in);
  31. while(scan.hasNextLine()){
  32. //读取键盘的输入
  33. String line=scan.nextLine();
  34. //将键盘的内容输出到SocketChanenel中
  35. sc.write(charset.encode(line));
  36. }
  37. }
  38. //定义读取服务器端的数据的线程
  39. private class ClientThread extends Thread{
  40. @Override
  41. public void run() {
  42. try{
  43. while(selector.select()>0){
  44. //遍历每个有可能的IO操作的Channel对银行的SelectionKey
  45. for(SelectionKey sk:selector.selectedKeys()){
  46. //删除正在处理的SelectionKey
  47. selector.selectedKeys().remove(sk);
  48. //如果该SelectionKey对应的Channel中有可读的数据
  49. if(sk.isReadable()){
  50. //使用NIO读取Channel中的数据
  51. SocketChannel sc=(SocketChannel)sk.channel();
  52. String content="";
  53. ByteBuffer bff=ByteBuffer.allocate(1024);
  54. while(sc.read(bff)>0){
  55. sc.read(bff);
  56. bff.flip();
  57. content+=charset.decode(bff);
  58. }
  59. //打印读取的内容
  60. System.out.println("聊天信息:"+content);
  61. sk.interestOps(SelectionKey.OP_READ);
  62. }
  63. }
  64. }
  65. }catch(IOException io){
  66. io.printStackTrace();
  67. }
  68. }
  69. }
  70. public static void main(String [] args) throws IOException{
  71. new NClient().init();
  72. }
  73. }

java nio实现非阻塞Socket通信实例的更多相关文章

  1. JAVA基础知识之网络编程——-基于NIO的非阻塞Socket通信

    阻塞IO与非阻塞IO 通常情况下的Socket都是阻塞式的, 程序的输入输出都会让当前线程进入阻塞状态, 因此服务器需要为每一个客户端都创建一个线程. 从JAVA1.4开始引入了NIO API, NI ...

  2. Java NIO 同步非阻塞

    同步非阻塞IO (NIO) NIO是基于事件驱动思想的,实现上通常采用Reactor(http://en.wikipedia.org/wiki/Reactor_pattern)模式,从程序角度而言,当 ...

  3. JAVA NIO使用非阻塞模式实现高并发服务器

    参考:http://blog.csdn.net/zmx729618/article/details/51860699  https://zhuanlan.zhihu.com/p/23488863 ht ...

  4. 【转载】高性能IO设计 & Java NIO & 同步/异步 阻塞/非阻塞 Reactor/Proactor

    开始准备看Java NIO的,这篇文章:http://xly1981.iteye.com/blog/1735862 里面提到了这篇文章 http://xmuzyq.iteye.com/blog/783 ...

  5. java的高并发IO原理,阻塞BIO同步非阻塞NIO,异步非阻塞AIO

    原文地址: IO读写的基础原理 大家知道,用户程序进行IO的读写,依赖于底层的IO读写,基本上会用到底层的read&write两大系统调用.在不同的操作系统中,IO读写的系统调用的名称可能不完 ...

  6. Flex通信-与Java实现Socket通信实例

    Flex通信-与Java实现Socket通信实例  转自:http://blessht.iteye.com/blog/1136888 博客分类: Flex 环境准备 [服务器端] JDK1.6,“ja ...

  7. Java Socket 通信实例 - 转载

    基于Tcp协议的简单Socket通信实例(JAVA)   好久没写博客了,前段时间忙于做项目,耽误了些时间,今天开始继续写起~ 今天来讲下关于Socket通信的简单应用,关于什么是Socket以及一些 ...

  8. java并发之非阻塞算法介绍

    在并发上下文中,非阻塞算法是一种允许线程在阻塞其他线程的情况下访问共享状态的算法.在绝大多数项目中,在算法中如果一个线程的挂起没有导致其它的线程挂起,我们就说这个算法是非阻塞的. 为了更好的理解阻塞算 ...

  9. 4.NIO的非阻塞式网络通信

    /*阻塞 和 非阻塞 是对于 网络通信而言的*/ /*原先IO通信在进行一些读写操作 或者 等待 客户机连接 这种,是阻塞的,必须要等到有数据被处理,当前线程才被释放*/ /*NIO 通信 是将这个阻 ...

随机推荐

  1. 前端什么是BFC

    什么是BFC? 全称块级格式化上下文?什么意思不懂.看了好多博客,基本都是抄的,真心都不是大白话.我今天来总结一下,用菜鸟级别的语言来描述. BFC 应该可以抽象成一个 独立的个体,出淤泥而不染的白莲 ...

  2. k8s部署测试实例

    查看运行中pod,并运行一个容器 [root@mast-1 k8s]# kubectl get pods No resources found. [root@mast-1 k8s]# kubectl ...

  3. softmax_regression完成mnist手写体数据集的识别

    ---恢复内容开始--- import tensorflow as tf from tensorflow.examples.tutorials.mnist import input_data mnis ...

  4. 利用CWinThread实现跨线程父子MFC窗口

    利用CWinThread实现跨线程父子MFC窗口 MFC对象只能由创建该对象的线程访问,而不能由其他线程访问. 不遵守该准则将导致断言(assertion)或者无法预知的程序行为等运行期错误. 在多线 ...

  5. C++中static,extern和extern "C"关键字

    1. extern 变量 extern 表明该变量在别的地方已经定义过了,在这里要使用那个变量. 当extern不与"C"在一起修饰变量或函数时,如在头文件中: extern in ...

  6. 安装Windows10+Ubentu18双系统

    1.先安装Windows系统,安装完成后,使用磁盘管理工具划分出一定的freespace空间留给linux安装系统用. 2.使用Universal-USB-Installer制作ubentu启动U盘. ...

  7. POJ-3278 抓住这头牛

    广搜解决. 广搜搜出最短路,直接输出返回就行了. 每个点只搜一次,而且界限进行一次判断. else 语句里面不要用if    else if,这样的话就直走一条路了. #include <ios ...

  8. rails使用bootstrap

    在Gemfile文件中添加'bootstrap-sass',再运行bundle install gem 'bootstrap-sass' 在config/application.rb添加一行代码,让b ...

  9. (十七)python 3 函数递归

    递归函数 即自己调用自己,递归中可以函数自身调用自身,但是使用时类似于条件循环一样,要有递归的终止条件 优点:使用递归时,常常可以让代码更加简洁 缺点:递归会占用比较多的内存,当递归次数比较多时,性能 ...

  10. Linux 基本操作指南

    Linux基本操作 1. su  切换用户   2.exit 退出当前登录用户 3.useradd 用户名  -m  在home目录下 创建一个和用户名同名的目录,并添加一个用户 (有root权限才能 ...