六狼论坛

 找回密码
 立即注册

QQ登录

只需一步,快速开始

新浪微博账号登陆

只需一步,快速开始

搜索
查看: 48|回复: 0

Java NIO 示例入门

[复制链接]

升级  30%

3

主题

3

主题

3

主题

童生

Rank: 1

积分
15
 楼主| 发表于 2013-1-15 02:36:42 | 显示全部楼层 |阅读模式
之前都没有看NIO的类,今天在网上搜索了一下资料,终于做出了个自己比较满意的例子。下面是JAVA代码,至于NIO的概念,网上的资料太多了,这里就不重述了。
  (如果有什么不正确或可以改进的地方,欢迎指出:)
Server.java
package test;import java.io.IOException;import java.net.InetSocketAddress;import java.net.ServerSocket;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.nio.charset.CharsetDecoder;import java.nio.charset.CharsetEncoder;import java.util.Iterator;public class Server extends Thread{private int port;private ServerSocketChannel channel;  // 服务通道private Selector selector;  // 事件selectorprivate ByteBuffer buffer;  // 读取缓冲private CharsetDecoder decoder;  // 字符集支持private CharsetEncoder encoder;  // 字符集支持public Server(int port) throws IOException{this.port = port;selector = Selector.open();  // 创建事件selectorbuffer = ByteBuffer.allocate(1024);  // 创建缓冲decoder = Charset.forName("utf-8").newDecoder();encoder = Charset.forName("utf-8").newEncoder();}public void run(){ServerSocket serverSocket = null;try {channel = ServerSocketChannel.open(); serverSocket = channel.socket(); serverSocket.bind(new InetSocketAddress(port), 20);channel.configureBlocking(false);  // 配置为非堵塞监听// 注册Accept事件 相当于channel.accept方法channel.register(selector, SelectionKey.OP_ACCEPT);  while(true){// 当有注册的事件发生时,返回>0// 空闲时的堵塞时间1000,避免快速的重复循环if(selector.select(1000) > 0){Iterator<SelectionKey> iter = selector.selectedKeys().iterator();while(iter.hasNext()){SelectionKey key = iter.next();// 处理KeyhandleKey(key);// 当一个Key处理完成后,要从就绪(ready)key中移除iter.remove();}}}} catch (IOException e1) {e1.printStackTrace();}finally{try {serverSocket.close();} catch (IOException e) {e.printStackTrace();}}}public void handleKey(SelectionKey key)throws IOException{ // 如果key是注册的SelectionKey.OP_ACCEPTif(key.isAcceptable()){// 此处获取的是服务器通道ServerSocketChannel server = (ServerSocketChannel)key.channel();SocketChannel channel = server.accept();channel.configureBlocking(false);// 相当于channel.accept()之后,注册读取客户端信息的KEYchannel.register(selector, SelectionKey.OP_READ);}// 如果key是注册的SelectionKey.OP_READelse if(key.isReadable()){SocketChannel client = (SocketChannel)key.channel();// 如果buffer是满的,将不能再读进信息buffer.clear();int count = client.read(buffer);if(count > 0 ){// 设置buffer中有效数据的终点位置,并重置起点位置buffer.flip();CharBuffer cb = decoder.decode(buffer);System.out.println("Client>>:" + cb);// 读完之后注册写的KEY,(如果还要继续读取或不需要写就不注册)SelectionKey keyTemp = client.register(selector, SelectionKey.OP_WRITE);// 下次这个key可以把这个字符串取出来keyTemp.attach(cb);}// 如果连接结束else if(count == -1) client.close();} // 如果key是注册的SelectionKey.OP_WRITEelse if(key.isWritable()){SocketChannel channel = (SocketChannel)key.channel();CharBuffer cb = (CharBuffer)key.attachment();channel.write(encoder.encode(CharBuffer.wrap("Re: " + cb)));// 注册读取的KEY (如果不需要读就不注册,但是要在这里关闭连接)channel.register(selector, SelectionKey.OP_READ);}}}

Client.java
package test;import java.io.IOException;import java.io.InputStream;import java.io.OutputStream;import java.net.InetAddress;import java.net.Socket;import java.net.UnknownHostException;import java.nio.charset.Charset;public class Client extends Thread{private Socket socket;private String name;private Charset charset;public Client(int port, String name) throws UnknownHostException, IOException{socket = new Socket(InetAddress.getLocalHost(), port);this.name = name;charset = Charset.forName("utf-8");}public void run(){try {OutputStream os = socket.getOutputStream();os.write(("你好!我是" + name + "。").getBytes(charset));InputStream is = socket.getInputStream();byte temp[] = new byte[1024];int read = is.read(temp);System.out.println("Server>> " + new String(temp, 0, read, charset) + " --by " +  name);os.write(("再见!我是" + name + "。").getBytes(charset));read = is.read(temp);System.out.println("Server>> " + new String(temp, 0, read, charset) + " --by " +  name);} catch (IOException e) {e.printStackTrace();} finally{try {socket.close();} catch (IOException e) {e.printStackTrace();}}}}

Main
int count = 20;Server server = new Server(2900);server.start();Client clients[] = new Client[count];for(int i=0;i<count;i++){clients[i] = new Client(2900, "c" + i);clients[i].start();}
您需要登录后才可以回帖 登录 | 立即注册 新浪微博账号登陆

本版积分规则

快速回复 返回顶部 返回列表