상세 컨텐츠

본문 제목

SelectSockets

보안

by MustThanks 2020. 8. 11. 22:33

본문

반응형
package com.nio.selector;

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

public class SelectSockets implements Runnable{

	public static void main(String[] args) {
		// TODO Auto-generated method stub

		System.out.println(16>>0);
		System.out.println(16>>2);
		System.out.println(16>>3);
		System.out.println(16>>4);
		
		SelectSockets selectSockets = new SelectSockets();
		
		selectSockets.setServerPort(1000);
		selectSockets.run();
		
	}
	
	private ServerSocketChannel serverSocketChannel;
	private ServerSocket serverSocket;	
	private Selector selector;
	
	private int serverPort;
	private boolean boolBlocking = false;
	
	private final int INT_ZERO = 0;
	
	
	public void setServerPort(int port)
	{
		serverPort = port;
	}
	
	//false nonblocking
	//true blockong
	public void setBlockingValue(boolean bool)
	{
		boolBlocking = bool;
	}
	
	
	@Override
	public void run() {
		// TODO Auto-generated method stub
		
		try {
			open();
			
			while(true)
			{
				
				System.out.println("========TTT==========");
				
				// This may block for a long time. Upon returning, the
				// selected set contains keys of the ready channels.
				int n = selector.select( );
				//int n = selector.selectNow( );
				
				System.out.println("==================");
				if (n == 0) { // it is not access to server
					continue; // nothing to do
				}
				
				setSelect();
			}			
			
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
	private void open() throws IOException
	{
		// Allocate an unbound server socket channel
		serverSocketChannel = ServerSocketChannel.open();
		
		// Get the associated ServerSocket to bind it with
		serverSocket = serverSocketChannel.socket();
		
		// Create a new Selector for use below
		selector = Selector.open( );
		
		bind();
		
	}
	
	
	private void bind() throws IOException
	{
		
		if(serverPort <=INT_ZERO) throw new IOException("server port is chekced");
		
		// Set the port the server channel will listen to
		serverSocket.bind (new InetSocketAddress (serverPort));
		
		// Set nonblocking mode for the listening socket
		serverSocketChannel.configureBlocking (boolBlocking);
		
		// Register the ServerSocketChannel with the Selector
		serverSocketChannel.register (selector, SelectionKey.OP_ACCEPT);
	}

	
	private void setSelect() throws Exception
	{
		
		// This may block for a long time. Upon returning, the
		// selected set contains keys of the ready channels.
		// Get an iterator over the set of selected keys
		//Iterator it = selector.selectedKeys().iterator( );
		Iterator<SelectionKey> keyIterator = selector.selectedKeys().iterator( );
				
		// Look at each key in the selected set
		while (keyIterator.hasNext( )) {

			SelectionKey key = keyIterator.next( );
			
			// Is a new connection coming in?
			if (key.isAcceptable( )) 
			{
					ServerSocketChannel server =	(ServerSocketChannel) key.channel( );
					SocketChannel channel = server.accept( );
					registerChannel (channel,	SelectionKey.OP_READ);
					sayHello (channel);
			}
		
		
			// Is there data to read on this channel?
			if (key.isReadable( )) {
				
				readDataFromSocket (key);
			}
			
			// Remove key from selected set; it's been handled
			keyIterator.remove( );
		}
		
		//Set<SelectionKey> selectedKeys = selector.selectedKeys();
		//Iterator<SelectionKey> keyIterator = selectedKeys.iterator();
		
		
	}
	
	
	
	private void registerChannel(SelectableChannel channel, int ops) throws Exception
	{
	
		if (channel == null) {
				return; // could happen
		}
		
		// Set the new channel nonblocking
		channel.configureBlocking (boolBlocking);
		
		// Register it with the selector
		channel.register (selector, ops);
	}
	
	
	
	private ByteBuffer buffer = ByteBuffer.allocateDirect (1024);
	
	protected void readDataFromSocket (SelectionKey key) throws Exception
	{
		SocketChannel socketChannel = (SocketChannel) key.channel( );
		
		int count;
		buffer.clear( ); // Empty buffer
		
		// Loop while data is available; channel is nonblocking
		while ((count = socketChannel.read (buffer)) > 0) {
			
			buffer.flip( ); // Make buffer readable
			
			// Send the data; don't assume it goes all at once
			while (buffer.hasRemaining( )) {
				socketChannel.write (buffer);
			}
			
			// WARNING: the above loop is evil. Because
			// it's writing back to the same nonblocking
			// channel it read the data from, this code can
			// potentially spin in a busy loop. In real life
			// you'd do something more useful than this.
			buffer.clear( ); // Empty buffer
		}
		
		if (count < 0) {
		// Close channel on EOF, invalidates the key
			socketChannel.close( );
		}
	}

	
	private void sayHello (SocketChannel channel)throws Exception
	{
			buffer.clear( );
			buffer.put ("Hi there!\r\n".getBytes( ));
			buffer.flip( );
			channel.write (buffer);
	}

	
	
	//https://jungwoon.github.io/java/2019/01/15/NIO-Network/
	//https://examples.javacodegeeks.com/core-java/nio/java-nio-async-http-client-example/
	//https://examples.javacodegeeks.com/core-java/nio/java-nio-ssl-example/
	
	//https://examples.javacodegeeks.com/core-java/nio/java-nio-socket-example/
	//https://jongmin92.github.io/2019/03/03/Java/java-nio/
	//https://www.baeldung.com/java-nio-selector
	
	/*  http://www.gurubee.net/article/12001
	 *  SelectableChannel은 모든 소켓채널의 수퍼클래스입니다. SelectableChannel은 블록킹이나 비블록킹 모드설정 기능을 제공해주며, Selector에 등록해 주는 기능
	 *  모든 채널이 네가지 이벤트 값을 모두 가질 수는 없고 각 채널마다 등록 가능한 이벤트들이 존재합니다. 아래를 참조하세요.
		ServerSocketChannel - OP_ACCEPT 
		SocketChannel - OP_CONNECT, OP_READ, OP_WRITE   OP_CONNECT(클라이언트 에서 이용)
		DatagramChannel - OP_READ, OP_WRITE
		Pipe.SourceChannel - OP_READ
		Pipe.SinkChannel - OP_WRITE

		- Selector는 이벤트가 발생한 채널들만을 선택해서 각 이벤트에 맞는 동작을 하도록 중간에서 모든 이벤트들에 대한 컨트롤러 역할을 하는 것입니다.
		- register() 메소드를 이용해서 채널을 Selector에 등록하면 해당 채널과 이 채널이 Selector에 등록하기 원하는 이벤트를 캡슐화한 SelectionKey를 만들고 이
		  SelectionKey를 Selector가 관리하는 내부 Set에 추가하게 됩니다. 그리고 이 SelectionKey를 메소드의 리턴값으로 리턴하게 됩니다.
		    따라서 SelectionKey는 Selector와 채널 사이의 중계자로서의 역할을 합니다.
		  keyFor() 메소드는 파라미터로 넘어온 Selector에 대해 이 채널이 등록한 상태라면 그 등록에 중계자 역할을 하는 SelectionKey를 리턴해주고 등록하지 않았다면 null을 리턴해 줍니다.
		  validOps() 메소드는 이 채널이 Selector에 등록한 이벤트 값을 리턴해줍니다.
	 */
     //http://homoefficio.github.io/2020/08/10/Java-NIO-FileChannel-%EA%B3%BC-DirectByteBuffer/
	
}

'보안' 카테고리의 다른 글

http 메세지  (0) 2020.08.18
java.exe 와 javaw.exe 의 차이점  (0) 2020.08.14
보안 PKI 예제 (Security PKI example)  (1) 2020.08.09
블럭 암호 공격  (0) 2020.08.07
Feistel SPN 구조  (0) 2020.08.05

관련글 더보기

댓글 영역