본문 바로가기

공부/컴퓨터

서버를 만들때 주의해야 할점 - 블로킹 메소드 사용 금지

채팅 서버의 경우 처럼 쓰레드별로 클아이언트의 소켓 연결을 전담해서 처리하면
프로그램은 아주 간단해 진다. 하지만 쓰레드를 생성하는 것이 프로세스의 생성보다는
훨씬 가벼운 일이지만, 많은 클라이언트의 동시 접속을 처리하기 위해 네트웍 연결마다
쓰레드를 생성하게 되면 메모리 등 리소스 오버헤드가 커지게 된다. 이런 경우에는
쓰레드 하나에 몇 개의 네트웍 연결을 할당하는 방식으로 개선할 수 있다.

쓰레드 하나가 여러 개의 네트웍 연결을 처리하려면 이 채팅 서버처럼 readLine()과 같은
블로킹 메소드를 사용하면 메시지가 들어올 때까지 이 메소드에서 블록되어 버리기 때문에
그동안 다른 네트웍 연결을 처리할 수가 없다. 따라서 이런 경우에는 넌블로킹 메소드인
InputStream의 available() 메소드나 Reader의 ready()를 사용하여 입력이 있는지 여부를
조사해보고, 입력이 있을 경우 현재 가능한 만큼만 읽어들이는 메소드인 read(byte[]) 혹은
read(char[]) 메소드를 사용해야 한다.

단일 쓰레드로 위의 채팅 서버를 고친다면 단일 쓰레드 부분은 다음과 같은 코드로 실행
될 수 있따. 책의 부록에 포함됨 NonBlockingChatServer.java 소스 코드를 참고하기 바란다.


/**
   * 각 클라이언트의 소켓 입력 상태를 검사한다.
   */

public void run() {
    wile (true) {
        Enumeration enum = clients.elements();
        while ( enum.hasMoreElements() ) {
            Client client = (Client) enum.nextElement();
            try {
                if ( client.in.ready() ) {
                    client.getMessage();
                }
            } catch (IOException e) {
                System.err.println(client.getname()+ " 출력 에러 : " + e.getMessage() ) ;
                client.closeSocket();
            }
        }
        try {
            Thread.sleep(10); // 잠깐씩 쉰다.
        } catch ( InterrupteExecption e) { }
    }
}