java.nio는 new input output의 약자로, 자바의 기존 i/o를 개선하기 위한 new i/o 입니다.
java.io는 다음과 같은 문제를 가지고 있습니다.
이를 java.nio는 다음과 같이 해결했습니다.
java.nio에는 다음과 같이 핵심이 되는 개념이 존재합니다.
java.nio의 동작 방식은 사실 멀티플렉싱 기반의 다중 서버 동작 방식과 유사합니다.
java.nio의 핵심 기능 중 하나가 멀티플렉싱 기반의 I/O이기 때문입니다.
위에 있는 그림이 멀티플렉싱 기반의 다중 서버의 동작 방식입니다.
이를 java.nio가 Non-Blocking I/O 방식으로 하나의 스레드가 여러 소켓을 수행하는 과정으로 변경해 동작 과정을 살펴보고자 합니다.
이 때, 동작 순서는 간단한 echo 서버 예제를 통해 확인해보고자 합니다.
public class EchoServer {
public static void main(String[] args) throws IOException {
Selector selector = Selector.open();
ServerSocketChannel server = ServerSocketChannel.open();
server.bind(new InetSocketAddress("localhost", 8080));
server.configureBlocking(false);
server.register(selector, SelectionKey.OP_ACCEPT);
ByteBuffer buffer = ByteBuffer.allocate(256);
while (true) {
selector.select();
Set<SelectionKey> selectedKeys = selector.selectedKeys();
Iterator<SelectionKey> iter = selectedKeys.iterator();
while (iter.hasNext()) {
SelectionKey key = iter.next();
iter.remove();
if (key.isAcceptable()) {
register(selector, server);
}
if (key.isReadable()) {
answerWithEcho(buffer, key);
}
}
}
}
private static void answerWithEcho(ByteBuffer buffer, SelectionKey key) throws IOException {
SocketChannel client = (SocketChannel) key.channel();
int readBytes = client.read(buffer);
if (readBytes == -1 || "EXIT".equals(new String(buffer.array()).trim())) {
client.close();
System.out.println("Server : 클라이언트와의 연결을 종료합니다.");
}
else {
buffer.flip();
client.write(buffer);
buffer.clear();
}
}
private static void register(Selector selector, ServerSocketChannel serverSocket) throws IOException {
SocketChannel client = serverSocket.accept();
client.configureBlocking(false);
client.register(selector, SelectionKey.OP_READ);
System.out.println("Server : 클라이언트와 연결되었습니다 : " + client.getRemoteAddress());
}
}
public class EchoClient {
public static void main(String[] args) throws IOException {
SocketChannel client = SocketChannel.open(new InetSocketAddress("localhost", 8080));
System.out.println("Client : 서버와 연결되었습니다 : " + client.getRemoteAddress());
Scanner sc = new Scanner(System.in);
while (true) {
System.out.print("Client : 서버에 전달할 문자열을 입력해주세요 : ");
String input = sc.nextLine();
ByteBuffer buffer = ByteBuffer.wrap(input.getBytes());
client.write(buffer);
buffer.clear();
client.read(buffer);
String response = new String(buffer.array()).trim();
if ("EXIT".equals(response)) {
System.out.println("Client : 서버와의 연결을 종료합니다.");
client.close();
break ;
}
System.out.println("Client : 서버로부터의 응답 : " + response);
buffer.clear();
}
}
}
다음과 같이 예제가 동작하는 것을 확인할 수 있습니다.