니 오 로 에코 서비스 구현

9375 단어 자바.netsocket
오늘 갑자기 니 오 로 에코 서 비 스 를 구현 하려 고 합 니 다.프로그램 이 실현 되 는 것 은 어렵 지 않 지만 달 린 후에 서버 의 ServerSocket 에서 accept 를 완성 한 후에 제 CPU 는 항상 100%까지 뛰 었 습 니 다.응,답답 해.나중에 야 서버 에 남 은 감청 사건 Selection Key.OP 를 등록 한 걸 알았어.WRITE,고 쳐 보 니 많이 좋아 졌 습 니 다.이 교훈 을 기억 하 시기 바 랍 니 다.
 
EchoServer.java
package edu.dlut.zxf.nio;

import java.io.IOException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
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.Set;

/**
 * Echo   
 * @author finux
 */
public class EchoServer {
	public final static int BUFFER_SIZE = 1024; //    
	public final static String HOST = "210.30.107.17";
	public final static int PORT = 8888;
	
	public static void main(String[] args) {
		ServerSocketChannel ssc = null;
		//   
		ByteBuffer buffer = ByteBuffer.allocate(BUFFER_SIZE);
		Selector selector = null;
		try {
			selector = Selector.open();
			ssc = ServerSocketChannel.open();
			ssc.socket().bind(new InetSocketAddress(InetAddress.getByName(HOST), PORT));
			ssc.configureBlocking(false);
			ssc.register(selector, SelectionKey.OP_ACCEPT);		
			print("     ,     ...");
			while (selector.select() > 0) {		
				Set<SelectionKey> selectionKeys = selector.selectedKeys();
				for (SelectionKey key: selectionKeys) {
					if (key.isAcceptable()) {
						SocketChannel sc = ssc.accept();
						print("     !  :" + sc.socket().getRemoteSocketAddress());
						sc.configureBlocking(false);
						sc.register(selector, SelectionKey.OP_READ);
						//     :
						// sc.register(selector, SelectionKey.OP_READ | SelectionKey.OP_WRITE);
						//              SelectionKey.OP_WRTE
						//      ,   accept ,CPU     100%
						
					}
					//same to if ((ops & SelectionKey.OP_READ) == SelectionKey.OP_READ) {
					if (key.isReadable()) { 
						SocketChannel sc = (SocketChannel)key.channel();
						print("     !  :" + sc.socket().getRemoteSocketAddress());						
						buffer.clear();						
						sc.read(buffer);
						buffer.flip();
						byte[] b = new byte[buffer.limit()];
						buffer.get(b);
						String s = new String(b);
						if (s.equals("bye")) {
							print("    :" + sc.socket().getRemoteSocketAddress());	
							//     ,               
							key.cancel();
							sc.close();
							continue;
						}
						print("      :" + s);	
						buffer.clear();
						s = "echo: " + s;
						buffer.put(s.getBytes());
						buffer.flip();
						sc.write(buffer);
					} 
				}
				selectionKeys.clear();
			}
		} catch(IOException e) {
			e.printStackTrace();
		} 
	}
	
	private static void print(String s) {
		System.out.println(s);
	}
}

 
EchoClient.java
package edu.dlut.zxf.nio;

import java.util.Set;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.InetSocketAddress;
import java.net.InetAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.SocketChannel;

/**
 * Echo   
 * @author finux
 */
public class EchoClient {
	public static void main(String[] args) {
		ByteBuffer buffer = ByteBuffer.allocate(EchoServer.BUFFER_SIZE);
		Selector selector = null;
		SocketChannel sc = null;
		try {
			selector = Selector.open();
			sc = SocketChannel.open();
			sc.configureBlocking(false);
			sc.connect(new InetSocketAddress(InetAddress.getByName(EchoServer.HOST), EchoServer.PORT));
			print("     ,    ...");
			if (sc.isConnectionPending()) {
				sc.finishConnect();
			}
			print("    ");
			sc.register(selector, SelectionKey.OP_READ | SelectionKey.OP_WRITE);
			
			boolean writed = false;
			boolean down = false;
			while (!down && selector.select() > 0) {				
				Set<SelectionKey> selectionKeys = selector.selectedKeys();
				for (SelectionKey key: selectionKeys) {					
					//int ops = key.readyOps();
					//if ((ops & SelectionKey.OP_WRITE) == SelectionKey.OP_WRITE && !writed) {
					if (key.isWritable() && !writed) {
						System.out.print("Input(bye to end): ");
						BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); 
						String s = br.readLine();
						if (s != null && !s.trim().equals("")) {
							buffer.clear();
							buffer.put(s.getBytes());
							buffer.flip();
							sc.write(buffer);
							writed = true;
							if (s.equals("bye")) {
								down = true;
								break;
							}
						}
					}
					//if ((ops & SelectionKey.OP_READ) == SelectionKey.OP_READ && writed) {
					if (key.isReadable() && writed) {
						buffer.clear();
						sc.read(buffer);
						buffer.flip();
						byte[] b = new byte[buffer.limit()];
						buffer.get(b);
						print(new String(b));
						writed = false;
					}
				}
				selectionKeys.clear();
			}
		} catch(IOException e) {
			e.printStackTrace();
		}
	}
	
	private static void print(String s) {
		System.out.println(s);
	}
}

 
물론 EchoClient 도 아래 와 같이 실현 할 수 있 습 니 다.
EchoClient2.java
package edu.dlut.zxf.nio;

import java.util.Set;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.InetSocketAddress;
import java.net.InetAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.SocketChannel;

/**
 * Echo   2
 * @author finux
 */
public class EchoClient2 {
	public static void main(String[] args) {
		ByteBuffer buffer = ByteBuffer.allocate(EchoServer.BUFFER_SIZE);
		Selector selector = null;
		SocketChannel sc = null;
		try {
			selector = Selector.open();
			sc = SocketChannel.open();
			sc.configureBlocking(false);
			sc.register(selector, SelectionKey.OP_CONNECT);
			sc.connect(new InetSocketAddress(InetAddress.getByName(EchoServer.HOST), EchoServer.PORT));
			print("     ,    ...");
			
			boolean writed = false;
			boolean down = false;
			while (!down && selector.select() > 0) {				
				Set<SelectionKey> selectionKeys = selector.selectedKeys();
				for (SelectionKey key: selectionKeys) {					
					//int ops = key.readyOps();
					//if ((ops & SelectionKey.OP_CONNECT) == SelectionKey.OP_CONNECT) {
					if (key.isConnectable()) {
						print("    !");
						if (sc.isConnectionPending()) {
							sc.finishConnect();
						}
						sc.register(selector, SelectionKey.OP_READ | SelectionKey.OP_WRITE);				
					}
					//if ((ops & SelectionKey.OP_WRITE) == SelectionKey.OP_WRITE && !writed) {
					if (key.isWritable() && !writed) {
						//   IO     
						System.out.print("Input(bye to end): ");
						BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); 
						String s = br.readLine();
						if (s != null && !s.trim().equals("")) {
							buffer.clear();
							buffer.put(s.getBytes());
							buffer.flip();
							sc.write(buffer);
							writed = true;
							if (s.equals("bye")) {
								down = true;
								break;
							}
						}
					}
					//if ((ops & SelectionKey.OP_READ) == SelectionKey.OP_READ && writed) {
					if (key.isReadable() && writed) {
						buffer.clear();
						sc.read(buffer);
						buffer.flip();
						byte[] b = new byte[buffer.limit()];
						buffer.get(b);
						print(new String(b));
						writed = false;
					}
				}
				selectionKeys.clear();
			}
		} catch(IOException e) {
			e.printStackTrace();
		}
	}
	
	private static void print(String s) {
		System.out.println(s);
	}
}

그러나 이렇게 되면 분명히 EchoClient 2 의 while 순환 중의 for 순환(n 번 이 있 으 면)은 순환 할 때마다 n-1 번 if 판단 이 더 나 옵 니 다.바로 다음 과 같 습 니 다.
if (key.isConnectable()) {

그래서 저 는 개인 적 으로 첫 번 째 EchoClient 를 더 좋아 합 니 다.하하,selection Key.OP 를 등록 하지 않 아 도 됩 니 다.CONNECT 감청 사건.허허..

좋은 웹페이지 즐겨찾기