JAVA IO 之NIO

说明:这篇文章的code不是我写的,来自 林昊的分布式Java 基础与应用的示例demo.

 

server端:

 

package mytcpnio;

import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.nio.ByteBuffer;
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;

public class ServerDemo {
	public static void main(String[] args) throws Exception{
		int port = 11111;
		
		Selector selector=Selector.open();
		ServerSocketChannel ssc=ServerSocketChannel.open();
		
		ServerSocket serverSocket=ssc.socket();
		//绑定监听端口
		serverSocket.bind(new InetSocketAddress(port));
		System.out.println("Server listens on port: "+port);
		
		ssc.configureBlocking(false);
		ssc.register(selector, SelectionKey.OP_ACCEPT);
		
		while(true){
			int keysNum = selector.select(1000);
			if(keysNum>0){
				for(SelectionKey sk : selector.selectedKeys()){
					if(sk.isAcceptable()){
						ServerSocketChannel serverSocketChannel = (ServerSocketChannel)sk.channel();
						SocketChannel sc = serverSocketChannel.accept();
						if(sc == null){
							continue;
						}
						sc.configureBlocking(false);
						sc.register(selector, SelectionKey.OP_READ);
					}
					if(sk.isReadable()){
						ByteBuffer buffer=ByteBuffer.allocate(1024);
						SocketChannel sc=(SocketChannel) sk.channel();
						int readBytes=0;
						String message=null;
						try{
							int ret;
							try{
								while((ret=sc.read(buffer))>0){
									readBytes+=ret;
								}
							}
							catch(Exception e){
								readBytes=0;
								// IGNORE
							}
							finally{
								buffer.flip();
							}
							if(readBytes>0){
								message=Charset.forName("UTF-8").decode(buffer).toString();
								buffer = null;
							}
						}
						finally{
							if(buffer!=null){
								buffer.clear();
							}
						}
						if(readBytes>0){
							System.out.println("Message from client: "+ message);
							if("quit".equalsIgnoreCase(message.trim())){
								sc.close();
								selector.close();
								System.out.println("Server has been shutdown!");
								System.exit(0);
							}
							String outMessage="Server response:"+message;
							//将消息写入通道
							sc.write(Charset.forName("UTF-8").encode(outMessage));
						}
					}
				}
				//清除这次循环的所有selectedKeys
				selector.selectedKeys().clear();
			}
		}
	}
}

分析:这个示例是一个基于tcp的通信demo.server端的大致创建过程如下:建立servesocketchannel,绑定监听端口,向selector注册,而后由selector轮询管理。server端只存在 accpetable和readable两种信道。

 

 

package mytcpnio;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.SocketChannel;
import java.nio.charset.Charset;

public class ClientDemo {

	public static void main(String[] args) throws Exception{
		
		int port=11111;
		
		SocketChannel socketChannal=SocketChannel.open();
		
		socketChannal.configureBlocking(false);
		SocketAddress target=new InetSocketAddress("127.0.0.1",port);
		socketChannal.connect(target);
		Selector selector=Selector.open();
		socketChannal.register(selector, SelectionKey.OP_CONNECT);
		BufferedReader systemIn=new BufferedReader(new InputStreamReader(System.in));
		while(true){
			if(socketChannal.isConnected()){
				String command=systemIn.readLine();
				/**写入消息到通道 
				 * 退出命令  执行过程大致如下   将退出命令写入通道
				 */
				
				socketChannal.write(Charset.forName("UTF-8").encode(command));
				if(command==null || "quit".equalsIgnoreCase(command.trim())){
					systemIn.close();
					socketChannal.close();
					selector.close();
					System.out.println("Client quit!");
					System.exit(0);
				}
			}
			int keysNum=selector.select(1000);
			if(keysNum>0){
				for (SelectionKey sk : selector.selectedKeys()) {
					if(sk.isConnectable()){
						SocketChannel sc=(SocketChannel) sk.channel();
						sc.configureBlocking(false);
						sc.register(selector, SelectionKey.OP_READ);
						sc.finishConnect();
					}
					else if(sk.isReadable()){
						ByteBuffer buffer=ByteBuffer.allocate(1024);
						SocketChannel sc=(SocketChannel) sk.channel();
						int readBytes=0;
						try{
							int ret=0;
							try{
								while((ret=sc.read(buffer))>0){
									readBytes+=ret;
								}
							}
							finally{
								buffer.flip();
							}
							if(readBytes>0){
								System.out.println(Charset.forName("UTF-8").decode(buffer).toString());
								buffer = null;
							}
						}
						finally{
							if(buffer!=null){
								buffer.clear();
							}
						}
					}
				}
				selector.selectedKeys().clear();
			}
		}
	}
}
 

client端的建立过程与server端大致相同,除了需要ip外,就是信道的种类不同,建立之后也是通过轮询来监听,client端只存在connectable和readable的信道。

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值