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)
UDP (Connectionless)