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/
}
댓글 영역