NIO Socket实现非阻塞通信示例
2016-11-01 18:01
232 查看
NIO Socket实现非阻塞通信示例
这两天学习了下NIO,写了个练习的demo,如下:服务端步骤
通过ServerSocketChannel.open()方法得到一个ServerSocketChannel通道对象设置通道为非阻塞模式(服务端也可以使用阻塞模式)
通过Selector.open()得到一个选择器
在选择器上注册通道,并设置感兴趣的事件
绑定本地端口并启动服务端
等待处理事件
客户端步骤
获取通道和选择器,注册敢兴趣的事件连接服务端
等待连接成功后发送数据
完整代码
import java.io.IOException; import java.net.InetSocketAddress; 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.Set; import org.junit.Test; public class OneThreadHandleAll { InetSocketAddress isaServer = new InetSocketAddress(7777); InetSocketAddress serverServer = new InetSocketAddress("localhost", 7777); Selector serverSelector; Selector clientSelector; Charset charset = Charset.forName("utf-8"); @Test public void mainTest() throws IOException, InterruptedException { ServerSocketChannel ssc = ServerSocketChannel.open(); ssc.socket().setReuseAddress(true); ssc.configureBlocking(false); serverSelector = Selector.open(); ssc.register(serverSelector, SelectionKey.OP_ACCEPT); ssc.bind(isaServer); Server server = new Server(); server.start(); // clientSelector = Selector.open(); SocketChannel sc = SocketChannel.open(); sc.socket().setReuseAddress(true); sc.configureBlocking(false); SelectionKey sk = sc.register(clientSelector, SelectionKey.OP_CONNECT); System.out.println(Integer.toBinaryString(sk.interestOps())); sc.connect(serverServer); Client client = new Client(); client.start(); Thread.sleep(2000000); } class Client extends Thread { void init() throws IOException, InterruptedException { while (clientSelector.select() > 0) { Set<SelectionKey> keys = clientSelector.selectedKeys(); for (SelectionKey selectionKey : keys) { //打印当前的selectionKey感兴趣的事件 System.out.println(Integer.toBinaryString(selectionKey.interestOps())); //从原始集合中移除当前事件,以免后续重复处理 keys.remove(selectionKey); if (selectionKey.isConnectable()) { System.out.println("Client isConnectable"); SocketChannel sc = (SocketChannel) selectionKey.channel(); sc.finishConnect(); //此处可以注册到clientSelector不会有冲突 sc.register(clientSelector, SelectionKey.OP_READ | SelectionKey.OP_WRITE); } else if (selectionKey.isReadable()) { System.out.println("Client isReadable"); } else if (selectionKey.isWritable()) { System.out.println("Client isWritable"); //发送数据 handleWritable(selectionKey); } } //为了在控制台清晰显示运行过程,让出cpu等待server接收并输出 Thread.sleep(2000); } } int i = 1; private void handleWritable(SelectionKey selectionKey) throws IOException { System.out.println("client writing..."); SocketChannel sc = (SocketChannel) selectionKey.channel(); while (true) { String content = "第" + i + "行数据\n"; if (i % 3 == 0) { content += "bye"; } ByteBuffer bb = ByteBuffer.wrap(content.getBytes()); sc.write(bb); i++; if (i % 3 == 0) { break; } } } @Override public void run() { try { init(); } catch (Exception e) { e.printStackTrace(); } } } class Server extends Thread { void init() throws IOException, InterruptedException { while (serverSelector.select() > 0) { Set<SelectionKey> keys = serverSelector.selectedKeys(); for (SelectionKey selectionKey : keys) { keys.remove(selectionKey); if (selectionKey.isAcceptable()) { System.out.println("Server isAcceptable"); handleAcceptable(selectionKey); } else if (selectionKey.isReadable()) { System.out.println("Server isReadable"); handleRreadable(selectionKey); } else if (selectionKey.isWritable()) { System.out.println("Server isWritable"); } } Thread.sleep(2000); } } private void handleRreadable(SelectionKey selectionKey) throws IOException { SocketChannel sc = (SocketChannel) selectionKey.channel(); ByteBuffer rst = ByteBuffer.allocate(512); while (selectionKey.isReadable()) { sc.read(rst); if (rst.remaining() == rst.capacity()) { System.out.println("server find no data!"); break; } rst.flip(); String rec = charset.decode(rst).toString(); System.out.println("server接收到数据:" + rec); rst.cle a716 ar(); if (rec.endsWith("bye")) { break; } } } private void handleAcceptable(SelectionKey selectionKey) throws IOException { ServerSocketChannel ssc = (ServerSocketChannel) selectionKey.channel(); SocketChannel sc = ssc.accept(); sc.configureBlocking(false); sc.register(serverSelector, SelectionKey.OP_READ | SelectionKey.OP_WRITE); } @Override public void run() { try { init(); } catch (Exception e) { e.printStackTrace(); } } } }
相关文章推荐
- .Net/C#控制台应用程序实现磁盘目录文件搜索的工具类 【本示例简体转繁体】
- XML 简单接口 (SAX2)用Visual Basic 实现的示例
- 一个用Dijkstra算法实现的路由算法的java程序——9 图信息文件示例
- ASP+ADO实现数据读写简单示例
- 简单的System.IFormattable实现示例:
- Survey Admin 示例:实现 Microsoft .NET 基于角色的安全性(转)
- (六)线程--分别用lock以及Interlocked和Monitor类实现线程的临界区操作(互斥)(示例下载)
- 用TreeView控件实现资源管理器(显示本地硬盘下所有文件夹和文件,并可以浏览图片)(示例代码下载)
- 用SHA1或MD5 算法加密数据(示例:对用户身份验证的简单实现)
- Java实现时间日期格式转换示例
- 一个利用反射来实现扩展的小程序示例
- Control Study -> 键盘模拟鼠标(实现用键盘操作鼠标光标)(示例代码下载)
- 分布式编程->Remoting的一个代码示例(借助Remoting实现发送信息功能)
- asp.net中调用javascript函数实现多功能日期控件示例
- 使用Log4j为项目配置日志输出应用详解以及示例演示的实现分析
- 使用 JSSE 和 NIO 实现非阻塞通信的一种快速方法
- asp.net中调用javascript函数实现多功能日期控件示例
- (八)线程--借助 封装类 实现“线程调用带参方法”(示例下载)
- 站点中,实现: 在线签名 功能 (示例代码下载)
- ASP+ADO实现数据读写简单示例