운영체제 - 프로세스간 통신( IPC )

TopOfTheHead·2025년 7월 22일

운영체제

목록 보기
10/24

프로세스는 Concurrently하게 처리될 경우 프로세스 간 Independent하거나, Cooperative하게 처리된다.

  • 프로세스가 Independent한 경우
    。다른 프로세스와 데이터를 공유하지 않는 프로세스
    ▶ 스케듈링만 잘하면 문제가 발생되지 않는다.

  • 프로세스가 Cooperative한 경우
    。다른 프로세스와 데이터를 공유하는 프로세스
    ▶ 다른 프로세스에 영향을 주거나 받을 수 있으며 주로 문제가 발생하는 유형

    。대표적으로 부모 프로세스 , 자식 프로세스가 존재

프로세스 간 통신 ( IPC : Inter-Process Communication )
。OS 상에서 Concurrently하게 실행중인 프로세스 간 서로 데이터 및 정보를 공유하기 위한 Mechanism

。프로세스가 Cooperative한 경우 데이터를 주고받는 IPC 기능이 필요한 경우 IPC Mechanism( ex. Shared Memory or Message Passing )으로 IPC를 구현

。IPC를 구현한 IPC System은 컴퓨터 내부 프로세스 간 통신( ex. Pipe ) / 네트워크 상 통신( ex. Socket ) 등이 존재.

IPC의 두가지 주요 메카니즘
。아래 두가지 기법으로 IPC를 구현

  • 공유메모리( Shared Memory )
    。프로세스 간 특정 메모리 공간( = Shared Memory )을 서로 공유하여 데이터를 주고받는 방식으로 IPC를 구현
    ▶ 주로 생산자 프로세스와 소비자 프로세스간 데이터 교환 시 버퍼로서 활용

    。Shared Memory는 메모리 영역으로서 범위가 제한되어있음.
    ▶ bounded buffer

    。모든 프로세스에서 접근이 가능

    。메모리 영역상에서 공유하는 경우 개발자가 Shared Memory에 접근 및 상호작용하는 코드를 일일이 명시적으로 하드코딩하여 작성해야하는 단점 존재
    • 버퍼 ( Buffer )
      。처리속도가 다른 프로세스 간 상호작용하는 데이터를 저장하는 임시저장공간
      ▶ 두 프로세스의 전송률을 비슷하게 조정하는 버퍼링에 활용


  • 메세지전달( Message Passing )
    。송신자 프로세스와 수신자 프로세스 간 메모리 영역 상 Message Queue를 통해 서로 Message를 주고받는 방식으로 IPC를 구현

    。OS가 IPC 용도의 API( send() , receive() )를 기본 제공 및 관리하므로 Shared Memory처럼 개발자가 직접 상호작용하는 코드를 하드코딩할 필요 없이 간편하게 API만 활용

    。프로세스간 통신을 구현하기위해 우선 두 프로세스 간 Communication Link가 사전에 설정되어야하며 이후 send()와 receive()의 두 API를 통해 Message-Passing을 수행

    통신링크 ( Comm.link : Communication Link )
    。Message-Passing 방식으로 IPC를 수행하기 위해 사전에 설정되어야하는 링크
    ▶ 구현된 이후 API를 통해 메시지를 주고받음

    。Comm.link 구현 옵션 :
    1) Direct / Indirect Communication
    2) Synchronous / Asynchronous Communication
    3) Automatic or explicit Buffering

    ex ) Direct하고 , Synchronous 하며 Automatic한 Communication Link 구현

    • Direct or Indirect Communication
      • 직접 통신 연결 ( Direct Communication )
        。메세지를 주고받을 두개의 수신자 프로세스와 송신자 프로세스의 각각의 프로세스 이름을 명시적으로 설정하여 직접적인 통신을 수행

        。통신을 수행할 2개의 프로세스 이름만 알면 프로세스간 통신 링크를 자동으로 구축
        ▶ 구현된 통신 링크는 오직 연결된 두 프로세스 와의 상호작용만 가능

        。프로세스 이름이 변경될 경우 문제가 생기는 단점이 존재
        ▶ Mailbox를 활용한 간접 통신 연결을 활용

        API 종류
        。send( P, 메시지 ) : P 프로세스에게 메세지를 전송

        。receive( Q, 메시지 ) : Q 프로세스으로부터로부터 메세지를 수신



      • 간접 통신 연결 ( Indirect Communication )
        。임의의 프로세스간 메세지 전달 시 Mailbox( = port )를 통해 메세지를 송신 및 수신받는 구조

        。통신을 수행할 임의의 프로세스들이 서로 동일한 Shared Mailbox로 연결되어 공유 시 통신링크를 구축할 수 있다.
        ▶ 직접 통신 연결과 다르게 구현된 통신링크는 메일박스를 통해 2개 이상의 프로세스간 상호작용이 가능

        。각 통신링크는 하나의 메일박스에 대응하며 각 프로세스 사이에 여러개의 통신링크를 구현할 수 있음
        ▶ 복잡한 통신링크를 구현할 수 있다

        。OS는 프로세스에게 다음 메카니즘을 기본적으로 제공.
        메일박스 생성 및 삭제 / 메일박스를 통한 메시지 송수신
        ▶ 다음 메카니즘을 활용하여 OS에 의해 Port( = Mailbox )가 자동으로 관리되도록 설정
        • Mailbox ( = Port )
          。복수의 프로세스로 부터 메시지를 수신받아 저장하거나 송신하여 삭제하는 공유 저장소 용도의 객체

        • API 종류
          。send( A, 메시지 ) : A 메일박스에게 메세지를 전송

          。receive( A, 메시지 ) : A 메일박스으로부터로부터 메세지를 수신


    • Synchronous or Asynchronous Communication
      。Blocking : Synchronous , Non-blocking : Asynchronous
      。다음 4가지 방식을 조합하여 IPC의 Message Passing 방식을 구현
      • Blocking I/O : 동기
        。메세지 송수신 작업이 완료될때까지 송/수신 프로세스를 대기해야하므로 비효율적이지만 데이터의 안정성이 높음

        Blocking Send
        。송신자 프로세스가 메세지 전송 시 해당 메세지가 수신할때까지 Block되어 대기큐에 전송되어 Waiting 상태로 대기
        ▶ 메세지가 수신될때까지 다른 프로세스가 CPU Scheduler에 의해 선택되어 디스패처에 의해 CPU가 할당되어 실행

        Blocking Receive :
        。수신자 프로세스는 메세지를 수신할때까지 대기큐에서 Waiting 상태로 대기

      • Non-Blocking I/O : 비동기
        。메세지 송수신 작업여부에 관계 없이 송/수신 프로세스를 계속 실행할 수 있어 효율적이지만 중간에 프로세스의 연결이 끊길 경우 전송중인 데이터가 불완전하게 전송되므로 불안정

        Non-Blocking Send
        。송신자 프로세스가 메세지 전송 시 메세지 수신여부에 관계없이 계속 Running 상태를 유지

        Non-Blocking Receive
        。수신자 프로세스는 메세지 수신여부에 관계없이 Running 상태로서 계속 Valid Message 또는 Null Message를 내보냄.
        ▶ 내보내는 메세지에 따라 수신여부를 판단.

생산자-소비자 문제 ( Producer-Consumer Problem )
。OS 상에서 여러 프로세스가 공유자원( ex. 버퍼 )에 접근하여 상호작용 시 발생하는 동기화( Syncronization ) 문제
▶ Cooperative한 프로세스간 주로 발생하는 문제

。생산자가 정보를 생성하면 소비자가 해당 정보를 소비하는 형태에서 생산속도와 소비속도의 차이로 인해 발생하는 문제
ex1 ) Compiler가 Assembly Code를 생성 시 Assembler가 해당 코드를 소비하여 machine code를 생성 시 발생하는 문제
ex2 ) 웹 서버가 HTML문서 생성 시 웹 브러우저가 해당 웹 주소로 접근하여 시각화하여 소비하는 경우 발생하는 문제

  • IPC : Shared-Memory 기법으로 문제 해결 시
    。생산자 프로세스와 소비자 프로세스 둘다 Concurrently하게 실행할 경우 메모리 영역 상 Shared-Memory를 Shared Buffer로서 활용하여 동기화를 원활하게하여 데이터를 공유하도록 설정
    ▶ 장치 컨트롤러의 데이터 버퍼링과 유사

    。Shared Buffer는 원형버퍼로 구현

    ▶ 생산자 프로세스는 Shared Buffer에 데이터를 채우고, 소비자 프로세스는 Shared Buffer를 비우면서 상호작용

    。이때 Shared-Memory는 메모리 영역으로서 범위가 제한된 Bounded Buffer이므로 Bounded Buffer Problem이 발생할 수 있음
    ▶ Buffer가 가득찬 경우 생산자 프로세스의 상태를 Waiting 변경 및 Buffer가 빈 경우 소비자 프로세스의 상태를 Waiting으로 설정

    。메모리 영역을 사용하는 방식이므로 개발자가 코드를 일일이 명시적으로 하드코딩하여 작성해야하는 단점 존재
    ▶ 메세지전달 방식을 사용하는 이유 중 하나

    코드구현
    。Shared Buffer 초기화
    ▶ 전역변수로 작성하여 각 프로세스에서 접근하도록 설정

    #include <stdio.h>
    #include <stdbool.h> 
    // 버퍼 초기화
    #define BUFFER_SIZE 10
    typedef struct {
      // 버퍼 요소를 구성할 item 구조체 선언
    } item;
    // 버퍼 배열 초기화
    item buffer[BUFFER_SIZE];
    // 버퍼 인덱스 초기화
    int in = 0;
    int out = 0;

    。생산자 프로세스 정의

    // 생산자 프로세스 정의
    item next_produced;
      while(true){
        // 버퍼가 가득찬 경우 아무 작업도 하지않기
        while(( in + 1 ) % BUFFER_SIZE == out) ; 
        //
        // 버퍼가 빈 경우 item input
        buffer[in] = next_produced;
        in = (in + 1) % BUFFER_SIZE;
      };

    。소비자 프로세스 정의

    // 소비자 프로세스 정의
      item next_consumed;
      while (true) {
        // 버퍼가 비어있는경우 아무 작업하지 않기
        while ( in == out ) ; 
        next_consumed = buffer[out];
        out = (out + 1) % BUFFER_SIZE;
      }

IPC Mechanism으로 구현된 대표적인 IPC System
。Shared Memory ▶ POSIX Shared Memory
。Message Passing ▶ Pipes

  • POSIX Shared Memory
    。Shared Memory Mechanism으로 구현된 IPC System

    。memory-mapped files을 통해 HDD에 저장된 파일을 메모리에 Mapping 후 해당 영역을 Shared Memory로 활용

    。Shared Memory 방식이므로 개발자가 shm_open() , shm_unlink() 등 데이터 전달에 대해 일일이 하드코딩할 코드가 많다
    • POSIX ( Portable Operating System Interface For Unix )
      。서로 다른 UNIX OS 간 호환성을 위해 공통 API를 책정한 Application Interface 규격
      ▶ POSIX를 준수하는 UNIX OS는 다른 UNIX OS와 호환

    • MMF ( Memory Mapped Files )
      。OS에서 HDD에 저장된 파일을 메모리에 Mapping하여 파일을 메모리의 일부로 간주하여 접근할 수 있도록 하는 기능


  • 파일이 매핑된 메모리 주소공간에 POSIX Shared Memory 생성

    1) POSIX Shared Memory 객체 생성
    fd=shm_open(name, O_CREAT | ORDWR, 0666);

    2) 객체의 byte 기준 크기 설정
    ftruncate(fd, 4096)
    ▶ 4096 Byte로 크기 설정

    3) POSIX Shared Memory 객체를 파일의 메모리 상 주소공간으로 Mapping
    mmap(0, SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0)
    • shm_open()
      。POSIX Shared Memory 객체를 생성하거나 기존 객체를 open하는 역할을 수행

      。생성된 객체의 크기는 0이므로 크기 설정이 필요.

    • ftruncate(fd, size)
      。생성된 객체의 크기를 Byte 단위로 설정

    • mmap()
      。POSIX Shared Memory 객체를 메모리 영역으로 Mapping

    • PROT ( Protection Flags )
      。메모리 보호 목적으로 Mapping 된 메모리 영역에 대해 어떠한 접근을 허용할 것인지 지정하는 인자

      PROT 종류

      • PROT_READ
        。메모리 페이지를 읽기 가능하게 설정

      • PROT_WRITE
        。메모리 페이지를 쓰기 가능하게 설정

      • PROT_EXEC
        。메모리 페이지에서 기계어 실행이 가능하도록 허용

      • PROT_NONE
        。메모리 페이지에 어떠한 접근을 모두 금지


    • flags
      。Mapping된 메모리 영역의 종류, 공유 방식, 주소지정방식을 정의하는 인자
      • MAP_SHARED
        。프로세스가 Shared Memory 객체에 대해 해당 메모리 영역에 대한 WRITE 작업을 허용


  • POSIX Shared-Memory API 구현
    • Producer Process
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <unistd.h>
    #include <fcntl.h>
    #include <sys/shm.h>
    #include <sys/stat.h>
    #include <sys/mman.h>
    int main(){
      // 생성할 POSIX shared memory 객체의 크기 , 이름 설정
      const int SIZE = 4096; 
      const char *name = "OS"; 
      //
      // 전달할 메시지 설정
      const char *message_0 = "Hello, ";
      const char *message_1 = "Shared Memory!\n";
      //
      int shm_fd; // shared memory의 file descriptor 정의
      char *ptr; // shared memory 포인터
      //
      // POSIX Shared Memory 객체 생성
      shm_fd = shm_open(name, O_CREAT | O_RDWR, 0666);
      //
      // 객체의 크기 설정
      ftruncate(shm_fd, SIZE);
      //
      // 객체의 Mapping 수행
      ptr = (char *)mmap(0, SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, shm_fd, 0);
      //
      // POSIX Shared Memory 객체로 메세지 공유
      sprintf(ptr, "%s" , message_0);
      ptr += strlen(message_0);
      sprintf(ptr, "%s", message_1);
      ptr += strlen(message_1);
    }

    。이후 터미널에 gcc 파일명.c -lrt로 컴파일
    ▶ -lrt : librt 라이브러리에 정의된 함수를 활용하기위해 해당 라이브러리를 링크

      • librt
        。POSIX 표준 中 Real-time Extension을 제공하는 라이브러리

        。POSIX Shared Memory 를 구현하는 shm_open() 등의 함수는 librt에 구현되어있어 -lrt 없이 컴파일 시 Link Error 발생.


    • Consumer Process
    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <string.h>
    #include <fcntl.h>
    #include <sys/shm.h>
    #include <sys/stat.h>
    #include <sys/mman.h>
    int main(){
      const int SIZE = 4096; 
      const char *name = "OS"; 
      int shm_fd; 
      char *ptr; 
      //
      // 읽기 목적의 POSIX Shared Memory 객체 생성
      shm_fd = shm_open(name, O_RDONLY,0666);
      //
      // POSIX Shared Memory 객체 Mapping
      ptr = (char *)mmap(0, SIZE, PROT_READ , MAP_SHARED, shm_fd, 0);
      // 객체로부터 읽기
      printf("%s", (char *)ptr);
      // 객체 삭제하기
      shm_unlink(name);
      return 0;
    }


    。 메세지가 POSIX Shared Memory에 송신 및 수신이 정상적으로 수행됨을 관측가능.

    。소비자 프로세스에서 shm_unlink()를 통해 메모리 공간상에 Mapping된 shared memory가 삭제됨.
    ▶ 한번 더 호출하는 경우 해당 객체를 찾을 수 없음

Pipes
。초창기 UNIX System에서 활용된 Message Passing으로 구현된 IPC Mechanism

。2개의 프로세스 간 통신으로 데이터를 주고받는 통로
▶ 파이프는 Message Box( = Port) 역할을 수행

。동일한 HW Device 내 프로세스 간 통신 시 사용.
▶ Client-Server System 상 네트워크로 연결된 다른 컴퓨터의 프로세스 접근 시 Pipe 대신 Socket 사용

  • Pipe 구현 시 고려사항
    • 단방향 ( Unidirectional ) / 양방향 ( Bidirectional )

      양방향인 경우 Half Duplex / Full Duplex
      。반이중 ( Half Duplex ) :
      한번에 한 방향으로만 데이터의 송수신이 가능한 것

      。전이중 ( Full Duplex ) :
      데이터를 동시에 송수신이 가능



    • 통신을 수행하는 프로세스 간 Relationship 존재 여부
      。Named Pipe는 Relationship 없이 사용가능
      ex ) 부모 / 자식 프로세스 관계

    • 네트워크 상 통신 여부
      。네트워크로 연결된 다른 컴퓨터의 프로세스 접근 시 Pipe 대신 Socket 사용


  • Pipe의 종류
    。파이프는 Message Box( = Port) 역할을 수행
    • 일반 파이프( Ordinary Pipe ) = 익명 파이프 ( Anonymous Pipe )
      。생산자 소비자 형태에서 두 프로세스간 통신을 수행
      ▶ 통신을 수행하는 프로세스는 서로 부모/자식 프로세스 관계여야한다.
      ▶ 생산자 프로세스는 부모 프로세스로서 파이프 좌측종단( = write end )에 데이터를 생성
      ▶ 소비자 프로세스는 자식 프로세스로서 파이프 우측종단( = read end )에서 데이터를 읽음

      。Ordinary Pipe는 2개의 File Descriptor를 활용한 단방향 ( Unidirectional ) 통신을 수행
      ▶ 양방향 통신 구현 시 2개의 Ordinary Pipe를 구현

      。일반 파이프 구현 시 반드시 부모 / 자식 프로세스 관계로 정의하여 부모 프로세스에서는 Write End , 자식 프로세스에서는 Read End를 수행하며 두 프로세스 모두 Concurrently하게 실행하여 프로세스 간 통신을 구현
      ▶ 파이프를 생성한 프로세스 이외는 접근 불가능

    • 지명 파이프( Named Pipe )
      。프로세스 간 각 파이프에 이름을 지정
      。양방향 통신 ( Bidirectional )
      。부모 자식 프로세스 간 Relationship이 없어도 사용 가능

UNIX System 상 Ordinary Pipe 구현

。Ordinary Pipe 생성 : pipe(int fd[])
。입력종단 ( write end ) : fd[0]
。쓰기종단 ( read end ) : fd[1]

。부모 프로세스는 write end , 자식 프로세스는 read end를 수행하며 두 프로세스 모두 Concurrently하게 동시처리.

#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <string.h>
#define BUFFER_SIZE 25
#define READ_END 0
#define WRITE_END 1
int main(){
  char write_msg[BUFFER_SIZE] = "Greetings";
  char read_msg[BUFFER_SIZE];
  int fd[2]; // file descriptor 초기화
  // 파이프 생성
  pipe(fd);
  // 자식 프로세스 생성
  pid_t pid;
  pid = fork();
  if (pid > 0){ // 부모프로세스
    // wait()이 없으므로 자식프로세스와 함께 실행
    close(fd[READ_END]);
    // 파이프 작성
    write(fd[WRITE_END], write_msg, strlen(write_msg)+1);
    close(fd[WRITE_END]);
  } else if ( pid == 0 ){ // 자식프로세스
    close(fd[WRITE_END]);
    // 파이프 읽기
    read(fd[READ_END], read_msg, BUFFER_SIZE);
    printf("read %s\n", read_msg);
    close(fd[READ_END]);
  }
  return 0;
}

  • 식별자 ( fd : file descriptor )
    。파일 또는 I/O Resource를 처리하는 용도로 활용되는 Abstract Indicator

  • pipe(int배열)
    。UNIX에서 IPC를 위해 Ordinary Pipe를 구현 시 사용하는 System Call
    ▶ WRITE or READ를 수행하는 2개의 식별자를 생성
int fd[2]; // file descriptor 초기화
  // 파이프 생성
  pipe(fd);

。식별자 역할의 int fd[2]를 생성 및 매개변수로 전달시 Write End과 Read End를 수행하는 2개의 식별자를 생성
▶ Read End 용도 식별자 : fd[0]
▶ Write End 용도 식별자 : fd[1]

  • File Descriptor 닫기
    。생성된 Ordinary Pipe는 단방향이므로 식별자의 write(fd) 또는 read(fd) 작업 후 특정방향으로 설정된 식별자를 닫는 과정이 필요.
    ▶ 단방향이므로 각 용도의 실행중인 식별자를 종료해야 다른 용도의 식별자를 실행가능

    。close(fd[0]) : Read End 용도 식별자 종료

    。close(fd[1]) : Write End 용도 식별자 종료

  • 파이프에 메세지 작성
    write(fd[0], 메세지, 메세지크기)

  • 파이프에서 메세지 읽기
    read(fd[1], 버퍼, 버퍼크기)

네크워크상에서의 IPC System
。Web Server 같은 Client - Server System에는 2가지 프로세스 간 통신방법이 존재 ( 소켓 , RPC )

  • 소켓 ( Sockets ) 컴퓨터네트워크 - 소켓

    。네트워크 상에서 연결된 두 컴퓨터의 프로세스 간 IPC를 위한 Endpoint
    ▶ IPC를 수행할 네트워크 상 컴퓨터의 프로세스는 소켓번호로 식별

    。Client Socket과 Server Socket으로 구분되어 소켓을 연결하여 두 프로세스 간 네트워크 통신을 가능하게함.

    。프로토콜 계층 상에서 어플리케이션 계층의 프로세스와 트랜스포트 계층의 프로토콜 간 Message를 전달하는 Interface 역할을 수행

    。IPC 메카니즘으로 Message-Passing을 활용
    ▶ Pipes와 유사

    。네트워크 통신을 수행할 각 프로세스는 하나의 소켓을 가진다
    ▶ 소켓을 생성하는 경우 Port Number가 식별자로서 각각의 소켓에 할당됨

    。Socket = IP Address + Port
    ▶ IP Address 번호와 각 Host의 프로세스를 연결하는 파이프 용도의 Port의 번호를 조합하여 네트워크로 연결된 Host를 식별 후 IPC를 수행
    ▶ Pipe = Message Box = Port

    ex) www.google.com:8080의 경우 도메인 주소로 변환한 IP Addrss의 서버컴퓨터에서 Port를 통해 데이터를 요청
    。 도커 컨테이너에서 Port는 서비스의 단위로 해석할 수 있다
    ▶ 단일 IP Address를 가지면서 각각 다른 Port를 가지는 다수의 도커 컨테이너를 가질 수 있으므로
    • Server Socket
      。Server Socket이 바인딩한 포트번호의 포트에 연결가능한 Client Socket수는 한정됨
      ▶ Load Balancing을 수행

    • Client Socket


  • 원격 프로시저 호출 ( RPC : Remote Procedure Calls )
    。네트워크 상에서 연결된 컴퓨터의 프로세스 간 Procedure Call 메카니즘을 추상화하여 설계된 IPC의 확장개념의 기술

    。Client는 네트워크로 연결된 다른 컴퓨터를 Remote Host로서 Host의 프로세스의 함수 or 프로시저를 원격호출하여 지역함수처럼 실행

    。Skeleton과 Stub간 통신 시 데이터의 Marshaling을 수행하여 전송에 적절한 형식으로 변환

    。Java에서는 RMI( Remote Method Invocation )로 구현됨
    • Stub( = Cilent Stub )
      。Client Side에서 사용되는 Proxy 객체로서 Client가 다른 컴퓨터의 프로세스의 Remote Method를 호출하는 주체로 활용

    • Skeleton ( = Server Stub )
      。Server-Side에서 실행되어 Stub을 통한 Client의 요청으로 Procedure Call한 실제 Method에 전달 및 결과를 Client에게 응답

Java에서의 Socket 구현
자바 Socket 관련 클래스
。Java의 소켓은 네트워크 통신을 위한 API 역할을 수행

。Socket 클래스와 ServerSocket 클래스의 객체를 생성하여 Server Socket과 Client Socket로서 활용

  • Server Socket
    。Server-Side로서 TCP 서버 역할을 수행할 특정 포트번호로 바인딩된 ServerSocket Class의 객체 생성
    ▶ 서버소켓객체는 바인딩된 포트번호로 Client Socket부터의 연결요청을 상시대기

    。Client Socket로부터 연결이 된 경우 서버소켓객체.accept()를 통해 Client Socket의 Socket 객체를 반환
    ▶ Client Socket의 Socket Class객체가 반환된 경우 두 프로세스 간 연결이 정상적으로 되었으며 반환된 Socket 객체를 통해 통신을 수행

    。통신이 전부 수행된 경우 서버소켓객체.close() 를 통해 프로세스 간 연결종료
import java.io.*;
import java.net.*;
public class DateServer {
    public static void main(String[] args) throws Exception {
        // 포트 8080의 TCP 서버소켓 생성
        ServerSocket server = new ServerSocket(8080);
        while ( true ){
            // 포트:8080으로 Client Socket으로부터의 연결요청 대기
            System.out.println("연결대기중");
            // 연결요청 수신 및 Client Socket의 Socket 객체 반환
            Socket client = server.accept();
            PrintWriter pout = new PrintWriter(client.getOutputStream(),true);
            System.out.println("새로운 클라이언트 소켓 연결됨");
            pout.println(new java.util.Date().toString());
            // 소켓 종료 및 연결요청 재대기
            client.close();
        }
    }
}

.

  • Client Socket
    。연결을 수행할 특정 ServerSocket의 컴퓨터의 IP주소, 포트번호를 생성자로 전달하여 연결될 Client Socket 역할의 Socket 객체를 생성
    ▶ 해당 Socket 객체를 통해 데이터의 송수신을 수행
 import java.io.*;
import java.net.*;
public class DateClient {
    public static void main(String[] args) throws Exception {
        Socket socket = new Socket("127.0.0.1", 8080);
        InputStream in = socket.getInputStream();
        BufferedReader br = new BufferedReader(new InputStreamReader(in));
        String line = null;
        // 소켓으로부터 Date 를 Read
        while ((line = br.readLine()) != null ) System.out.println(line);
        // 소켓 연결 종료
        socket.close();
    }
}

출처
。운영체제 공룡책 강의

profile
공부기록 블로그

0개의 댓글