1. 단방향 통신 (Simplex)
1️⃣ 단방향 통신이란?
한쪽에서만 데이터 전송 가능, 반대 방향은 불가
2️⃣ 단방향 통신의 특징
- 데이터 흐름 한 방향
- 구조 단순
- 응답 불가
3️⃣ 단방향 통신의 예시
- TV 방송
- 라디오
- 키보드 → 컴퓨터
- 센서 데이터 전송
4️⃣ 실습
1) Server
package com.mtcoding.ex04;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;
public class MyServer2 {
public static void main(String[] args) {
try {
ServerSocket ss = new ServerSocket(20000);
Socket socket = ss.accept();
InputStream in = socket.getInputStream();
InputStreamReader ir = new InputStreamReader(in);
BufferedReader br = new BufferedReader(ir);
while (true) {
String line = br.readLine();
System.out.println("[Server] " + line);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}2) Client
package com.mtcoding.ex04;
import java.io.*;
import java.net.Socket;
public class MyClient2 {
public static void main(String[] args) {
try {
Socket socket = new Socket("127.0.0.1",20000); // 자기 자신 IP 주소 - 127.0.0.1 or localhost
InputStream keyStream = System.in;
InputStreamReader keyReader = new InputStreamReader(keyStream);
BufferedReader keyBuf = new BufferedReader(keyReader);
OutputStream out = socket.getOutputStream();
OutputStreamWriter ow = new OutputStreamWriter(out);
BufferedWriter bw = new BufferedWriter(ow);
while (true) {
String keyBoardDate = keyBuf.readLine();
bw.write(keyBoardDate);
bw.write("\n");
bw.flush();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
3) Client 결과

4) Server 결과

2. 반이중 통신 (Half-Duplex)
1️⃣ 반이중 통신이란?
양방향 통신 가능하지만, 동시에 불가능
요청(Request)이 오면 응답(Response) → 동기적
주로 웹서버에서 사용됨
2️⃣ 반이중 통신의 특징
- 한 번에 한 쪽만 송신
- 충돌 방지 필요
- 효율 중간
3️⃣ 반이중 통신의 예시
- 무전기
- 일부 옛날 Ethernet
- RS-485
4️⃣ 반이중 통신의 목적
클라이언트가 필요한 것을 구체적으로 서버에 요청하고 서버로부터 응답이 오면 통신 끝
통신을 끊지 않고 연결 유지하면 비용 많이 듦!

5️⃣ 실습
1) Server
package com.mtcoding.ex05;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;
public class MyServer3 {
public static void main(String[] args) {
try {
ServerSocket ss = new ServerSocket(20000);
Socket socket = ss.accept();
// 읽기 버퍼
Scanner sc = new Scanner(socket.getInputStream());
// 쓰기 버퍼
PrintWriter pw = new PrintWriter(socket.getOutputStream(), true);
while (true) {
String line = sc.nextLine(); // 엔터키(\n)까지 읽기 / 엔터키까지 안읽는 다른 함수도 있음
System.out.println("[Server] " + line);
pw.println("ok");
}
} catch (Exception e) {
e.printStackTrace();
}
}
}2) Client
package com.mtcoding.ex05;
import java.io.*;
import java.net.Socket;
import java.util.Scanner;
public class MyClient3 {
public static void main(String[] args) {
try {
Socket socket = new Socket("127.0.0.1",20000); // 자기 자신 IP 주소 - 127.0.0.1 or localhost
Scanner sc = new Scanner(System.in); // 키보드에 연결된 버퍼
PrintWriter pw = new PrintWriter(socket.getOutputStream(), true); // 쓰기 버퍼 / true -> autoflush
Scanner socketSc = new Scanner(socket.getInputStream());
while (true) {
String keyBoardDate = sc.nextLine();
pw.println(keyBoardDate); // ln이 \n이 넣어주고, autoFlush가 된다.
String recv = socketSc.nextLine();
System.out.println("서버로부터 받은 메시지 : " + recv);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
3) Server 결과

4) Client 결과

3. 전이중 통신 (Full-Duplex)
1️⃣ 전이중 통신이란?
양쪽이 동시에 송신/수신 가능 (병렬)
동시에 이루어져야 하기 때문에 소켓마다 2개의 스레드가 필요
2️⃣ 전이중 통신의 특징
- 가장 빠르고 효율적
- 구현 복잡
- 자원 더 필요
3️⃣ 전이중 통신의 예시
- 전화 통화
- 인터넷 (TCP 소켓)
- 채팅
- HTTP/HTTPS
4️⃣ 실습
1) Server
package com.mtcoding.ex08;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;
public class MyServerDuplex {
public static void main(String[] args) {
try {
ServerSocket ss = new ServerSocket(20000);
System.out.println("[server] 대기중...");
Socket socket = ss.accept();
System.out.println("[server] 연결됨: " + socket.getInetAddress());
Scanner socketSc = new Scanner(socket.getInputStream());
PrintWriter pw = new PrintWriter(socket.getOutputStream(), true);
Scanner keyboardSc = new Scanner(System.in);
// 1) 수신 스레드: 클라이언트 -> 서버
Thread receiver = new Thread(() -> {
try {
while (socketSc.hasNextLine()) {
String line = socketSc.nextLine();
System.out.println("[server][recv] " + line);
// 자동 응답도 가능
// pw.println("ok: " + line);
if ("quit".equalsIgnoreCase(line)) {
try { socket.close(); } catch (Exception ignored) {}
break;
}
}
} catch (Exception e) {
System.out.println("[server] receiver 종료: " + e.getMessage());
}
});
// 2) 송신 스레드: 서버 -> 클라이언트 (서버 키보드 입력)
Thread sender = new Thread(() -> {
try {
while (true) {
String msg = keyboardSc.nextLine();
pw.println(msg);
if ("quit".equalsIgnoreCase(msg)) {
try { socket.close(); } catch (Exception ignored) {}
break;
}
}
} catch (Exception e) {
System.out.println("[server] sender 종료: " + e.getMessage());
}
});
receiver.start();
sender.start();
} catch (Exception e) {
e.printStackTrace();
}
}
}2) Client
package com.mtcoding.ex08;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.Scanner;
public class MyClientDuplex {
public static void main(String[] args) {
try {
Socket socket = new Socket("127.0.0.1", 20000);
Scanner keyboardSc = new Scanner(System.in);
Scanner socketSc = new Scanner(socket.getInputStream());
PrintWriter pw = new PrintWriter(socket.getOutputStream(), true);
// 1) 수신 스레드: 서버 -> 클라이언트
Thread receiver = new Thread(() -> {
try {
while (socketSc.hasNextLine()) {
String recv = socketSc.nextLine();
System.out.println("[client][recv] " + recv);
}
} catch (Exception e) {
System.out.println("[client] receiver 종료: " + e.getMessage());
}
});
// 2) 송신 스레드: 클라이언트 -> 서버 (키보드)
Thread sender = new Thread(() -> {
try {
while (true) {
String msg = keyboardSc.nextLine(); // 블로킹
pw.println(msg); // autoFlush=true
// 종료 명령 예시
if ("quit".equalsIgnoreCase(msg)) {
try { socket.close(); } catch (Exception ignored) {}
break;
}
}
} catch (Exception e) {
System.out.println("[client] sender 종료: " + e.getMessage());
}
});
receiver.start();
sender.start();
} catch (Exception e) {
e.printStackTrace();
}
}
}3) Server 결과

4) Client 결과

4. 통신 방식 비교표
구분 | 단방향 | 반이중 | 전이중 |
방향 | 한쪽만 | 양쪽 가능(번갈아) | 양쪽 동시 |
동시에 송수신 | ❌ | ❌ | ⭕ |
속도 | 느림 | 중간 | 빠름 |
Share article