`
shihuan830619
  • 浏览: 574129 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

Java.nio

    博客分类:
  • J2SE
阅读更多
附件里为阻塞模式、非阻塞模式、阻塞和非阻塞的混合模式代码。

下面为非阻塞的一段客户端和服务器的代码:
服务器端代码:
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;
import java.util.Set;

/**
 * 非阻塞模式服务器
 * */
public class EchoNoblockServer {

	private Selector selector = null;
	private ServerSocketChannel serverSocketChannel = null;
	private int port = 8000;
	private Charset charset = Charset.forName("GBK");
	
	public EchoNoblockServer() throws IOException{
		selector = Selector.open();
	    serverSocketChannel = ServerSocketChannel.open();
	    serverSocketChannel.socket().setReuseAddress(true);
	    serverSocketChannel.configureBlocking(false);
	    serverSocketChannel.socket().bind(new InetSocketAddress(port));
	    System.out.println("服务器启动");
	}
	
	public void service() throws IOException{
		serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
	    while (selector.select() > 0){
	    	Set readyKeys = selector.selectedKeys();
	    	Iterator it = readyKeys.iterator();
	    	while (it.hasNext()){
	    		SelectionKey key = null;
	    		try{
	    			key = (SelectionKey) it.next();
	    			it.remove();

	    			if (key.isAcceptable()) {
	    				ServerSocketChannel ssc = (ServerSocketChannel) key.channel();
	    				SocketChannel socketChannel = (SocketChannel) ssc.accept();
	    				System.out.println("接收到客户连接,来自:" + socketChannel.socket().getInetAddress() + ":" + socketChannel.socket().getPort());
	    				socketChannel.configureBlocking(false);
	    				ByteBuffer buffer = ByteBuffer.allocate(1024);
	    				socketChannel.register(selector, SelectionKey.OP_READ | SelectionKey.OP_WRITE, buffer);
	            }
	            if (key.isReadable()) {
	                receive(key);
	            }
	            if (key.isWritable()) {
	                send(key);
	            }
	        }catch(IOException e){
	           e.printStackTrace();
	           try{
	               if(key != null){
	                   key.cancel();
	                   key.channel().close();
	               }
	           }catch(Exception ex){
	        	   e.printStackTrace();
	           }
	        }
	      }//#while
	   }//#while
	}
	
	public void send(SelectionKey key) throws IOException{
	    ByteBuffer buffer = (ByteBuffer)key.attachment();
	    SocketChannel socketChannel = (SocketChannel)key.channel();
	    buffer.flip();  //把极限设为位置,把位置设为0
	    String data = decode(buffer);
	    if(data.indexOf("\r\n") == -1) return;
	    String outputData = data.substring(0, data.indexOf("\n")+1);
	    System.out.print(outputData);
	    ByteBuffer outputBuffer = encode("echo:"+outputData);
	    while(outputBuffer.hasRemaining())
	    	socketChannel.write(outputBuffer);

	    ByteBuffer temp = encode(outputData);
	    buffer.position(temp.limit());
	    buffer.compact();

	    if(outputData.equals("bye\r\n")){
	    	key.cancel();
	    	socketChannel.close();
	    	System.out.println("关闭与客户的连接");
	    }
	}

	public void receive(SelectionKey key) throws IOException{
	    ByteBuffer buffer = (ByteBuffer)key.attachment();

	    SocketChannel socketChannel = (SocketChannel)key.channel();
	    ByteBuffer readBuff = ByteBuffer.allocate(32);
	    socketChannel.read(readBuff);
	    readBuff.flip();

	    buffer.limit(buffer.capacity());
	    buffer.put(readBuff);
	}

	public String decode(ByteBuffer buffer){  //解码
	    CharBuffer charBuffer = charset.decode(buffer);
	    return charBuffer.toString();
	}
	public ByteBuffer encode(String str){  //编码
	    return charset.encode(str);
	}
	
	/**
	 * @param args
	 */
	public static void main(String[] args) {
		EchoNoblockServer server;
		try {
			server = new EchoNoblockServer();
			server.service();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

}

客户端代码:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.InetAddress;
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.SocketChannel;
import java.nio.charset.Charset;
import java.util.Iterator;
import java.util.Set;

/**
 * 非阻塞模式客户端
 * */
public class EchoNoblockClient {

	private SocketChannel socketChannel = null;
	private ByteBuffer sendBuffer = ByteBuffer.allocate(1024);
	private ByteBuffer receiveBuffer = ByteBuffer.allocate(1024);
	private Charset charset = Charset.forName("GBK");
	private Selector selector;
	
	public EchoNoblockClient() throws IOException {
		socketChannel = SocketChannel.open();
	    InetAddress ia = InetAddress.getLocalHost();
	    InetSocketAddress isa = new InetSocketAddress(ia, 8000);
	    socketChannel.connect(isa);
	    socketChannel.configureBlocking(false);
	    System.out.println("与服务器的连接建立成功");
	    selector=Selector.open();
	}
	
	public void receiveFromUser(){
		try{
			BufferedReader localReader = new BufferedReader(new InputStreamReader(System.in));
			String msg = null;
			while((msg=localReader.readLine()) != null){
				synchronized(sendBuffer){
					sendBuffer.put(encode(msg + "\r\n"));
				}
				if(msg.equals("bye"))
					break;
			}
	    }catch(IOException e){
	       e.printStackTrace();
	    }
	}

	public void talk() throws IOException {
		socketChannel.register(selector, SelectionKey.OP_READ | SelectionKey.OP_WRITE);
	    while (selector.select() > 0){
	    	Set readyKeys = selector.selectedKeys();
	    	Iterator it = readyKeys.iterator();
	    	while (it.hasNext()){
	    		SelectionKey key = null;
	    		try{
	    			key = (SelectionKey) it.next();
	    			it.remove();

	    			if (key.isReadable()) {
	    				receive(key);
	    			}
	    			if (key.isWritable()) {
	    				send(key);
	    			}
	    		}catch(IOException e){
	    			e.printStackTrace();
	    			try{
	    				if(key != null){
	    					key.cancel();
	    					key.channel().close();
	    				}
	    			}catch(Exception ex){
	    				e.printStackTrace();
	    			}
	    		}
	    	}//#while
	    }//#while
	}

	public void send(SelectionKey key) throws IOException{
		SocketChannel socketChannel = (SocketChannel)key.channel();
		synchronized(sendBuffer){
			sendBuffer.flip();  //把极限设为位置
			socketChannel.write(sendBuffer);
			sendBuffer.compact();
		}
	}
	public void receive(SelectionKey key) throws IOException{
		SocketChannel socketChannel = (SocketChannel)key.channel();
		socketChannel.read(receiveBuffer);
		receiveBuffer.flip();
		String receiveData = decode(receiveBuffer);

		if(receiveData.indexOf("\n") == -1) return;

		String outputData = receiveData.substring(0, receiveData.indexOf("\n")+1);
		System.out.print(outputData);
		if(outputData.equals("echo:bye\r\n")){
			key.cancel();
			socketChannel.close();
			System.out.println("关闭与服务器的连接");
			selector.close();
			System.exit(0);
		}

		ByteBuffer temp = encode(outputData);
		receiveBuffer.position(temp.limit());
		receiveBuffer.compact();
	}

	public String decode(ByteBuffer buffer){  //解码
	    CharBuffer charBuffer = charset.decode(buffer);
	    return charBuffer.toString();
	}
	public ByteBuffer encode(String str){  //编码
		return charset.encode(str);
	}
	
	/**
	 * @param args
	 */
	public static void main(String[] args) {
		final EchoNoblockClient client;
		try {
			client = new EchoNoblockClient();
			Thread receiver = new Thread(){
		    	public void run(){
		    		client.receiveFromUser();
		    	}
		    };

		    receiver.start();
		    client.talk();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

}

Ping客户端代码:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
import java.util.LinkedList;

/**
 * 非阻塞模式Ping客户端
 * */
public class PingNoblockClient {

	private Selector selector;
	//存放用户新提交的任务
	private LinkedList targets = new LinkedList();
	//存放已经完成的需要打印的任务
	private LinkedList finishedTargets = new LinkedList();
	
	public PingNoblockClient() throws IOException{
		selector=Selector.open();
	    Connector connector = new Connector();
	    Printer printer = new Printer();
	    connector.start();
	    printer.start();
	    receiveTarget();
	}
	
	public void addTarget(Target target) {
		//向targets队列中加入一个任务
	    SocketChannel socketChannel = null;
	    try {
	    	socketChannel = SocketChannel.open();
	        socketChannel.configureBlocking(false);
	        socketChannel.connect(target.address);

	        target.channel = socketChannel;
	        target.connectStart = System.currentTimeMillis();

	        synchronized (targets) {
	        	targets.add(target);
	        }
	        selector.wakeup();
	    } catch (Exception x) {
	    	if (socketChannel != null) {
	    		try {
	    			socketChannel.close();
	            } catch (IOException xx) { }
	        }
	        target.failure = x;
	        addFinishedTarget(target);
	    }
	}
	
	public void addFinishedTarget(Target target) {
		//向finishedTargets队列中加入一个任务
	    synchronized (finishedTargets) {
	    	finishedTargets.notify();
	    	finishedTargets.add(target);
	    }
	}
	
	public void printFinishedTargets() {
		//打印finisedTargets队列中的任务
	    try {
	    	for (;;) {
	    		Target target = null;
	            synchronized (finishedTargets) {
	                while (finishedTargets.size() == 0)
	                    finishedTargets.wait();
	                target = (Target)finishedTargets.removeFirst();
	            }
	            target.show();
	        }
	    } catch (InterruptedException x) {
	        return;
	    }
	}
	
	public void registerTargets(){
		//取出targets队列中的任务,向Selector注册连接就绪事件
	    synchronized (targets) {
	    	while (targets.size() > 0) {
	    		Target target = (Target)targets.removeFirst();

	    		try {
	    			target.channel.register(selector, SelectionKey.OP_CONNECT, target);
	    		} catch (IOException x) {
	    			try{
	    				target.channel.close();
	    			}catch(IOException e){
	    				e.printStackTrace();
	    			}
	    			target.failure = x;
	    			addFinishedTarget(target);
	    		}
	    	}
	    }
	}
	
	public void processSelectedKeys() throws IOException {
		//处理连接就绪事件
	    for (Iterator it = selector.selectedKeys().iterator(); it.hasNext();) {
	    	SelectionKey selectionKey = (SelectionKey)it.next();
	    	it.remove();

	    	Target target = (Target)selectionKey.attachment();
	    	SocketChannel socketChannel = (SocketChannel)selectionKey.channel();

	    	try {
	    		if (socketChannel.finishConnect()) {
	    			selectionKey.cancel();
	    			target.connectFinish = System.currentTimeMillis();
	    			socketChannel.close();
	    			addFinishedTarget(target);
	    		}
	    	} catch (IOException x) {
	    		socketChannel.close();
	    		target.failure = x;
	    		addFinishedTarget(target);
	    	}
	    }
	}
	
	public void receiveTarget(){
		//接收用户输入的地址,向targets队列中加入任务
	    try{
	    	BufferedReader localReader = new BufferedReader(new InputStreamReader(System.in));
	    	String msg=null;
	    	while((msg=localReader.readLine()) != null){
	    		if(!msg.equals("bye")){
	    			Target target = new Target(msg);
	    			addTarget(target);
	    		}else{
	    			shutdown = true;
	    			selector.wakeup();
	    			break;
	    		}
	    	}
	    }catch(IOException e){
	    	e.printStackTrace();
	    }
	}
	
	/**
	 * @param args
	 */
	public static void main(String[] args) {
		try {
			new PingNoblockClient();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
	boolean shutdown = false;
	
	public class Printer extends Thread{
		public Printer(){
			setDaemon(true);
	    }
	    public void run(){
	        printFinishedTargets();
	    }
	}

	public class Connector extends Thread{
		public void run(){
	        while (!shutdown) {
	            try {
	                registerTargets();
	                if (selector.select() > 0) {
	                    processSelectedKeys();
	                }
	            } catch (Exception e) {
	                e.printStackTrace();
	            }
	       }
	       try{
	           selector.close();
	       }catch(IOException e){e.printStackTrace();}
		}
	}
}

class Target {  //表示一项任务
	InetSocketAddress address;
	SocketChannel channel;
	Exception failure;
	long connectStart;  //开始连接时的时间
	long connectFinish = 0;  //连接成功时的时间
	boolean shown = false;  //该任务是否已经打印

	Target(String host) {
		try {
			address = new InetSocketAddress(InetAddress.getByName(host), 80);
	    } catch (IOException x) {
	    	failure = x;
	    }
	}

	void show() {  //打印任务执行的结果
		String result;
	    if (connectFinish != 0)
	    	result = Long.toString(connectFinish - connectStart) + "ms";
	    else if (failure != null)
	    	result = failure.toString();
	    else
	        result = "Timed out";
	    
	    System.out.println(address + " : " + result);
	    shown = true;
	}
}
分享到:
评论

相关推荐

    Java.NIO资源下载资源下载

    Java.NIO资源下载资源下载

    Java.nio 与Java.io比较

    Java.nio 与Java.io比较

    优雅的操作文件:java.nio.file 库介绍.pdf

    但 Java 在后期版本中引入了 java.nio.file 库来提高 Java 对文件操作的能力。还增加的流的功能,似乎使得文件变成更好用了。所以本章,我们就来主要介绍 java.nio.file 中常用的类和模块,大致如下: Path 路径:...

    java.io:clojure.java.io 的 JK7 java.nio.file.Path 兼容性

    java.io clojure.java.io 的 JK7 java.nio.file.Path 兼容性依赖信息该库托管在 Releases 上。 依赖: [me.moocar/java.io " 0.1.0 " ]用法是 JDK7 中引入的文件路径的抽象。 这个库提供了和 Paths 之间的兼容性。 ...

    java.nio新功能的优点

    java 1.4中推出的java.nio(新输入/输出)软件包允许像在其他低级语言——如C语言——中一样进行输入/输出。许多开发者认为这些新功能只能进行非阻塞操作;但是,这些新功能提供许多其他新鲜有趣的特性,它们包括:...

    The_Study_about_Java.nio.rar_java nio

    java.nio包的学习总结,看看确实有收获

    Java.NIO_网络编程_入门讲解

    Java.NIO_网络编程_入门讲解,初学者适合的资料

    nio:Clojure对java.nio的支持

    o Clojure对java.nio的支持。 将clojure.java.io的输入流,输出流和复制功能扩展到java.nio类。 定义新的强制功能缓冲区,字节缓冲区,字符缓冲区,双缓冲区,浮点缓冲区,整数缓冲区,长缓冲区,短缓冲区,通道,可...

    java.nio(socket异步通讯完整版)

    重新写的Java.nio的socket异步通讯,包含客户端及服务端完整版, 注:解析信息CLASS及进制转换CLASS需要自己去写,项目直接导入,需要自己写一些解析及转换类,这样你才能读懂SOCKET的异步,否则光拿代码没用 ...

    java org.apache.http.nio jar包

    找了好久,终于找到了,java刷新同步获取网络资源

    JDK1.7 之java.nio.file.Files 读取文件仅需一行代码实现

    下面小编就为大家分享一篇JDK1.7 之java.nio.file.Files 读取文件仅需一行代码实现,具有很好的参考价值,希望对大家有所帮助

    nio.rar_NIO_NIO-socket_java nio_java 实例_java.nio

    java nio 编程一个实例子.服务端程序

    java.nio demo

    Java的IO操作集中在java.io这个包中,是基于流的同步(blocking)API。对于大多数应用来说,这样的API使用很方便,然而,一些对性能要求较高的应用,尤其是服务端应用,往往需要一个更为有效的方式来处理IO。从JDK ...

    java.nio API详解

    在JDK 1.4以前,Java的IO操作集中在java.io这个包中,是基于流的同步(blocking)API。对于大多数应用来说,这样的API使用很方便,然而,一些对性能要求较高的应用,尤其是服务端应用,往往需要一个更为有效的方式来...

    java NIO详细教程

    java NIO详细教程,包括使用背景,实现原理,代码实现

    dirwatch:Clojure目录观察程序,包装了JDK 7 java.nio.file.WatchService

    目录监视 监视目录以查找更改。 类似于t望塔(但使用JDK 7异步... ( watch-dir println ( clojure.java.io/file " /tmp " )) 执照 版权所有:copyright:2013 JUXT。 与clojure一样,根据Eclipse Public License分发。

    java nio.doc

    java.nio.charset 包中定义了字符集 API,java.nio.channels 包中定义了信道和选择器 API。每个子包都具有自己的服务提供程序接口 (SPI) 子包,SPI 子包的内容可用于扩展平台的默认实现或构造替代实现。

    java NIO.zip

    java NIO.zip

Global site tag (gtag.js) - Google Analytics