好多年都没用Java里面的NIO写Socket应用了,Mina等框架封装了太多东西,现在重新写个NIO Socket的小例子回顾下。其实NIO写正确还是挺不容易的,太多的东西要注意,这个例子太过简单,要想在生产中使用还有更多的东西要注意,比如读和写由于是非阻塞的,每次操作了多少数据是没保证的,读的数据要进行累积拼接,业务逻辑应在线程池中处理等等。。。
public class TestNioServer { private Selector selector; private List<SocketChannel> channels = new ArrayList<SocketChannel>(); private final byte[] resp; ByteBuffer readBuffer = ByteBuffer.allocate(1024); public TestNioServer(int port) throws IOException { ServerSocketChannel serverSocketChannel = ServerSocketChannel.open(); serverSocketChannel.socket().bind(new InetSocketAddress(port)); serverSocketChannel.configureBlocking(false); selector = Selector.open(); serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT); System.out.println("Server is listening at : " + port); StringBuilder sb = new StringBuilder(); for (int i=0; i<1000; i++) { sb.append("how are you? "); } resp = sb.toString().getBytes(); } public void work() throws IOException { while(true) { selector.select(); //在此处阻塞 Set<SelectionKey> keys = selector.selectedKeys(); /* 此处不可放到另外的线程中处理,原因至少有两个 1. selector.select()阻塞时刚刚accept的连接是无法进行注册的, 注册行为会因select()阻塞,具体请看register方法的说明。 2. 如果读或者写事件没被及时处理会导致无数读或者写触发事件*/ handleSelectionKey(keys, false); } } private void handleSelectionKey(Set<SelectionKey> keys, boolean tryAnsyc) throws IOException { if (keys == null) { System.out.println("keys == null"); return; } Iterator<SelectionKey> itr = keys.iterator(); while (itr.hasNext()) { SelectionKey key = itr.next(); itr.remove(); System.out.println(key); if (key.isAcceptable()) { System.out.println("isAcceptable"); //处理接入的连接 SocketChannel ch = ((ServerSocketChannel)key.channel()).accept(); //此处与read和wirte处不同 ch.configureBlocking(false);//默认是阻塞的 channels.add(ch); //如果想异步地执行handleSelectionKey,可以使用wakeup来解除selector.select()阻塞,否则后面的注册会阻塞 if (tryAnsyc) selector.wakeup(); ch.register(selector, SelectionKey.OP_READ); } //一个SelectionKey可以同时有多个状态,因此此处不可用else if (key.isReadable()) { System.out.println("isReadable"); //处理读数据,每个channel的数据需要进行累积,业务逻辑应在另外的线程中处理 SocketChannel socketChannel = (SocketChannel)key.channel(); int len = socketChannel.read(readBuffer);//此处非阻塞,读到多少数据没任何保证 readBuffer.flip(); byte[] b = new byte[readBuffer.limit()]; readBuffer.get(b); System.out.println("len : " + len + " : " + new String(b)); readBuffer.clear(); //回点数据 socketChannel.register(selector, SelectionKey.OP_WRITE|SelectionKey.OP_READ, ByteBuffer.wrap(resp)); } if (key.isWritable()) { System.out.println("isWritable"); //处理写数据,也可以放在另外的线程中 SocketChannel socketChannel = (SocketChannel)key.channel(); ByteBuffer buf = (ByteBuffer)key.attachment(); while (buf.hasRemaining()) { int writtenLen = socketChannel.write(buf);//非阻塞,每次写多少不能保证 System.out.println("writtenLen=" + writtenLen); } //改成注册读事件,否则会有无数写事件被触发,因为只要是IO处于可写状态就会触发 socketChannel.register(selector, SelectionKey.OP_READ); } if (key.isConnectable()) { //客户端用的,此处ignore } } } public void broadcast() throws ClosedChannelException { for (SocketChannel ch : channels) { ch.register(selector, SelectionKey.OP_WRITE, ByteBuffer.wrap(resp)); //如果selector.select()处在阻塞状态,那么新的register将不会影响到它, //因此需要在此处将其唤醒,以使register生效 selector.wakeup(); } } public static void main(String[] args) throws IOException, InterruptedException { int port = 1234; final TestNioServer server = new TestNioServer(port); new Thread() { public void run() { try { server.work(); } catch (IOException e) { e.printStackTrace(); } } }.start(); Thread.sleep(15000); System.out.println("想要广播?"); server.broadcast(); } }
客户端为了简单,使用的是阻塞模式:
public class TestSocketClient { public static void main(String[] args) throws UnknownHostException, IOException, InterruptedException { int port = 1234; Socket socket = new Socket(); socket.connect(new InetSocketAddress(InetAddress.getByName("localhost"), port)); final InputStream is = socket.getInputStream(); OutputStream os = socket.getOutputStream(); new Thread () { public void run() { for (;;) { byte[] b = new byte[1024]; try { is.read(b); } catch (IOException e) { e.printStackTrace(); break; } System.out.println(new String(b)); } } }.start(); for (int i=0; i<3; i++) { os.write(new byte[]{65}); os.flush(); System.out.println("written"); Thread.sleep(1000); } } }
相关推荐
**Socket编程在NIO中的应用**: 1. **ServerSocketChannel**:用于监听客户端连接,通过调用`ServerSocketChannel.open()`创建,然后绑定到指定的IP和端口,并调用`accept()`方法接收客户端连接。 2. **...
使用NIO socket不需要多线程来处理多个连接的请求,效率非常高 可以作为NIO socket入门的例子,Reactor模式,重点理解key.attach, jar文件里包含了源代码 1,运行server.bat启动服务器,可以打开编辑,修改端口号 ...
本例包含服务器端和客户端,多线程,每线程多次发送,Eclipse工程,启动服务器使用 nu.javafaq.server.NioServer,启动客户端使用 nu.javafaq.client.NioClient。另本例取自javafaq.nv上的程序修改而成
### Java NIO 实现Socket通信详解 #### 一、NIO与传统IO的区别及优势 在探讨如何使用Java NIO实现Socket通信之前,我们需要先理解NIO(Non-blocking I/O,非阻塞I/O)与传统阻塞I/O之间的区别。 **传统阻塞I/O...
`Socket`在NIO中的实现是`SocketChannel`,它代表了网络上的一个连接。`ServerSocketChannel`则用于监听客户端的连接请求。通过`ServerSocketChannel`的`accept()`方法,服务器可以接收新的客户端连接,然后将其注册...
Ioserver java Nio socket 框架 是个不错的NIO 通讯框架,本来想学习mina框架,看了看mina的源码太头痛,本人觉得看懂了Ioserver 再看mina的框架,想多的学习 java NIO 的也可以下载 看看,很值得学习啊!!!
java NIO和java并发编程的书籍java NIO和java并发编程的书籍java NIO和java并发编程的书籍java NIO和java并发编程的书籍java NIO和java并发编程的书籍java NIO和java并发编程的书籍java NIO和java并发编程的书籍java...
在这个“基于java NIO的socket通信demo”中,我们将探讨如何使用NIO进行服务器和客户端的Socket通信,并解决通信过程中的字符集乱码问题。 首先,我们来看`NioServer.java`。这个文件中包含了一个基于NIO的服务器端...
NioSocket是一个基于Java NIO(非阻塞I/O)技术实现的网络通信框架,它包含服务器端(Server)和客户端(Client)两部分。在Java编程中,NIO(New Input/Output)提供了一种不同于传统IO模型的I/O操作方式,其核心...
Java NIO系列教程(一) Java NIO 概述 Java NIO系列教程(二) Channel Java NIO系列教程(三) Buffer Java NIO系列教程(四) Scatter/Gather Java NIO系列教程(五) 通道之间的数据传输 Java NIO系列教程(六)...
标题“nio.rar_NIO_NIO-socket_java nio_java 实例_java.nio”表明这个压缩包包含了一个关于Java NIO的实例,特别是关于NIO套接字(Socket)的编程示例。NIO套接字是Java NIO库中用于网络通信的关键组件,它们允许...
标题中的“Java socketA_java nio_java socket a”可能是指使用Java NIO实现的Socket通信,这里的"A"可能是表示"Advanced"或"Alternative",意味着比传统的阻塞I/O模型更为高级或替代方案。 在Java Socket API中,...
Java NIO,全称为Non-Blocking Input/Output(非阻塞输入/输出),是Java标准库提供的一种替代传统的I/O模型的新技术。自Java 1.4版本引入NIO后,它为Java开发者提供了更高效的数据传输方式,尤其是在处理大量并发...
Java NIO,全称为Non-Blocking Input/Output(非阻塞输入/输出),是Java平台中用于替代标准I/O(BIO)模型的一种新机制。NIO在Java 1.4版本引入,提供了更高效的数据处理和通道通信方式,特别适用于高并发、大数据...
《网络通信测试与Java NIO Socket编程详解》 在信息技术高速发展的今天,网络通信成为了软件开发中的重要一环。为了确保网络应用的稳定性和效率,网络通信测试工具扮演了不可或缺的角色。"默蓝网络通信测试工具(NIO...
在Java编程领域,Socket是网络通信的基础,它允许两个或多个应用程序通过TCP/IP协议进行数据交换。本篇文章将深入探讨如何使用Java NIO(非阻塞I/O)来实现阻塞多线程通信,这对于高性能服务器端应用尤其重要。我们...
Java NIO 深入探讨了 1.4 版的 I/O 新特性,并告诉您如何使用这些特性来极大地提升您所写的 Java 代码的执行效率。这本小册子就程序员所面临的有代表性的 I/O 问题作了详尽阐述,并讲解了 如何才能充分利用新的 I/O ...
Java NIO(New IO)是一个可以替代标准Java IO API的IO API(从Java 1.4开始),Java NIO提供了与标准IO不同的IO工作方式。 Java NIO: Channels and Buffers(通道和缓冲区) 标准的IO基于字节流和字符流进行操作的,...