Java는 강력한 네트워크 프로그래밍 기능을 제공하며, 소켓(Socket)을 활용하면 서버와 클라이언트 간의 통신을 쉽게 구현할 수 있습니다. 이번 글에서는 소켓을 이용하여 기본적인 서버와 클라이언트 프로그램을 구현하는 방법을 단계별로 살펴보겠습니다.
1. 소켓(Socket)이란?
소켓은 네트워크 상에서 데이터를 송수신하기 위한 양쪽 끝단을 의미합니다.
- 서버 소켓(Server Socket): 클라이언트의 연결 요청을 대기하고 처리합니다.
- 클라이언트 소켓(Client Socket): 서버에 연결 요청을 보내고 데이터를 주고받습니다.
TCP 소켓: 신뢰성이 높은 연결 기반 통신. UDP 소켓: 빠르고 가벼운 비연결 기반 통신.
2. 서버 프로그램 구현하기
다음은 Java에서 TCP 기반의 서버를 구현한 예제입니다.
import java.io.*;
import java.net.*;
public class ServerExample {
public static void main(String[] args) {
try (ServerSocket serverSocket = new ServerSocket(12345)) {
System.out.println("서버가 12345 포트에서 대기 중입니다...");
// 클라이언트 연결 대기
Socket clientSocket = serverSocket.accept();
System.out.println("클라이언트가 연결되었습니다: " + clientSocket.getInetAddress());
// 데이터 송수신
BufferedReader in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
PrintWriter out = new PrintWriter(clientSocket.getOutputStream(), true);
String message = in.readLine();
System.out.println("클라이언트로부터 받은 메시지: " + message);
out.println("서버에서 답변: " + message.toUpperCase());
} catch (IOException e) {
System.out.println("서버 오류: " + e.getMessage());
}
}
}
설명:
ServerSocket
객체 생성: 특정 포트(12345)에서 연결 대기.accept()
메서드: 클라이언트 연결을 수락.BufferedReader
와PrintWriter
: 클라이언트와 데이터 송수신.
3. 클라이언트 프로그램 구현하기
클라이언트는 서버에 연결하고 데이터를 주고받습니다.
import java.io.*;
import java.net.*;
public class ClientExample {
public static void main(String[] args) {
try (Socket socket = new Socket("localhost", 12345)) {
System.out.println("서버에 연결되었습니다.");
// 데이터 송수신
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
out.println("안녕하세요, 서버!");
String response = in.readLine();
System.out.println("서버로부터 받은 메시지: " + response);
} catch (IOException e) {
System.out.println("클라이언트 오류: " + e.getMessage());
}
}
}
설명
Socket
객체 생성: 서버에 연결 요청.BufferedReader
와PrintWriter
: 서버와 데이터 송수신.- 서버의 응답 처리.
4. 실행 순서
- 서버 프로그램 실행.
- 클라이언트 프로그램 실행.
- 클라이언트에서 서버로 메시지를 보내고, 서버에서 메시지를 처리하여 응답.
예시 출력
- 서버
서버가 12345 포트에서 대기 중입니다...
클라이언트가 연결되었습니다: /127.0.0.1
클라이언트로부터 받은 메시지: 안녕하세요, 서버!
- 클라이언트
서버에 연결되었습니다.
서버로부터 받은 메시지: 안녕하세요, 서버!
5. 네트워크 프로그래밍 시 주의사항
- 포트 충돌 방지
- 동일한 포트를 사용하는 다른 프로세스가 실행 중일 수 있습니다. 포트를 변경하거나 확인하세요.
- 에러 처리
- 네트워크 환경은 예기치 못한 에러가 발생할 수 있으므로 적절한 예외 처리가 필요합니다.
- 멀티스레드 서버
- 다중 클라이언트를 처리하려면 각 클라이언트마다 별도의 스레드를 생성해야 합니다.
멀티스레드 예제
class ClientHandler extends Thread {
private Socket clientSocket;
public ClientHandler(Socket socket) {
this.clientSocket = socket;
}
@Override
public void run() {
try {
BufferedReader in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
PrintWriter out = new PrintWriter(clientSocket.getOutputStream(), true);
String message = in.readLine();
out.println("서버에서 답변: " + message.toUpperCase());
} catch (IOException e) {
System.out.println("클라이언트 처리 중 오류: " + e.getMessage());
}
}
}
결론
자바에서 네트워크 프로그래밍의 Socket을 이용한 서버와 클라이언트 구현에 대해 알아 보았습니다. Java의 소켓 프로그래밍은 네트워크 통신을 구현하는 데 매우 유용한 도구입니다. 서버와 클라이언트 간의 기본 통신에서 멀티스레드와 같은 고급 기능으로 확장할 수 있습니다.
다음 블로그에서는 Java에서의 데이터베이스 연결 중 JDBC를 이용한 SQL 쿼리 실행에 대해 알아 보겠습니다. 감사합니다.