java NIO实例学习
来源:互联网 发布:qt tcp客户端发送数据 编辑:程序博客网 时间:2024/05/19 13:09
ServerSocketChannel和SocketChannel
在使用传统的ServerSocket和Socket的时候 很多时候程序是会阻塞的,比serverSocket.accept(),socket.getInputStream.read()
会阻塞accept(),除非等到客户端socket的连接或者异常中断,否则会一直等待下去。read()方法也是如此,除非在输入流中有了足够数据,否则该方法也会一直等待下去直到数据的到来。在ServerSocket和Socket方法中,服务器往往要为客户端分配一个线程,而每一个线程都有可能处于长时间的阻塞状态中,而过多的线程也会影响服务器的性能。因此在JDK1.4中引入了非阻塞的通信方式,这样使得服务器端只需要一个线程就能处理所有客户端Socket的请求。
通信实例
上一篇的最后讲了在实例中需要用到的核心类。在这里就不再叙述了。
下面是一个该通信模式下的实例。首先建一个服务器端:
public class NIOServer2{ /*标识数字*/ private int flag = 0; /*缓冲区大小*/ private int BLOCK = 4096; /*接受数据缓冲区*/ private ByteBuffer sendbuffer = ByteBuffer.allocate(BLOCK); /*发送数据缓冲区*/ private ByteBuffer receivebuffer = ByteBuffer.allocate(BLOCK); private Selector selector; public NIOServer2(int port) throws IOException { // 打开服务器套接字通道 ServerSocketChannel serverSocketChannel = ServerSocketChannel.open(); // 服务器配置为非阻塞 serverSocketChannel.configureBlocking(false); // 检索与此通道关联的服务器套接字 ServerSocket serverSocket = serverSocketChannel.socket(); // 进行服务的绑定 serverSocket.bind(new InetSocketAddress(port)); // 通过open()方法找到Selector selector = Selector.open(); // 注册到selector,等待连接 serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT); System.out.println("Server Start----8888:"); } // 监听 private void listen() throws IOException { while (true) { // 选择一组键,并且相应的通道已经打开 selector.select(); // 返回此选择器的已选择键集。 Set<SelectionKey> selectionKeys = selector.selectedKeys(); Iterator<SelectionKey> iterator = selectionKeys.iterator(); while (iterator.hasNext()) { SelectionKey selectionKey = iterator.next(); iterator.remove(); handleKey(selectionKey); } } } // 处理请求 private void handleKey(SelectionKey selectionKey) throws IOException { // 接受请求 ServerSocketChannel server = null; SocketChannel client = null; String receiveText; String sendText; int count=0; // 测试此键的通道是否已准备好接受新的套接字连接。 if (selectionKey.isAcceptable()) { System.out.println("服务器端的通道处于可连接状态。。。"); // 返回为之创建此键的通道。 server = (ServerSocketChannel) selectionKey.channel(); // 接受到此通道套接字的连接。 // 此方法返回的套接字通道(如果有)将处于阻塞模式。 client = server.accept(); // 配置为非阻塞 client.configureBlocking(false); // 注册到selector,等待连接 client.register(selector, SelectionKey.OP_READ); } else if (selectionKey.isReadable()) { System.out.println("服务器端可读。。。"); // 返回为之创建此键的通道。 client = (SocketChannel) selectionKey.channel(); //将缓冲区清空以备下次读取 receivebuffer.clear(); //读取服务器发送来的数据到缓冲区中 count = client.read(receivebuffer); if (count > 0) { receiveText = new String( receivebuffer.array(),0,count); System.out.println("服务器端接受客户端数据--:"+receiveText); client.register(selector, SelectionKey.OP_WRITE); } } else if (selectionKey.isWritable()) { System.out.println("服务器端可写。。。。"); //将缓冲区清空以备下次写入 sendbuffer.clear(); // 返回为之创建此键的通道。 client = (SocketChannel) selectionKey.channel(); sendText="message from server--" + flag++; //向缓冲区中输入数据 sendbuffer.put(sendText.getBytes()); //将缓冲区各标志复位,因为向里面put了数据标志被改变要想从中读取数据发向服务器,就要复位 sendbuffer.flip(); //输出到通道 client.write(sendbuffer); System.out.println("服务器端向客户端发送数据--:"+sendText); client.register(selector, SelectionKey.OP_READ); } } /** * @param args * @throws IOException */ public static void main(String[] args) throws IOException { // TODO Auto-generated method stub int port = 1234; NIOServer2 server = new NIOServer2(port); server.listen(); }}在该类中可以看到,建立服务器的方法是:首先打开服务器套接字通道,并进行服务绑定,然后注册到selector,等待客户端的连接。然后就是监听,实时监听通道的状态。监听的方法是 选择注册的一组键,该组键是一个集合,从中选出已选择的键集,然后通过迭代对每一个键进行处理。
对已选择键进行处理:首先判断其正处的状态:连接就绪、读就绪、写就绪。对不同的状态作相应的处理
客户端:
public class NIOClient { /*标识数字*/ private static int flag = 0; /*缓冲区大小*/ private static int BLOCK = 4096; /*接受数据缓冲区*/ private static ByteBuffer sendbuffer = ByteBuffer.allocate(BLOCK); /*发送数据缓冲区*/ private static ByteBuffer receivebuffer = ByteBuffer.allocate(BLOCK); /*服务器端地址*/ private final static InetSocketAddress SERVER_ADDRESS = new InetSocketAddress( "localhost", 1234); public static void main(String[] args) throws IOException { // TODO Auto-generated method stub // 打开socket通道 SocketChannel socketChannel = SocketChannel.open(); // 设置为非阻塞方式 socketChannel.configureBlocking(false); // 打开选择器 Selector selector = Selector.open(); // 注册连接服务端socket动作 socketChannel.register(selector, SelectionKey.OP_CONNECT); // 连接 socketChannel.connect(SERVER_ADDRESS); // 分配缓冲区大小内存 Set<SelectionKey> selectionKeys; Iterator<SelectionKey> iterator; SelectionKey selectionKey; SocketChannel client; String receiveText; String sendText; int count=0; while (true) { //选择一组键,其相应的通道已为 I/O 操作准备就绪。 //此方法执行处于阻塞模式的选择操作。 selector.select(); //返回此选择器的已选择键集。 selectionKeys = selector.selectedKeys(); //System.out.println(selectionKeys.size()); iterator = selectionKeys.iterator(); while (iterator.hasNext()) { selectionKey = iterator.next(); if (selectionKey.isConnectable()) { System.out.println("client connect"); client = (SocketChannel) selectionKey.channel(); // 判断此通道上是否正在进行连接操作。 // 完成套接字通道的连接过程。 if (client.isConnectionPending()) { client.finishConnect(); System.out.println("完成连接!"); sendbuffer.clear(); sendbuffer.put("Hello,Server".getBytes()); sendbuffer.flip(); client.write(sendbuffer); } client.register(selector, SelectionKey.OP_READ); } else if (selectionKey.isReadable()) { System.out.println("客户端可读。。。。"); client = (SocketChannel) selectionKey.channel(); //将缓冲区清空以备下次读取 receivebuffer.clear(); //读取服务器发送来的数据到缓冲区中 count=client.read(receivebuffer); if(count>0){ receiveText = new String( receivebuffer.array(),0,count); System.out.println("客户端接受服务器端数据--:"+receiveText); client.register(selector, SelectionKey.OP_WRITE); } } else if (selectionKey.isWritable()) { System.out.println("客户端可写。。。"); sendbuffer.clear(); client = (SocketChannel) selectionKey.channel(); sendText = "message from client--" + (flag++); sendbuffer.put(sendText.getBytes()); //将缓冲区各标志复位,因为向里面put了数据标志被改变要想从中读取数据发向服务器,就要复位 sendbuffer.flip(); client.write(sendbuffer); System.out.println("客户端向服务器端发送数据--:"+sendText); client.register(selector, SelectionKey.OP_READ); } } selectionKeys.clear(); } }}
这是一个不断循环的通信实例。在具体的项目中根据自己的需求可进行相应的配置。
0 0
- java NIO实例学习
- JAVA NIO的实例
- Java nio 开发实例
- JAVA NIO 实例
- JAVA NIO 实例
- java NIO 使用实例
- Java NIO实例
- java nio实例一
- JAVA NIO 实例
- JAVA NIO入门实例
- JAVA NIO 实例
- JAVA NIO 实例
- java nio socket 实例
- java nio socket实例
- JAVA NIO 实例
- Java NIO服务器实例
- Java NIO服务器实例
- JAVA NIO 实例
- globalZOrder()与localZOrder()
- SeaJS 中的 exports 和模块加载
- position 定位法,float浮动法
- VirtualBox的入门教程
- 一种项目管理工具WBS CHART PRO介绍
- java NIO实例学习
- 李开复给中国大学生的第四封信
- Bigtable探秘 Google分布式数据存储系统DFS
- Ubuntu 14.04 无线网卡驱动安装(BCM4312)
- 详细解析如何提升设计作品中的价值
- jcifs 查找局域网计算机
- 【C++专题】static_cast, dynamic_cast, const_cast探讨
- 李开复给中国大学生的第五封信
- 网络基础-netsh命令