[소켓]1. 단방향 통신

gov's avatar
Dec 12, 2024
[소켓]1. 단방향 통신
💡
네트워크에서 두 애플리케이션 간 데이터 교환을 가능하게 하는 양방향 통신 방식.
모든 소켓은 포트 번호를 가지고 있어, 해당 포트를 통해 프로세스를 식별.
통신 시 IP 주소와 포트 번호가 모두 필요.
 
데이터 송수신 시 반드시 버퍼(Buffer)를 사용.
  • bw(Buffer Write): 데이터를 보내기 위한 전송 버퍼.
  • br(Buffer Read): 데이터를 받기 위한 수신 버퍼.

전송 방식

1. 단방향 통신

  • 데이터를 한쪽 방향만 전송.
  • 사용 예: 라디오 방송처럼 송신자가 일방적 데이터 전송.

2. 반이중 통신 (Half-Duplex)

  • 한 번에 하나의 방향만 데이터 전송 가능.
  • 작동 원리:
    • 송신(bw) 중에는 수신(br) 대기 상태.
    • 수신 시 이벤트가 발생해 데이터를 처리.
  • 특징:
    • 통신 채널이 한 개.
    • 요청이 있을 때만 데이터 교환(수동적).
  • 사용 예: 무전기, 일반적인 요청-응답 웹 서버.

3. 전이중 통신 (Full-Duplex)

  • 동시에 양방향 데이터 전송 가능.
  • 작동 원리:
    • 두 개의 통신 채널을 사용하거나, 스레드를 활용해 병렬 처리.
    • 송신(bw)과 수신(br)이 동시에 동작.
  • 특징:
    • 통신이 능동적.
    • 실시간 데이터 교환에 적합.
  • 사용 예: 웹소켓, 화상회의.
 

통신 흐름

하드웨어(HS) → 운영 체제(OS) → 애플리케이션(App)

1. 하드웨어(Hardware)

  • 네트워크 카드(NIC)가 물리적 데이터를 송수신.
  • 데이터를 OS로 전달.

2. 운영 체제(OS)

  • 커널이 네트워크 계층의 데이터를 처리.
  • 애플리케이션과 통신하기 위해 파일 인터페이스를 제공.

3. 애플리케이션(App)

  • 소켓(Socket) 생성:
    • OS의 파일 인터페이스를 사용해 소켓을 생성.
    • 소켓은 IP 주소와 포트를 사용해 통신.
  • 데이터를 전송(bw)하거나 수신(br)하며, 통신을 완성.
 

구현 코드

  • MyServer
    • public class MyServer { public static void main(String[] args) throws IOException { try { ServerSocket serverSocket = new ServerSocket(10000); // 1. 서버포켓 생성 Socket socket = serverSocket.accept(); // 2. 리스닝 System.out.println("oh! connect?"); BufferedReader br = new BufferedReader( // 소켓으로 부터 input 읽음 new InputStreamReader(socket.getInputStream()) ); String line = br.readLine(); // 버퍼에 있는 메세지를 \n까지 읽는다 System.out.println("read : " + line); // 읽고 끝. 쓰려면 밑에 bw 구현 } catch (IOException e) { e.printStackTrace(); } } }
 
  • MyClient
    • public class MyClient { public static void main(String[] args) throws IOException { Socket socket = new Socket("localhost", 10000); // 로컬호스트와 포트 필요 PrintWriter pw = new PrintWriter(socket.getOutputStream(), true); pw.println("Hello World"); // BufferedWriter bw = new BufferedWriter( // new OutputStreamWriter(socket.getOutputStream()) // ); // // // 프로토콜 통신 약속: \n 붙임.없으면 터진다 // // bw여러개면 마지막에만 \n 붙이기 // bw.write("Hello World\n"); // 글작성 // bw.flush(); // 전송 } }
      1. PrintWriter
    • 목적: 편리한 텍스트 출력 제공.
    • 특징:
      • 문자열 출력에 특화되어 있음.
      • 다양한 데이터 타입(int, float, String 등)을 텍스트 형태로 출력 가능.
      • 자동으로 줄바꿈이나 포맷팅 지원 (e.g., println, printf).
      • autoFlush 옵션 지원: true로 설정 시 println 또는 printf 실행 후 자동으로 플러시.
    • 장점:
      • 다목적, 직관적인 출력 방식 제공.
      • 줄바꿈이 포함된 출력을 쉽게 처리.
      2. BufferedWriter
    • 목적: 버퍼링을 통해 효율적인 데이터 출력 제공.
    • 특징:
      • 출력 데이터를 임시 저장 후 한 번에 전송하여 입출력 성능을 향상.
      • 줄바꿈과 같은 포맷팅은 수동으로 처리해야 함.
      • 데이터가 버퍼에 남아있을 수 있으므로 항상 flush() 호출 필요.
    • 장점:
      • 대량의 데이터를 처리할 때 효율적.
      • 데이터 출력의 세밀한 제어 가능.
 
 
  • MyWriter 기존 BufferedWriter의 기능에 자동 플러시(autoFlush)println 메서드를 추가하여 편의성을 높인 커스텀 클래스
    • public class MyWriter extends BufferedWriter { private boolean autoFlush = false; public MyWriter(OutputStream stream) { super(new OutputStreamWriter(stream)); } public MyWriter(OutputStream stream, boolean autoFlush) { super(new OutputStreamWriter(stream)); this.autoFlush = autoFlush; } public void println(String msg) { try { this.write(msg); this.write("\n"); if (autoFlush) { this.flush(); } } catch (Exception e) { throw new RuntimeException(e); } } }
      동작 과정
      1. 생성자
        1. OutputStream을 받아 **OutputStreamWriter*로 변환 후, BufferedWriter로 초기화.
          기본 생성자: autoFlush = false.
          추가 생성자: autoFlush 값을 설정.
      1. println 메서드
        1. 주어진 문자열을 출력(write)한 뒤 줄바꿈(\n) 추가.
          autoFlush가 활성화된 경우, 출력 후 즉시 flush() 호출.
          코드 장점
          편리한 줄바꿈 지원
          • BufferedWriter는 기본적으로 줄바꿈 메서드가 없지만, println을 추가하여 이를 간단히 처리 가능.
          자동 플러시 지원
          • PrintWriter처럼 autoFlush 기능을 제공하여 데이터 전송을 자동화 가능.
          커스터마이징 가능
          • 표준 BufferedWriter의 동작을 확장하여 특정 환경(예: 통신 프로토콜 요구 사항)에 맞게 동작을 조정.
Share article

goho