知识大全 使用NIO实现非阻塞Socket通信(2)[2]

Posted

篇首语:归志宁无五亩园,读书本意在元元。本文由小常识网(cha138.com)小编为大家整理,主要介绍了知识大全 使用NIO实现非阻塞Socket通信(2)[2]相关的知识,希望对你有一定的参考价值。

疯狂Java讲义:使用NIO实现非阻塞Socket通信(2)[2]  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!

  服务器端的Selector仅需要监听两种操作 连接和读数据 所以程序中分别处理了这两种操作 如程序中②和③代码所示 处理连接操作之时 系统只需将接受连接后产生的SocketChannel注册到指定Selector对象即可 处理读数据操作之时 系统先从该Socket中读取数据 再将数据写入Selector上注册的所有Channel

  使用NIO来实现服务器时 甚至无须使用ArrayList来保存服务器中所有SocketChannel 因为所有的SocketChannel都需要注册到指定的Selector对象 除此之外 当客户端关闭时会导致服务器对应的Channel也抛出异常 而且本程序只有一条线程 如果该异常得不到处理将会导致整个服务器退出 所以程序捕捉了这种异常 并在处理异常时从Selector删除异常Channel的注册 如程序中斜体字代码所示

  本示例程序的客户端程序需要两个线程 一个线程负责读取用户的键盘输入 并将输入的内容写入SocketChannel中 另一个线程则不断地查询Selector对象的select()方法的返回值

  程序清单 codes/ / /NoBlock/NClient java

  public class NClient

  

  //定义检测SocketChannel的Selector对象

  private Selector selector = null;

  //定义处理编码和解码的字符集

  private Charset charset = Charset forName( UTF )

  //客户端SocketChannel

  private SocketChannel sc = null;

  public void init()throws IOException

  

  selector = Selector open()

  InetSocketAddress isa = new InetSocketAddress( )

  //调用open静态方法创建连接到指定主机的SocketChannel

  sc = SocketChannel open(isa)

  //设置该sc以非阻塞方式工作

  sc configureBlocking(false)

  //将SocketChannel对象注册到指定Selector

  sc register(selector SelectionKey OP_READ)

  //启动读取服务器端数据的线程

  new ClientThread() start()

  //创建键盘输入流

  Scanner scan = new Scanner(System in)

  while (scan hasNextLine())

  

  //读取键盘输入

  String line = scan nextLine()

  //将键盘输入的内容输出到SocketChannel中

  sc write(charset encode(line))

  

  

  //定义读取服务器数据的线程

  private class ClientThread extends Thread

  

  public void run()

  

  try

  

  while (selector select() > )

  

  //遍历每个有可用IO操作Channel对应的SelectionKey

  for (SelectionKey sk : selector selectedKeys())

  

  //删除正在处理的SelectionKey

  selector selectedKeys() remove(sk)

  //如果该SelectionKey对应的Channel中有可读的数据

  if (sk isReadable())

  

  //使用NIO读取Channel中的数据

  SocketChannel sc = (SocketChannel)sk channel()

  ByteBuffer buff = ByteBuffer allocate( )

  String content = ;

  while(sc read(buff) > )

  

  sc read(buff)

  buff flip()

  content += charset decode(buff)

  

  //打印输出读取的内容

  System out println( 聊天信息 + content)

  //为下一次读取作准备

  sk interestOps(SelectionKey OP_READ)

  

  

  

  

  catch (IOException ex)

  

  ex printStackTrace()

  

  

  

  public static void main(String[] args)

  throws IOException

  

  new NClient() init()

  

  

  相比之下 客户端程序比服务器程序要简单多了 客户端只有一条SocketChannel 将该SocketChannel注册到指定Selector后 程序启动另一条线程来监测该Selector即可

       返回目录 疯狂Java讲义

       编辑推荐

       Java程序性能优化 让你的Java程序更快 更稳定

       新手学Java 编程

       Java程序设计培训视频教程

cha138/Article/program/Java/hx/201311/27262

相关参考