자바 NIO 를 사용 하여 비동기 적 인 socket 통신 을 실현 합 니 다.

6574 단어 JAVANIO 관련
NIO 에 대한 소 개 는 이 글 을 참고 할 수 있 습 니 다.http://tutorials.jenkov.com/java-nio/index.html이 강 좌 는 비교적 잘 썼 다.
구 IO 로 이 루어 진 Socket 통신 에 대해 서 는 이 글 을 참고 할 수 있 습 니 다.http://blog.csdn.net/kongxx/article/category/1077912
최근 NIO 와 Socket 을 공부 할 때 인터넷 에서 진정 으로 비동기 적 인 socket 을 실현 하 는 예 가 드 물 게 발견 되 었 다.대부분 Selector 만 사용 하여 서버 의 Server Socket Channel 을 관리 하 는데 사실상 진정한 이 보 를 하지 못 했 거나 순서대로 연결 을 받 아들 이 고 메 시 지 를 받 은 후에 연결 을 풀 었 다.
더 일반적인 방법 은 서버 에서 두 개의 스 레 드 를 사용 하고 한 스 레 드 는 차단 하 는 방법 으로 accept 클 라 이언 트 를 사용 하 며 다른 스 레 드 는 selector 로 모든 연결 을 비동기 적 으로 처리 하 는 것 입 니 다.
     
비동기 IO 의 간단 한 인 스 턴 스 를 위해 selector 를 사용 합 니 다.서버 는 메 인 스 레 드 에서 무한 순환 차단 스 레 드 를 통 해 들 어 오 는 연결 을 감청 하고 다른 스 레 드 를 시작 합 니 다.selector 를 통 해 연 결 된 통 로 를 비동기 적 으로 처리 합 니 다.클 라 이언 트 가 100 개의 스 레 드 를 시작 하여 100 명의 사용자 가 동시에 서버 에 연결 되 는 것 을 모 의 합 니 다.출력 결 과 를 통 해 클 라 이언 트 와 서버 의 통신 이 비동기 적 으로 이 루어 진 것 을 알 수 있 습 니 다.
먼저 도구 류 를 붙 이 고 그 안에 메 시 지 를 보 내 는 두 가지 방법 이 있다.

import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.SocketChannel;
import java.nio.charset.Charset;
import java.nio.charset.CharsetDecoder;

public class SendAndReceiveUtil {
	public static String receiveData(SocketChannel channel) {
		// TODO Auto-generated method stub
		// TODO Auto-generated method stub
		ByteBuffer bb = ByteBuffer.allocate(1024);
		StringBuilder msg = new StringBuilder();
		Charset charset = Charset.forName("UTF-8");  
		CharsetDecoder decoder = charset.newDecoder();
		try {
			while( (channel.read(bb) ) > 0 ){
				bb.flip();		
				msg.append(decoder.decode(bb).toString());
				//System.out.println(msg.toString());
	
				bb.clear();
			}
			return msg.toString();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return null;
	}
	public static  void sendData(SocketChannel socketChannel, String msg) {
		// TODO Auto-generated method stub
		try {
			socketChannel.write(ByteBuffer.wrap(msg.getBytes()));
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}

그리고 서버 코드 를 붙 여 주세요.

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Iterator;

public class ChatServer {

	/**
	 * @param args
	 * @throws IOException 
	 */
	public static void main(String[] args) throws IOException {
		// TODO Auto-generated method stub
		final Selector selector = Selector.open();;
		
		ServerSocketChannel ssc = ServerSocketChannel.open();
		
		try{
			// Bind the server socket to the local host and port 
			ssc.socket().bind(new InetSocketAddress("localhost", 8080));
			
			//start a thread to handle the wirte and read
			startWRThread(selector);
			//block the main thread to accept client
			while(true){  // will block the thread
				
				SocketChannel sc = ssc.accept();
				//Get the server socket and set to non blocking mode  
				sc.configureBlocking(false);
				sc.register(selector, SelectionKey.OP_READ);
			}
		}finally{
			selector.close();
			ssc.close();
		}
	}

	private static void startWRThread(final Selector selector) {
		// TODO Auto-generated method stub
		new Thread(new Runnable() {
			@Override
			public void run() {
				// TODO Auto-generated method stub			
				try {
					while(true){
						while(selector.selectNow() > 0){
							
							Iterator it = selector.selectedKeys().iterator();
							//// Walk through the ready keys collection and process date requests.
							while(it.hasNext()){
								SelectionKey readyKey = it.next();
								if(readyKey.isReadable()){
									SocketChannel sc = (SocketChannel) readyKey.channel();
									 String msg = SendAndReceiveUtil.receiveData(sc);  
							         if(msg != null && !msg.equals("")) {
							        	 if(msg.equals("bye")){
							        		 System.out.println("Get a msg : " + msg);
							        		 sc.close();
							        	 }else{
							        		 System.out.println("Get a msg : " + msg);
							        		 SendAndReceiveUtil.sendData(sc,"Server have got you msg:"+ msg);
							        		 sc.shutdownOutput();
							        	 }	        	
							         }
							         
									 it.remove(); 
								}

								//execute((ServerSocketChannel) readyKey.channel());
							}
						}
					}
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}).start();
	}

}

마지막 으로 클 라 이언 트 코드 를 붙 입 니 다.클 라 이언 트 는 100 개의 스 레 드 를 시작 하여 100 개의 클 라 이언 트 를 모 의 해서 서버 에 연결 하고 스 레 드 id 를 서버 에 보 낸 다음 에'bye'를 보 내 서 연결 을 끝 냅 니 다.

import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.nio.channels.SocketChannel;




public class ChatClient {
	

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		for (int i = 1; i < 100; i++) {  
            final int idx = i;  
            new Thread(new MyRunnable(idx)).start();  
        }  
	}
	private static class MyRunnable implements Runnable {

		private final int idx;  
  	  
        private MyRunnable(int idx) {  
            this.idx = idx;  
        }  
		@Override
		public void run() {
			// TODO Auto-generated method stub
			SocketChannel socketChannel = null;  
            try {  
                socketChannel = SocketChannel.open();  
                SocketAddress socketAddress = new InetSocketAddress("localhost", 8080);  
                
                socketChannel.connect(socketAddress);  
                
                SendAndReceiveUtil.sendData(socketChannel, "My id is " + idx);  
                  
                String msg = SendAndReceiveUtil.receiveData(socketChannel);  
                if(msg != null) System.out.println("The server reply:"+msg);
                
                SendAndReceiveUtil.sendData(socketChannel,"bye");
          
            } catch (Exception ex) {  
                ex.printStackTrace();
            } finally {  
                try {          
                    socketChannel.close();  
                } catch(Exception ex) {
               	 	ex.printStackTrace();
                }  
            }  
		}
		
		
	}
}

좋은 웹페이지 즐겨찾기