疯狂Java讲义:使用NIO实现非阻塞Socket通信(2)[2]

 我来答
科创17
2022-10-05 · TA获得超过5988个赞
知道小有建树答主
回答量:2846
采纳率:100%
帮助的人:189万
展开全部

  服务器端的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程序设计培训视频教程

lishixinzhi/Article/program/Java/hx/201311/27262

已赞过 已踩过<
你对这个回答的评价是?
评论 收起
推荐律师服务: 若未解决您的问题,请您详细描述您的问题,通过百度律临进行免费专业咨询

为你推荐:

下载百度知道APP,抢鲜体验
使用百度知道APP,立即抢鲜体验。你的手机镜头里或许有别人想知道的答案。
扫描二维码下载
×

类别

我们会通过消息、邮箱等方式尽快将举报结果通知您。

说明

0/200

提交
取消

辅 助

模 式