NioEchoServer

一个简单的nio交互服务,可用命令:date、unix_timestamp、bye、helllo、hi。

主要用于演示,nio的高并发处理应该不是这种方式。



package org.sl.nio.server;

import java.io.IOException;
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.util.Iterator;
import java.util.Set;

import org.apache.log4j.Logger;
import org.sl.nio.server.handler.NioAcceptableHandler;
import org.sl.nio.server.handler.NioAcceptableHandler1;
import org.sl.nio.server.handler.NioReadableHandler;

/**
 * 
 * @author shanl
 *
 */
public class NioServer {
	Logger logger = Logger.getLogger(NioServer.class);
	String ip = "127.0.0.1";
	int port = 7777;
	int timeOut = 200;

	public void service(){
		InetSocketAddress address = null;
		ServerSocketChannel ssc = null;
		ServerSocket ss = null;		
		Selector selector = null;
		SelectionKey selectkey = null;
		Set<SelectionKey> keys = null;
		Iterator<SelectionKey> iterator = null;
		SelectionKey key = null;
		int rc = 0;
		SocketChannel sc = null;
		
		try {
			address = new InetSocketAddress(ip, port);
			ssc = ServerSocketChannel.open();
			ss = ssc.socket();
			ss.bind(address);
			ssc.configureBlocking(false);			
			System.err.print("NioEchoService listening in "+ip+":"+port+"...\r\n");
//			System.out.println();
			
			selector = Selector.open();
			selectkey = ssc.register(selector, SelectionKey.OP_ACCEPT );

			for(int i=0; i<3; i++){
				if((rc = selector.select(timeOut)) > 0) {
//					System.out.println("request count: "+rc);					
					keys = selector.selectedKeys();
					iterator = keys.iterator();
					
					while(iterator.hasNext()) {
						key = iterator.next();	
						
//						System.out.println("operate:"+key.interestOps());
						if(key.isAcceptable()){
//							System.out.println("isAcceptable");
//							new NioAcceptableHandler(key).run();
							new Thread(new NioAcceptableHandler1(key)).start();
						}
//						else  if(key.isReadable()){
							System.out.println("isReadable");							
							new NioReadableHandler(key).run();
//							new Thread(new NioReadableHandler(key)).start();
//						}
//						
//						if(key.isWritable()){
//							continue;
//						}
						
						iterator.remove();
					}					
				}else{
					System.out.println("time out.");
				}
			}
		} catch (Exception ex) {		
			logger.error(ex.getMessage(), ex);
		}
	}

	public void setService(String ip, int port) {
		this.ip = ip;
		this.port = port;
	}

	public void setServicePort(int port) {
		this.port = port;
	}
	
	public void setTimeout(int timeout){
		this.timeOut = timeout;
	}
}


package org.sl.nio.server.handler;

import java.io.IOException;
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.util.Date;
import java.util.Iterator;

public class NioAcceptableHandler1 implements Runnable{
	private SelectionKey key = null;
	private SocketChannel sc = null;
	private ByteBuffer readBuff = null;
	private ByteBuffer writeBuff = null;
	private byte[] cmdBuff = null;
	private Selector sel = null;
	private static final ByteBuffer prompt = ByteBuffer.wrap("\r\n$ >>".getBytes());
	private boolean isRun = true;
	
	public NioAcceptableHandler1(SelectionKey key){
		try{
			this.key = key;
			this.sc = ((ServerSocketChannel)key.channel()).accept();
			this.readBuff = ByteBuffer.allocate(512);
			this.cmdBuff = new byte[512];
			this.writeBuff = ByteBuffer.allocate(1024*2);
		}catch(Exception ex){
			ex.printStackTrace();
		}
	}

	@Override
	public void run() {
		try {
			this.sel = Selector.open();
			Iterator<SelectionKey> iter = null;
			SelectionKey key = null;
			
			sc.configureBlocking(false);
			sc.register(sel, 
					SelectionKey.OP_READ);
			
			echoWelcome();
			echoPrompt();
			
			while(isRun){
				if(sel.select(20)>0){
					iter = sel.selectedKeys().iterator();
					
					while(iter.hasNext()){
						key = iter.next();						
						
						if(key.isReadable()){							
							readable();							
//							key.interestOps(SelectionKey.OP_WRITE);
						}
//						else if(key.isWritable()){
//							writable();
							key.interestOps(SelectionKey.OP_READ);
//						}
						
						iter.remove();
					}
				}
			}
			
			sel.wakeup();
			sel.close();
			sc.close();
		} catch (Exception e) {		
			e.printStackTrace();
		}
	}
	
	boolean readable()throws Exception{
		if(sc.read(readBuff)<=0)return false;		

		switch(readBuff.get(readBuff.position()-1)){
		case 10: //确认,既输入回车
			enter();				
			echoPrompt();
			break;
		case 0: //
			sel.wakeup();
			break;
		default: //其他字符
		}	
		
		return true;
	}
	
	boolean readable1()throws Exception{
//		System.out.println("r");
		ByteBuffer tb = ByteBuffer.allocate(32);
		int readLen = 0;
		byte[] bys = null;
		
		if((readLen = sc.read(tb))>0){
//			System.out.println(tb.get(readLen-1));
			switch(tb.get(readLen-1)){
			case 10: //确认
				enter();				
				echoPrompt();
				break;
			case 0:
				sel.wakeup();
				break;
			default: //写到buff中
				tb.flip();	
				readBuff.put(tb);
			}			
		}else{
			return true;
		}
		
		return false;
	}
	
	/**
	 * 用户输入回车
	 */
	void enter1()throws Exception{
		readBuff.flip();
		int buffSize = readBuff.limit();
		readBuff.get(cmdBuff,0,buffSize);
		String cmd = new String(cmdBuff,0,buffSize);
		System.out.println("command: "+cmd);
		readBuff.clear();
		
		writeBuff.put(cmdBuff,0,buffSize);
		writeBuff.put("\r\nok.\r\n".getBytes());
		writeBuff.flip();
		sc.write(writeBuff);
		writeBuff.clear();
	}	
	
	/**
	 * 用户输入回车
	 * @throws Exception
	 */
	void enter()throws Exception{
		readBuff.flip();
		int buffSize = readBuff.limit();
		readBuff.get(cmdBuff,0,buffSize);
		String cmd = new String(cmdBuff,0,buffSize);
		System.out.println("command: "+cmd+"");
		readBuff.clear();
		
		String res = parseCommand(cmd);
		sc.write(ByteBuffer.wrap(res.getBytes()));
		if("\r\nbye bye.\r\n".equals(res)){
			this.isRun = false;			
		}
	}
	
	String parseCommand(String cmd){
		String res = null;
		
		if(cmd.startsWith("date")){
			res = new Date().toString();
		}else if(cmd.startsWith("unix_timestamp")){
			res = System.currentTimeMillis()+""; 
		}else if(cmd.startsWith("hello") || cmd.startsWith("hi")){
			res = "hi";
		}else if(cmd.startsWith("bye")){
			res = "bye bye.";			
		}else{
			res = "unknown command.";
		}		

		return "\r\n"+res+"\r\n";
	}
	
	void writable2()throws Exception{
		readBuff.flip();
		int buffSize = readBuff.limit();
		readBuff.get(cmdBuff,0,buffSize);
		String cmd = new String(cmdBuff,0,buffSize);
		System.out.println("command: "+cmd);
				
		readBuff.flip();
		sc.write(readBuff);		
		readBuff.clear();
	}
	
	void echoWelcome()throws Exception{
		sc.write(ByteBuffer.wrap("welcome to NioEchoServer.\r\n".getBytes()));
	}
	
	void echoPrompt()throws Exception{		
		if(isRun) {
			sc.write(prompt);
			prompt.flip();
		}		
	}

}

import org.sl.nio.server.NioServer;


public class NioServerTest {
	public static void main(String[] args){
		t1();
	}
	
	static void t1(){
		NioServer nserver = new NioServer();
		nserver.setService("192.168.2.23", 7777);
		nserver.setTimeout(0);
		nserver.service();
	}
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值