[java] 자바 비동기 IO를 사용한 채팅 서버 구현하기
이번 포스트에서는 자바에서 비동기 IO를 사용하여 간단한 채팅 서버를 구현하는 방법에 대해 알아보겠습니다. 비동기 IO를 사용하면 서버가 동시에 여러 클라이언트의 요청에 대응할 수 있어서 확장성과 성능을 향상시킬 수 있습니다.
필요한 기술 요구사항
- JDK 1.7 이상
- NIO (New IO) 패키지
단계별로 진행해보기
- 서버 소켓 생성하기: 서버 소켓을 생성하여 클라이언트의 연결 요청을 받을 준비를 합니다.
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.nio.charset.StandardCharsets;
public class ChatServer {
private ServerSocketChannel serverSocketChannel;
public void startServer(int port) {
try {
serverSocketChannel = ServerSocketChannel.open();
serverSocketChannel.bind(new InetSocketAddress(port));
} catch (IOException e) {
e.printStackTrace();
}
}
public void acceptClient() {
while (true) {
try {
SocketChannel clientSocketChannel = serverSocketChannel.accept();
// 클라이언트 연결 처리 로직 구현
} catch (IOException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
ChatServer chatServer = new ChatServer();
chatServer.startServer(9090);
chatServer.acceptClient();
}
}
- 클라이언트 연결 처리하기: 클라이언트가 서버에 연결되었을 때 발생하는 이벤트를 처리하는 로직을 구현합니다.
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
public class ChatServer {
// ...
public void acceptClient() {
while (true) {
try {
SocketChannel clientSocketChannel = serverSocketChannel.accept();
clientSocketChannel.configureBlocking(false);
Selector selector = Selector.open();
clientSocketChannel.register(selector, SelectionKey.OP_READ);
while (true) {
selector.select();
Iterator<SelectionKey> keyIterator = selector.selectedKeys().iterator();
while (keyIterator.hasNext()) {
SelectionKey key = keyIterator.next();
keyIterator.remove();
if (key.isReadable()) {
SocketChannel channel = (SocketChannel) key.channel();
ByteBuffer buffer = ByteBuffer.allocate(1024);
int bytesRead = channel.read(buffer);
if (bytesRead > 0) {
buffer.flip();
byte[] data = new byte[buffer.remaining()];
buffer.get(data);
String message = new String(data, StandardCharsets.UTF_8);
System.out.println("Received message: " + message);
// 클라이언트로부터 받은 메시지 처리 로직 구현
}
}
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
// ...
}
- 클라이언트로부터 받은 메시지 처리하기: 클라이언트로부터 받은 메시지에 대한 처리 로직을 구현합니다. 이 예제에서는 간단하게 받은 메시지를 그대로 콘솔에 출력하는 것으로 구현했습니다.
// ...
if (bytesRead > 0) {
buffer.flip();
byte[] data = new byte[buffer.remaining()];
buffer.get(data);
String message = new String(data, StandardCharsets.UTF_8);
System.out.println("Received message: " + message);
// 클라이언트로부터 받은 메시지 처리 로직
// ...
// 클라이언트에게 응답하기
String responseMessage = "Message received!";
byte[] responseBytes = responseMessage.getBytes(StandardCharsets.UTF_8);
ByteBuffer responseBuffer = ByteBuffer.wrap(responseBytes);
channel.write(responseBuffer);
}
- 코드 실행하기:
ChatServer
클래스의main
메서드를 실행하여 서버를 시작합니다.
public static void main(String[] args) {
ChatServer chatServer = new ChatServer();
chatServer.startServer(9090);
chatServer.acceptClient();
}
결론
이렇게 자바에서 비동기 IO를 사용하여 간단한 채팅 서버를 구현하는 방법에 대해 알아보았습니다. 비동기 IO를 사용하면 동시에 여러 클라이언트와 효율적으로 통신할 수 있으며, 확장성과 성능을 향상시킬 수 있습니다.