- NIO NonBlocking 기반 서버
- Selector가 Blocking 되어 있지 않는 "accept() 와 receive()"를 수신시 매칭해주는 중재자 역할을 함
- 클라이언트의 생성과 중지는 "startClient() & stopClient()"의 메소드 오버라이딩이 필요
- 싱글톤으로 전역접근가능
- 제네릭으로 특정 클라이언트 처리
/* ServerOthello - singleton */
public abstract class Server<T> {
private static Server instance;
/* Field */
public ExecutorService executorService;
public ServerSocketChannel serverSocketChannel;
public Selector selector;
public List<T> clients;
/* Constructor */
public Server(short port) {
if(instance != null) return;
instance = this;
this.clients = new Vector<>();
start(port);
}
/* GetInstance */
public static Server getInstance() {
return instance;
}
/* Start */
public void start(short port) {
// == 가용한 프로세서만큼 스레드 생성 ==
executorService = Executors.newFixedThreadPool( Runtime.getRuntime().availableProcessors() ); // 4
try {
selector = Selector.open();
serverSocketChannel = ServerSocketChannel.open();
// == 넌블로킹설정 ==
serverSocketChannel.configureBlocking(false);
// == bind(port) ==
serverSocketChannel.bind( new InetSocketAddress(port) );
// == register() ==
serverSocketChannel.register( selector, SelectionKey.OP_ACCEPT );
// == select() ==
select();
} catch (IOException e) {
e.printStackTrace();
}
}
/* Stop */
public void stop() {
try {
if(serverSocketChannel != null && serverSocketChannel.isOpen()) {
serverSocketChannel .close();
}
if(executorService != null && executorService.isShutdown()) {
executorService.shutdown();
}
} catch (IOException e) {}
}
/* Select - 기다려서 분기해주는 메소드 */
protected void select() {
Runnable runnable = new Runnable() {
@Override
public void run() {
while(true) {
try {
// == select() ==
int keyCount = selector.select();
if(keyCount == 0) { continue; }
Set<SelectionKey> selectionKeys = selector.selectedKeys();
Iterator<SelectionKey> iterator = selectionKeys.iterator();
while(iterator.hasNext()) {
SelectionKey selectionKey = iterator.next();
// == accept ==
if(selectionKey.isAcceptable()) {
startClient(selectionKey);
}
// == read ==
else if(selectionKey.isReadable()) {
ClientOthello client = (ClientOthello) selectionKey.attachment();
client.receive();
}
// == write ==
else if(selectionKey.isWritable()) { //
ClientOthello client = (ClientOthello) selectionKey.attachment();
client.send();
}
// == (처리완료) Key remove() ==
iterator.remove();
}
} catch (IOException e) {
if(serverSocketChannel.isOpen()) stop();
break;
}
}
}
};
executorService.submit(runnable);
}
/* startClient */
protected abstract void startClient(SelectionKey selectionKey);
/* stopClient */
public abstract void stopClients();
}
'Java > Java 구현' 카테고리의 다른 글
Java // 구현 // Client Socket // NIO Blocking (0) | 2018.08.06 |
---|---|
Java // 구현 // Client SocketChannel (in Server) // NIO NonBlocking (0) | 2018.08.03 |
Java FX // 구현 // GridPane // DataBinding (0) | 2018.07.26 |