본문 바로가기

프로그래밍/CS

NETWORKING stateless/stateful

SERVER

  • 서버. 네트워크 연결을 기다리는 쪽
  • Socket(소켓) : 서로 다른 통신 환경 연결해주는 객체
  • Server Socket(서버 소켓) : 네트워크 연결을 기다리는 객체
  • 포트 번호 : 동일 서버 내 네트워크 연결을 기다리는 프로그램의 식별 번호. OS는 이 번호로 데이터 받을 프로그램을 결정.
포트 번호

0 ~ 1023 (well-known port)
    - 특정 프로그램이 관습적으로 사용하는 포트 번호
    - 프로그램을 작성할 때 가능한 이 포트 번호를 사용하지 말아야 한다.
    - 7(echo), 20(FTP 데이터 포트), 21(FTP 제어포트), 23(telnet),
      25(SMTP), 53(DNS), 80(HTTP), 110(POP3), 143(IMAP) 등
1024 ~ 49151 (registered port)
    - 일반적인 통신 프로그램을 작성할 때 사용하는 포트 번호
    - 다만 이 범위에 번호 중에서 특정 프로그램이 널리 사용하는 번호가 있다. 피하는게 좋음.
    - 8080(proxy), 1521(Oracle), 3306(MySQL) 등
49152 ~ 65535 (dynamic port)
    - 통신을 하는 프로그램은 반드시 포트번호를 가져야 한다. 그래야 OS가 해당 프로그램을 구분할 수 있다.
    - 따라서 클라이언트 프로그램도 포트번호를 갖는데,  OS로부터 자동 발급 받는다.
    - 이 범위의 포트번호는 클라이언트가 OS로부터 자동 발급 받는 포트 번호이다. 피할 것.
  • 대기열(backlog) : 접속 요청한 클라이언트의 정보를 큐(FIFO) 방식으로 저장하여 관리. 대기열의 크기가 연결 가능한 클라이언트의 최대 개수로, 이를 초과하면 서버는 응답하지 않는다. 일정 시간(timeout) 내 응답을 받지 못하면 예외를 던지고 연결 요청을 취소한다.
    
    System.out.println("서버 대기 중...");
    ServerSocket ss = new ServerSocket(8888);
    // ServerSocket ss = new ServerSocket(8888, 2); -> (포트번호, 대기열수)
    
    OutputStream out = socket.getOutputStream();
    InputStream in = socket.getInputStream())

    System.out.println("클라이언트 연결을 기다리는 중...");
    Socket socket = ss.accept();

    System.out.println("대기 중인 클라이언트 중 한 개의 클라이언트에 대해 연결 승인!");

    socket.close();
    System.out.println("클라이언트와의 연결 해제!");
    
    ss.close();
    System.out.println("서버 종료!");
    

CLIENT

  • 사용자. 연결을 요청하는 쪽.
  • 서버주소("localhost")는 IP, 도메인명 모두 가능
  • localhost : 127.0.0.1 -> 로컬 컴퓨터 가리킴
    
    System.out.println("서버에 연결을 요청 중...");
 
    Socket socket = new Socket("localhost", 8888);
    System.out.println("서버에 연결됨!");
    
    /* 응답 대기시간 지정하기 */
    Socket socket = new Socket();  // 소켓 생성
    SocketAddress socketAddress = new InetSocketAddress("localhost", 8888); // 소켓 주소 설정
    socket.connect(socketAddress, 5000); // (timeout : milliseconds)
    System.out.println("서버에 연결됨!");
    
    OutputStream out = socket.getOutputStream();
    InputStream in = socket.getInputStream()) {

    socket.close();
    

STATELESS

  • 서버에 작업을 요청할 때 연결하고, 서버로부터 응답을 받으면 연결을 끊음 => [요청/응답] 한 번 수행
    • 비영속적 단일 작업 처리 시 적합
      • HTTP : 웹브라우저 -> 서버 연결, 요청 -> 서버 응답 -> 연결 끊음  ==> Session
      • 메신저 : 메신저 서버에 연결 -> 메시지 전송 -> 연결 끊음
      • 메일 : 메일 서버에 데이터 전송 -> 연결 끊음
      • 오프라인 : 114, 배달
  • + ) 자동으로 서버와 연결을 끊기 때문에, 서버 입장에서는 메모리 절약
    • 작업 처리 동안만 연결정보를 유지 -> stateful 방식 보다 더 많은 클라이언트의 요청 처리 가능
  • - ) 요청할 때 마다 서버에 새로 연결해야 하기 때문에 실행 시간이 오래 걸림
    • 실행시간 = 연결 시간 + 데이터 전송 시간 + 작업 처리 시간 + 데이터 수신 시간
    • 연결시, 사용자 인증(authentication; 아이디, 암호 유효 여부 검사)이나 사용권한 확인(authorization; 사용자 접근 허용 범위 확인) 등을 수행하는 경우 시간이 더 많이 걸림

STATEFUL

  • 서버와 연결 후, 클라이언트에서 연결을 끊을 때 까지 계속해서 연결을 유지하며 클라이언트 요청 처리
    • 영속성 필요한 작업 처리 시 적합
      • 게임 서버 : 접속하면 게임을 끝낼 때 까지 데이터를 주고 받음
      • 화상 통신 : 한 번 연결하면 연결 끊을 때 까지 데이터를 주고 받음
      • 채팅 서버 : 전용 클라이언트 이용한 채팅
      • 텔렛 : 원격 제어 프로그램
      • FTP : 파일 전송 프로그램
  • + ) 한 번 서버에 연결되면 클라이언트가 연결을 끊을 때까지 유지 -> 요청에 대한 응답이 빠름.
    • 연결된 상태에서 수행한 작업 정보 서버에 유지 가능
    • 작업처리하는데 걸리는 시간 = 데이터 전송 시간 + 작업 처리 시간 + 데이터 수신 시간
    • 즉, 작업을 요청할 때마다 연결할 필요가 없기 때문에 연결하는데 시간이 걸리지 않음
  • - ) 클라이언트가 작업을 요청하지 않더라도 계속 연결정보를 유지해야 함
    • => 이전 클라이언트의 연결이 끊길 때 까지 다음 클라이언트의 요청을 처리할 수 없다 
      • 해결책)
      • 각 클라이언트와의 통신을 독립적으로 실행 => 쓰레드(Thread) 사용

TCP (Connection-Oriented)

  • 연결 후 통신
  • ex) 전화

UDP (Connectionless)

  • 연결 없이 데이터 전송 
  • ex) 편지

'프로그래밍 > CS' 카테고리의 다른 글

어셈블리어  (0) 2021.01.13
TCP/UDP  (0) 2020.02.11
자료구조 - Stack vs Queue || Shallow/Deep Copy  (0) 2020.01.13
ArrayList vs LinkedList  (0) 2020.01.12
연산자  (0) 2019.12.16