
객체 지향 설계의 5원칙 (SOLID)
SRP(Single Responsibility Principle): 단일 책임 원칙 → 하나의 클래스는 하나의 기능 담당
OCP(Open Closed Priciple): 개방 폐쇄 원칙 → 확장에 개방, 수정에 폐쇄, 추상화 사용
LSP(Listov Substitution Priciple): 리스코프 치환 원칙 → 서브 타입은 부모 타입으로 교체 O (다형성)
ISP(Interface Segregation Principle): 인터페이스 분리 원칙 → 인터페이스의 단일 책임
DIP(Dependency Inversion Principle): 의존 역전 원칙
→ 대상의 상위 요소 (추상클래스, 인터페이스)로 참조
→ 구현 클래스 의존 X, 인테페이스에 의존
반이중
- 양방향 전송이 가능하지만 동시에 양쪽 방향에서 전송할 수 없는 방식
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.nio.charset.Charset;
public class Server {
public static void main(String[] args) {
try {
ServerSocket serverSocket = new ServerSocket(2000);
Socket socket = serverSocket.accept();
// 소켓 연결 완료
// 버퍼 만들기 (received)
BufferedReader br = new BufferedReader(
new InputStreamReader(socket.getInputStream())
);
String requestMsg = br.readLine();
System.out.println("클라이언트로부터 받은 메세지: " + requestMsg);
//버퍼 만들기 (send)
PrintWriter pw = new PrintWriter(socket.getOutputStream(), true, Charset.forName("UTF-8"));
if (requestMsg.equals("1")) {
pw.println("영화");
} else if (requestMsg.equals("2")) {
pw.println("드라마");
} else {
pw.println("프로토콜을 확인하세요 -> 1은 영화, 2는 드라마");
}
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
public class Client {
public static void main(String[] args) {
try {
Socket socket = new Socket("localhost", 2000);
PrintWriter pw = new PrintWriter(socket.getOutputStream(), true);
pw.println("1");
BufferedReader br = new BufferedReader(
new InputStreamReader(socket.getInputStream())
);
String responseMsg = br.readLine();
System.out.println("서버로부터 받은 메세지: " + responseMsg);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
전이중

- 동시에 양방향 전송이 가능한 방식

- 서버 생성
- 클라이언트 생성
- 클라이언트 → 서버 (메세지를 지속적으로 전송)
- 서버 → 클라이언트 (메세지를 지속적으로 전송)
내가 만든 전이중 채팅
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;
public class Server {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
try {
ServerSocket serverSocket = new ServerSocket(5000);
Socket socket = serverSocket.accept();
PrintWriter pw = new PrintWriter(socket.getOutputStream(), true);
BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
System.out.println("클라이언트와 연결 완료");
Thread receiveThread = new Thread(() -> {
String requestMsg;
try {
while ((requestMsg = br.readLine()) != null) {
System.out.println("-클라이언트로부터 받은 메세지: " + requestMsg);
if (requestMsg.equalsIgnoreCase("quit")) {
System.out.println("연결 종료");
break;
}
}
} catch (IOException e) {
throw new RuntimeException(e);
}
});
Thread sendThread = new Thread(() -> {
String sendMsg;
while (true) {
System.out.print("클라이언트로 보낼 메세지 입력 후 엔터: ");
sendMsg = sc.nextLine();
pw.println(sendMsg);
}
});
receiveThread.start();
sendThread.start();
receiveThread.join();
sendThread.join();
} catch (IOException | InterruptedException e) {
throw new RuntimeException(e);
}
}
}
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.Scanner;
public class Client {
public static void main(String[] args) {
final Scanner sc = new Scanner(System.in);
try {
Socket clientSocket = new Socket("localhost", 5000);
BufferedReader br = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
PrintWriter pw = new PrintWriter(clientSocket.getOutputStream(), true);
Thread sendThread = new Thread(() -> {
String responseMsg;
while (true) {
System.out.print("서버로 보낼 메세지 입력 후 엔터: ");
responseMsg = sc.nextLine();
pw.println(responseMsg);
if (responseMsg.equalsIgnoreCase("quit")) {
break;
}
}
});
Thread receiveThread = new Thread(() -> {
String receiveMsg;
try {
while ((receiveMsg = br.readLine()) != null) {
System.out.println("-서버로부터 온 메세지: " + receiveMsg);
}
} catch (IOException e) {
throw new RuntimeException(e);
}
});
sendThread.start();
receiveThread.start();
sendThread.join();
receiveThread.join();
} catch (IOException | InterruptedException e) {
throw new RuntimeException(e);
}
}
}
풀이
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;
public class Server {
public static void main(String[] args) {
try {
// 1. 소켓과 버퍼 만들기
ServerSocket serverSocket = new ServerSocket(2000);
Socket socket = serverSocket.accept();
PrintWriter pw = new PrintWriter(socket.getOutputStream(), true);
Scanner sc = new Scanner(System.in);
BufferedReader br = new BufferedReader(
new InputStreamReader(socket.getInputStream())
);
// 2. 메세지 받기 스레드, 다른 스택이라 try-catch 가능
new Thread(() -> {
while (true) {
try {
String requestMsg = br.readLine();
System.out.println("클라이언트로부터 받은 메세지: " + requestMsg);
} catch (IOException e) {
e.printStackTrace();
}
}
}).start();
new Thread(() -> {
while (true) {
String keyboardMsg = sc.nextLine();
pw.println(keyboardMsg);
}
}).start();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.Scanner;
public class Client {
public static void main(String[] args) {
try {
// 1. 소켓과 버퍼 만들기
Socket socket = new Socket("localhost", 2000);
PrintWriter pw = new PrintWriter(socket.getOutputStream(), true);
Scanner sc = new Scanner(System.in);
BufferedReader br = new BufferedReader(
new InputStreamReader(socket.getInputStream())
);
// 2. 메세지 전송 스레드
new Thread(() -> {
while (true) {
String keyboardMsg = sc.nextLine();
pw.println(keyboardMsg);
}
}).start();
//3. 메세지 읽기 스레드
new Thread(() -> {
while (true) {
try {
String requestMsg = br.readLine();
System.out.println("클라이언트로부터 받은 메세지: " + requestMsg);
} catch (IOException e) {
e.printStackTrace();
}
}
}).start();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
전이중 → state full - 최초의 소켓 연결 후 요청과 응답이 끊기지 않는 거
반이중 → state less - 응답이 끊기는 거
Share article