Java 소켓 프로그래밍: 멀티스레딩을 이용한 서버 구현
소개
이전 포스트에서는 Java 소켓 프로그래밍의 기본 개념과 간단한 TCP 에코 서버 및 클라이언트를 구현해보았습니다. 이번 포스트에서는 멀티스레딩을 이용해 다수의 클라이언트와 동시에 통신할 수 있는 서버를 구현해보겠습니다.
멀티스레딩의 필요성
단일 스레드 서버는 한 번에 하나의 클라이언트만 처리할 수 있습니다. 여러 클라이언트가 동시에 서버에 연결을 시도할 경우, 각 클라이언트는 이전 클라이언트의 처리가 완료될 때까지 기다려야 합니다. 이를 해결하기 위해 멀티스레딩을 사용하여 동시에 여러 클라이언트를 처리할 수 있는 서버를 구현할 수 있습니다.
멀티스레딩 서버의 동작 원리
멀티스레딩 서버는 각 클라이언트의 요청을 별도의 스레드에서 처리합니다. 기본적인 동작 과정은 다음과 같습니다:
- 서버 소켓 생성: 서버는 특정 포트에서 클라이언트의 연결을 기다립니다.
- 클라이언트 연결 수락: 클라이언트의 연결 요청을 수락합니다.
- 새 스레드 생성: 각 클라이언트 연결을 처리하기 위해 새 스레드를 생성합니다.
- 데이터 송수신: 각 스레드에서 클라이언트와 데이터를 주고받습니다.
- 연결 종료: 통신이 끝나면 연결을 종료합니다.
멀티스레딩 에코 서버 예제
서버 코드
먼저 멀티스레딩을 지원하는 서버 코드를 작성해보겠습니다.
import java.io.*;
import java.net.*;
// 에코 서버 클래스
public class MultithreadedEchoServer {
public static void main(String[] args) {
int port = 12345;
try (ServerSocket serverSocket = new ServerSocket(port)) {
System.out.println("Multithreaded Echo server is listening on port " + port);
while (true) {
// 클라이언트의 연결을 수락
Socket socket = serverSocket.accept();
System.out.println("New client connected");
// 클라이언트를 처리하기 위해 새 스레드 생성
new EchoClientHandler(socket).start();
}
} catch (IOException ex) {
System.out.println("Server exception: " + ex.getMessage());
ex.printStackTrace();
}
}
}
// 클라이언트 요청을 처리하는 스레드 클래스
class EchoClientHandler extends Thread {
private Socket socket;
public EchoClientHandler(Socket socket) {
this.socket = socket;
}
@Override
public void run() {
try {
InputStream input = socket.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(input));
OutputStream output = socket.getOutputStream();
PrintWriter writer = new PrintWriter(output, true);
String text;
while ((text = reader.readLine()) != null) {
System.out.println("Received: " + text);
writer.println("Echo: " + text);
}
socket.close();
} catch (IOException ex) {
System.out.println("Server exception: " + ex.getMessage());
ex.printStackTrace();
}
}
}
클라이언트 코드
클라이언트 코드는 이전 예제와 동일하게 사용합니다. 여기서 변경된 부분은 없습니다.
import java.io.*;
import java.net.*;
public class EchoClient {
public static void main(String[] args) {
String hostname = "localhost";
int port = 12345;
try (Socket socket = new Socket(hostname, port)) {
OutputStream output = socket.getOutputStream();
PrintWriter writer = new PrintWriter(output, true);
InputStream input = socket.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(input));
BufferedReader consoleReader = new BufferedReader(new InputStreamReader(System.in));
String text;
System.out.println("Connected to the echo server. Type your messages:");
while ((text = consoleReader.readLine()) != null) {
writer.println(text);
String response = reader.readLine();
System.out.println(response);
}
} catch (UnknownHostException ex) {
System.out.println("Server not found: " + ex.getMessage());
} catch (IOException ex) {
System.out.println("I/O error: " + ex.getMessage());
}
}
}
코드 설명
MultithreadedEchoServer
- ServerSocket: 특정 포트에서 클라이언트의 연결을 기다립니다.
- accept(): 클라이언트의 연결을 수락합니다.
- 새 스레드 생성: 클라이언트의 요청을 처리하기 위해
EchoClientHandler
스레드를 생성하고 시작합니다.
EchoClientHandler
- Socket: 클라이언트와의 통신을 담당합니다.
- InputStream과 OutputStream: 클라이언트와 데이터를 주고받기 위한 스트림입니다.
- BufferedReader와 PrintWriter: 편리하게 데이터를 읽고 쓰기 위해 사용합니다.
- run(): 스레드가 시작될 때 호출되며, 클라이언트와의 통신을 처리합니다.
결과
멀티스레딩 에코 서버를 통해 여러 클라이언트가 동시에 서버에 연결하여 메시지를 주고받을 수 있습니다. 각 클라이언트는 별도의 스레드에서 처리되므로, 클라이언트 간의 간섭 없이 독립적으로 통신할 수 있습니다.
결론
이번 포스트에서는 멀티스레딩을 이용한 Java 소켓 프로그래밍을 다루었습니다. 이를 통해 다수의 클라이언트를 동시에 처리할 수 있는 서버를 구현하는 방법을 배웠습니다. 다음 포스트에서는 소켓 프로그래밍의 고급 주제들, 예를 들어 비동기 소켓 채널(Asynchronous Socket Channel)과 같은 고급 기술을 다룰 예정입니다.
'자바' 카테고리의 다른 글
[JAVA] 자바 메서드 심화: 오버로딩과 오버라이딩 (0) | 2024.07.19 |
---|---|
[JAVA] 자바 함수(메서드)의 기초: 선언부터 사용까지 (0) | 2024.07.19 |
[API] Python API와 Java 클라이언트를 이용한 CPK 분석 및 히스토그램 생성 (0) | 2024.07.19 |
[JAVA] 소켓 프로그래밍 3번 (0) | 2024.07.08 |
[JAVA] 소켓 프로그래밍 1번 (0) | 2024.07.08 |