`
shihuan830619
  • 浏览: 583862 次
  • 性别: 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.io比较

    在探讨Java.nio与Java.io之间的比较时,我们首先需要理解这两个包在Java编程语言中的核心作用和它们各自的优势。Java.io和Java.nio是Java中处理输入/输出操作的两个主要框架,它们各自拥有独特的特性和应用场景。 #...

    Java.NIO资源下载资源下载

    根据提供的文件信息,我们可以提取并总结出关于Java NIO(New Input/Output)的重要知识点。 ### Java NIO 概述 Java NIO 是 Java 平台的一个重要特性,首次出现在 Java 1.4 版本中。它为 Java 开发者提供了一套...

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

    【java.nio.file库详解】 Java 早期版本的文件I/O操作功能相对有限,存在几个显著问题:不支持现代文件系统特性、API设计复杂且冗长、处理大文件和并发性能不足。为了解决这些问题,Java引入了`java.nio.file`库,...

    nio.rar_NIO_NIO-socket_java nio_java 实例_java.nio

    标题“nio.rar_NIO_NIO-socket_java nio_java 实例_java.nio”表明这个压缩包包含了一个关于Java NIO的实例,特别是关于NIO套接字(Socket)的编程示例。NIO套接字是Java NIO库中用于网络通信的关键组件,它们允许...

    java.nio API详解

    3. `java.nio.charset`:这个包提供了字符编码和解码的相关类,如Charset、CharsetDecoder和CharsetEncoder,用于处理字符串和字节之间的转换。 4. `java.nio.charset.spi`:这是一个服务提供者接口(SPI)包,定义...

    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 之间的兼容性。 ...

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

    JDK1.7 之 java.nio.file.Files 读取文件仅需一行代码实现 java.nio.file.Files 类是 JDK1.7 中引入的新的文件操作类,该类包含了许多有用的方法来操作文件。其中,Files.readAllBytes(Path) 方法可以将整个文件...

    nio:Clojure对java.nio的支持

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

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

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

    java.NIO与Files工具类(解决方案).md

    java.NIO与Files工具类(解决方案).md

    java.NIO与Files工具类(处理方案示例).md

    java.NIO与Files工具类(处理方案示例).md

    java org.apache.http.nio jar包

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

    java NIO.zip

    Java NIO,全称为Non-Blocking Input/Output(非阻塞输入/输出),是Java标准库提供的一种替代传统的I/O模型的新技术。自Java 1.4版本引入NIO后,它为Java开发者提供了更高效的数据传输方式,尤其是在处理大量并发...

    用java修改文件的编码

    2. **`java.nio`包中的Charset类**:Java标准库提供了`java.nio.charset`包,其中的`Charset`类用于表示字符集,提供对各种字符编码的支持。例如,`StandardCharsets.UTF_8`代表UTF-8编码。 3. **BufferedReader和...

    基于Java 1.7及java.nio的FTP4Che功能丰富FTP库设计源码

    该项目为功能全面的FTP库,采用Java 1.7及java.nio技术构建,包含52个文件,其中48个为Java源代码文件,1个为Git忽略文件,1个为许可协议文件,1个为Markdown文档,1个为XML配置文件。该库旨在提供丰富的FTP功能支持...

    java监测一个目录是否有文件的增删改,附例子和jar

    Java提供了`java.nio.file`包中的`WatchService`接口,可以方便地实现这一功能。本文将深入讲解如何使用Java来监测目录中的文件增删改事件,并提供一个示例代码和相关的jar文件。 `WatchService`是Java 7引入的一个...

Global site tag (gtag.js) - Google Analytics