【练习代码】写了基于java nio的RepeatServer -- by auzll
2013-10-09 09:18
417 查看
昨天在翻看mina源码时,突然想起我貌似还没直接写过基于java nio的代码,于是今天想抓紧练习下,写段小程序。
这段小程序可以在terminal用telnet连服务器端,输入内容,当服务器收到内容之后,会在控制台打印输出,接着再把这些内容稍做“包装”并返回给客户端terminal。程序里面还支持是否强制使用java epoll (配置个系统参数 java.nio.channels.spi.SelectorProvider = sun.nio.ch.EPollSelectorProvider就可以了),不过当然这得看运行环境了,对linux版本和java版本都有要求。下面直接贴贴代码:
发布在 http://auzll.iteye.com
这段小程序可以在terminal用telnet连服务器端,输入内容,当服务器收到内容之后,会在控制台打印输出,接着再把这些内容稍做“包装”并返回给客户端terminal。程序里面还支持是否强制使用java epoll (配置个系统参数 java.nio.channels.spi.SelectorProvider = sun.nio.ch.EPollSelectorProvider就可以了),不过当然这得看运行环境了,对linux版本和java版本都有要求。下面直接贴贴代码:
package niotest; import java.io.IOException; import java.net.InetSocketAddress; import java.nio.ByteBuffer; import java.nio.CharBuffer; 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.Iterator; /** * 基于java nio的RepeatServer。 * 可以在terminal用telnet连服务器端,输入内容,当服务器收到内容之后,会在控制台打 * 印输出,接着再把这些内容稍做“包装”并返回给客户端terminal。 * * @author auzll */ public final class RepeatServer { private ServerSocketChannel serverSocketChannel; private Selector selector; private static final String SELECTOR_PROVIDER_KEY = "java.nio.channels.spi.SelectorProvider"; private static final String EPOLL_SELECTOR_CLASS = "sun.nio.ch.EPollSelectorProvider"; public RepeatServer(boolean epoll, int port) throws IOException { if (epoll) { // 强制设置使用java epoll,需要linux和java版本的支持 // 在我写这个测试代码的时候,我的机器环境是默认使用了EPollSelectorProvider System.setProperty(SELECTOR_PROVIDER_KEY, EPOLL_SELECTOR_CLASS); } serverSocketChannel = ServerSocketChannel.open(); serverSocketChannel.configureBlocking(false); serverSocketChannel.socket().setReuseAddress(true); serverSocketChannel.bind(new InetSocketAddress(port)); selector = Selector.open(); // 仅注册OP_ACCEPT serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT); System.out.println(String.format("*** Server start on %d , selector provider class is %s ***", port, selector.provider().getClass().getName())); } /** * 处理客户端连接,并注册读事件 */ private void handleAcceptable(SelectionKey readyKey) throws IOException { ServerSocketChannel serverSocketChannel = (ServerSocketChannel) readyKey.channel(); SocketChannel socketChannel = serverSocketChannel.accept(); socketChannel.configureBlocking(false); ByteBuffer byteBuffer = ByteBuffer.allocate(1024); socketChannel.register(selector, SelectionKey.OP_READ, byteBuffer); } /** * 处理读事件 */ private void handleReadable(SelectionKey readyKey) throws IOException { SocketChannel socketChannel = (SocketChannel) readyKey.channel(); ByteBuffer readBuff = ByteBuffer.allocate(1024); Charset charset = Charset.defaultCharset(); boolean gotData = false; while ( socketChannel.read(readBuff) > 0 ) { gotData = true; // 注册写事件 readyKey.interestOps(readyKey.interestOps() | SelectionKey.OP_WRITE); readBuff.flip(); CharBuffer charBuffer = charset.decode(readBuff); String repeatData = "We got: [" + charBuffer.toString().trim() + "]\r\n"; System.out.println(repeatData); ByteBuffer attachBuff = (ByteBuffer) readyKey.attachment(); attachBuff.clear(); attachBuff.put(charset.encode(repeatData)); } if (!gotData) { // 完全读不到数据的情况下,取消注册读事件 readyKey.interestOps(readyKey.interestOps() & ~SelectionKey.OP_READ); } } /** * 处理写事件 */ private void handleWriteable(SelectionKey readyKey) throws IOException { SocketChannel socketChannel = (SocketChannel) readyKey.channel(); ByteBuffer attachBuff = (ByteBuffer) readyKey.attachment(); attachBuff.flip(); socketChannel.write(attachBuff); // 取消注册写事件 readyKey.interestOps(readyKey.interestOps() & ~SelectionKey.OP_WRITE); } /** * 开始服务 */ public void start() throws IOException { int selected = 0; while ((selected = selector.select()) > 0) { System.out.println("selected is " + selected); Iterator<SelectionKey> readyKeys = selector.selectedKeys().iterator(); while (readyKeys.hasNext()) { SelectionKey readyKey = readyKeys.next(); readyKeys.remove(); if (!readyKey.isValid()) { continue; } if (readyKey.isAcceptable()) { handleAcceptable(readyKey); } if (readyKey.isReadable()) { handleReadable(readyKey); } if (readyKey.isWritable()) { handleWriteable(readyKey); } } } } public static void main(String[] args) throws Exception { // 开始测试 new RepeatServer(false, 9876).start(); } }
发布在 http://auzll.iteye.com
相关文章推荐
- Hadoop基于Protocol Buffer的RPC实现代码分析-Server端
- Hadoop基于Protocol Buffer的RPC实现代码分析-Server端
- Hadoop基于Protocol Buffer的RPC实现代码分析-Server端
- 使用VisualSVN Server快速搭建基于SVN的代码版本控制服务器
- Hadoop基于Protocol Buffer的RPC实现代码分析-Server端--转载
- Hadoop基于Protocol Buffer的RPC实现代码分析-Server端
- Hadoop RPC Server基于Reactor模式和Java NIO 的架构和原理
- 【matlab代码练习9】基于连通域提取感兴趣区域
- Cosmos动手练习(基于里程碑2的代码)--.net/C#开源操作系统学习系列十
- DllRegisterServer的调用失败,错误代码为0x80040200 (vista手动注册ocx dll问题)
- 十三种基于直方图的图像全局二值化算法原理、实现、代码及效果。
- zookeeper注册中心两套环境 部分代码一致 例如两套不同的sso-server怎么区分 dubbo-monitor怎么监控
- Java NIO系列教程(九) ServerSocketChannel
- 基于JQuery EasyUI、Web Api的 ASP.NET MVC 代码生成插件
- 基于Java HttpClient和Htmlparser实现网络爬虫代码
- 重构一段基于原生JavaScript的表格绘制代码
- 基于QTcpSocket和QTcpServer的Tcp通讯以及QDataStream序列化数据
- Spice代码阅读一:Spice Client 与 Spice Server 通道建立过程
- Struts2练习--基于注解方式Action配置