자바 진급 학습:네트워크 서버 프로 그래 밍
자바 의 Socket API 는 네트워크 프로 그래 밍 에 편리 한 대상 인 터 페 이 스 를 제공 합 니 다.본 고 는 간단 한 TCP 에코 서버 를 예 로 들 어 자바 로 네트워크 서버 를 완성 하 는 방법 을 보 여 주 었 다.
예 를 들 어 TCP Echo Server 는 다음 과 같은 방식 으로 작 동 합 니 다.
클 라 이언 트 가 TCP 를 통 해 서버 에 연결 되면 클 라 이언 트 는 이 연결 을 통 해 서버 에 데 이 터 를 보 낼 수 있 고 서버 가 데 이 터 를 받 으 면 이 데 이 터 를 같은 TCP 연결 로 클 라 이언 트 에 보 낼 수 있 습 니 다.서버 는 클 라 이언 트 가 닫 힐 때 까지 이 연결 을 유지 합 니 다.
서버 가 여러 클 라 이언 트 를 동시에 처리 할 수 있어 야 하기 때문에 우 리 는 먼저 흔히 볼 수 있 는 다 중 스 레 드 서비스 모델 을 선택 합 니 다.
Thread 가 감청 서비스 포트 를 담당 하도록 합 니 다.새로운 연결 이 생 겼 을 때 이 감청 의 Thread 는 이 연결 에 새로운 Thread 를 만들어 처리 합 니 다.이렇게 하면 서버 는 여러 개의 연결 을 받 아들 이 고 여러 개의 Thread 로 각각 처리 할 수 있 습 니 다.
다음은 해당 서버 프로그램 입 니 다.
public class EchoServer implements Runnable {
public void run() {
try {
ServerSocket svr = new ServerSocket(7);
while (true) {
Socket sock = svr.accept();
new Thread(new EchoSession(sock)).start();
}
} catch (IOException ex) {
throw new ExceptionAdapter(ex);
}
}
}
이 코드 는 먼저 ServerSocket 의 대상 을 만 들 고 TCP 포트 7 에 감청 시 킨 다음 하나의 순환 에서 accept()방법 으로 새로운 연결 을 받 고 이 연결 을 처리 하 는 Thread 를 만 듭 니 다.모든 클 라 이언 트 연결 을 실제 처리 하 는 논 리 는 EchoSession 클래스 에 포함 되 어 있 습 니 다.
상기 코드 에서 Exception Adapter 라 는 종 류 를 사 용 했 습 니 다.checked Exception 을 Runtime Exception 으로 포장 하 는 역할 을 합 니 다.자세 한 설명 은 자바 에서 Checked Exception 을 사용 하지 않도록 참고 할 수 있 습 니 다.
다음은 EchoSession 의 코드 입 니 다.
public class EchoSession implements Runnable {
public EchoSession(Socket s) {
_sock = s;
}
public void run() {
try {
try {
InputStream input = _sock.getInputStream();
OutputStream output = _sock.getOutputStream();
byte [] buf = new byte [128];
while (true) {
int count = input.read(buf);
if (count == -1)
break;
output.write(buf, 0 , count);
}
} finally {
_sock.close();
}
} catch (IOException ex) {
throw new ExceptionAdapter(ex);
}
}
protected Socket _sock = null;
}
EchoSession 은 Socket 대상 을 구조 적 매개 변수 로 받 아들 입 니 다.run()방법 에서 이 Socket 대상 의 InputStream 에서 데 이 터 를 읽 고 이 Socket 의 OutputStream 에 기록 합 니 다.이 연결 이 클 라 이언 트 에 의 해 닫 힐 때 까지(InputStream 의 read 방법 은-1 로 되 돌아 갑 니 다).
EchoSession 은 EchoSession 의 부모 클래스 로 Thread 를 사용 하 는 것 을 연상 시 키 는 스 레 드 가 필요 합 니 다.그러나 이렇게 하 는 것 은 융통성 이 없고 지출 도 비교적 크다.EchoSession 이 Runnable 인 터 페 이 스 를 실현 하도록 선택 하면 훨씬 유연 하 다.다음 스 레 드 풀 을 사용 하 는 에코 서버 에서 이 점 을 볼 수 있다.
이상 은 이미 완전한 TCP 에코 서버 입 니 다.그러나 고객 의 끊 임 없 는 연결 과 끊 김 에 따라 이 서버 는 끊임없이 스 레 드 를 생 성하 고 제거 합 니 다.이 두 가 지 는 모두 비교적'비 싼'작업 입 니 다.이런 소 모 를 피하 기 위해 서 는 Thread Pool 의 메커니즘 을 사용 하 는 것 을 고려 할 수 있다.
간단 한 Thread 버퍼 에 사용 되 는 글 에서 Thread Pool 의 실현 은 EchoServer 를 다음 과 같이 수정 할 수 있 습 니 다(EchoSession 은 수정 할 필요 가 없습니다).
public class EchoServer implements Runnable {
public void run() {
try {
ServerSocket svr = new ServerSocket(7);
//스 레 드 풀 초기 화
SyncQueue queue = new SyncQueue(10);
for (int i = 0; i < 10; i ++) {
new Thread(new Worker(queue)).start();
}
while (true) {
Socket sock = svr.accept();
//Thread Pool 에 퀘 스 트 넣 기
queue.put(new EchoSession(sock));
}
} catch (IOException ex) {
throw new ExceptionAdapter(ex);
}
}
}
이 를 통 해 EchoSession 이 Runnable 인터페이스의 유연성 을 실현 하고 수정 하지 않 아 도 Thread Pool 에서 사용 할 수 있 음 을 알 수 있다.
이 예 에서 사용 하 는 Thread Pool 은 비교적 간단 하고 Thread 수량 을 동적 으로 조정 하 는 기능 이 없 기 때문에 이 Echo Server 는 최대 10 개의 클 라 이언 트 만 동시에 서비스 할 수 있 습 니 다.그러나 SyncQueue 를 다시 불 러 오 면 이 제한 을 돌파 하기 위해 편리 하 게 이 기능 을 추가 할 수 있 습 니 다.
네트워크 서버 의 성능 과 병발 도 에 대한 요구 가 높 을 때 모든 클 라 이언 트 를 하나의 전문 적 인 Thread 로 처리 하면 우리 의 요 구 를 만족 시 키 지 못 할 수도 있 습 니 다(수천 개의 클 라 이언 트 가 동시에 있 는 상황 을 상상 해 보 세 요).이 때 자바 의 NIO API 를 사용 하여 서버 구 조 를 구축 하 는 것 을 고려 할 수 있 습 니 다.NIO 에서 IO 작업 이 모두 차단 되 지 않 기 때문에 우 리 는 아주 적은 Thread 만 있 으 면 CPU 를 충분히 이용 하여 여러 클 라 이언 트 의 요청 을 처리 할 수 있 습 니 다.NIO 에 관 한 이 야 기 는 더 이상 군말 하지 않 겠 습 니 다.나중에 토론 할 기회 가 있 기 를 바 랍 니 다.:)