티스토리 뷰

Computer/Apache MINA

[MINA] Quick Start Guide (KOREAN)

인생이글케쉬우냐 2009. 5. 14. 15:18

출처 아파치 미나 두서없이 주절거림 - Apache MINA Quick Start Guide 번역
원본 http://natan70.spaces.live.com/Blog/cns%219168BA121D2B3458%21135.entry
MINA v2.0 Quick Start Guide

Introduction

이 튜토리얼은 MINA를 기반으로 프로그램을 작성하는 방법을 알려주게 된다.  이 튜토리얼에서는 time서버를 구축하는 예를 들 것이다.  다음의 요구사항은 이 튜토리얼을 진행하는데 필요한 것들이다.:

  • MINA 2.x Core
  • JDK 1.5 or greater
  • SLF4J 1.3.0 or greater
    • Log4J 1.2 사용자들: slf4j-api.jar, slf4j-log4j12.jar, and Log4J 1.2.x
    • Log4J 1.3 사용자들: slf4j-api.jar, slf4j-log4j13.jar, and Log4J 1.3.x
    • java.util.logging 사용자들: slf4j-api.jar and slf4j-jdk14.jar
    • 중요사항: 여러분이 사용하고 있는 로깅프레임웍에 꼭 맞는 slf4j-*.jar 를 사용해야만 한다.
      적용시점에, slf4j-log4j12.jar 와 log4j-1.3.x.jar 는 함께 사용될 수 없으며, 함께 사용되면 오류를 유발하게 된다.

이 프로그램은 Windows© 2000 professional 과 linux 두 곳에서만 테스트되었다.  만약, 이 프로그램으로 작업중 어떠한 문제가 발생된다면 MINA 개발자와 이야기하기 위해 우리와 접촉 하기를 망설이지는 않도록 하라.  또한, 이 튜토리얼은 여러가지 개발환경(IDE, editors..etc)에 독립적으로 작성되었다.  이 튜토리얼은 여러분이 즐겨사용하는 어떠한 환경에서도 잘 작동할 것이다.  컴파일이나 실행 명령은 간결함을 위해 생략되었다.  컴파일이나 실행과 관련된 문의사항이나 도움이 필요하다면 Java tutorial 의 도움을 받도록 하라.

MINA time server 작성하기 

이제 MinaTimeServer.java 파일부터 작성해보기로 하자. 최초의 코드는 아래와 같다:

public class MinaTimeServer {

    public static void main(String[] args) {
    	// code will go here next
    }
}

이 코드는 모두에게 간단할 수 밖에 없을것이다.  프로그램을 시작하기 위한 main 메써드를 간단하게 정의하고 있다.  이 시점에서 우리는 서버를 만들기 위한 코드를 작성하기 시작할 것이다.  첫번째로, 요청 connection을 리스닝하는 객체가 필요하다.  TCP/IP기반으로 작동할 것이기 때문에, SocketAcceptor 라는 것이 추가되어야 한다.

import org.apache.mina.common.IoAcceptor;
import org.apache.mina.transport.socket.nio.NioSocketAcceptor;

public class MinaTimeServer
{

    public static void main( String[] args )
    {
        IoAcceptor acceptor = new NioSocketAcceptor();
    }

}

NioSocketAcceptor 를 추가하여 핸들러 클래스를 정의하여 사용할 수 있고, NioSocketAcceptor 를 특정 port 에 바인드할 수 있다.  SocketAcceptor 에 쓰레드모델을 추가하는데 관심이 있다면 쓰레드모델 설정 튜토리얼을 읽어보기 바란다.
이제 우리는 NioSocketAcceptor 설정을 추가하게 된다.  이것은 소켓에 지정된 세팅을 통해 클라이언트로부터의 connection을 허용할 수 있도록 한다.

import java.nio.charset.Charset;

import org.apache.mina.common.IoAcceptor;
import org.apache.mina.filter.codec.ProtocolCodecFilter;
import org.apache.mina.filter.codec.textline.TextLineCodecFactory;
import org.apache.mina.filter.logging.LoggingFilter;
import org.apache.mina.transport.socket.nio.NioSocketAcceptor;

public class MinaTimeServer
{
    public static void main( String[] args )
    {
        IoAcceptor acceptor = new NioSocketAcceptor();

        acceptor.getFilterChain().addLast( "logger", new LoggingFilter() );
        acceptor.getFilterChain().addLast( "codec", new ProtocolCodecFilter( new TextLineCodecFactory( Charset.forName( "UTF-8" ))));
    }
}

다음으로, 필터를 설정에 추가했다.  LoggingFilter 필터는 세션생성후, 메시지수신후, 메시지 전송, 세션닫기 ()등에서 로그를 남기게 된다.  다음 필터는 ProtocolCodecFilter로서, 메시지 객체에 바이너리변환이나 프로토콜 별로 적절한 데이터를 넣을 수 있게 해주고, 반대의 과정을 처리할 수 있게 해준다.

이 시점에서 클라이언트 접속과 현재 시간에 대한 요청을 처리하는데 사용될 핸들러를 정의해보자.  핸들러 클래스는 IoHandler 인터페이스를 구현한 클래스여야 한다.  여기까지가 MINA를 사용하는 프로그램의 거의 대부분이고, 클라이언트로부터의 각종 요청을 처리할 수 있는 프로그램의 토대가 만들어진 것이다.  이 튜토리얼에서는 IoHandlerAdapter 클래스를 상속받도록 한다.  이 클래스는 adapter design pattern  을 이용한 것으로 IoHandler 인터페이스를 구현해 기본적으로 필요한 거의 대부분의 코드를 간단하게 사용할 수 있도록 이미 만들어져 있다.

import java.io.IOException;
import java.nio.charset.Charset;

import org.apache.mina.common.IdleStatus;
import org.apache.mina.common.IoAcceptor;
import org.apache.mina.filter.codec.ProtocolCodecFilter;
import org.apache.mina.filter.codec.textline.TextLineCodecFactory;
import org.apache.mina.filter.logging.LoggingFilter;
import org.apache.mina.transport.socket.nio.NioSocketAcceptor;

public class MinaTimeServer
{
    public static void main( String[] args ) throws IOException
    {
        IoAcceptor acceptor = new NioSocketAcceptor();

        acceptor.getFilterChain().addLast( "logger", new LoggingFilter() );
        acceptor.getFilterChain().addLast( "codec", new ProtocolCodecFilter( new TextLineCodecFactory( Charset.forName( "UTF-8" ))));

        acceptor.setHandler(  new TimeServerHandler() );

        acceptor.getSessionConfig().setReadBufferSize( 2048 );
        acceptor.getSessionConfig().setIdleTime( IdleStatus.BOTH_IDLE, 10 );
    }
}

MinaTimeServer 클래스에 세 줄의 새로운 코드가 삽입되었다.  이들 메쏘드는 IoHandler에서 필요로 하는 인풋버퍼사이즈와 세션의 idle속성을 세팅한다.  버퍼사이즈는 OS에서 받아들여야 하는 데이터를 위해 어느 정도 공간을 확보해야 하는지 지정한다.  두번째 줄은 idle세션을 언제 체크해야 하는지 지정한다.  setIdleTime을 호출할 때, 첫번째 인자는 세션이 idle상태인지 결정할 때 어떠한 액션이 이루어져야 하는지 정의하고,  두번째 인자는 세션에서 최후에 어떤 동작이 발생한 이후 idle상태가 얼마나 지속될 때 idle이라고 판단할지에 대한 시간으로 '초'로 계산된다.

핸들러 코드는 아래와 같다:

import java.util.Date;

import org.apache.mina.common.IdleStatus;
import org.apache.mina.common.IoHandlerAdapter;
import org.apache.mina.common.IoSession;

public class TimeServerHandler extends IoHandlerAdapter
{
    @Override
    public void exceptionCaught( IoSession session, Throwable cause ) throws Exception
    {
        cause.printStackTrace();
    }

    @Override
    public void messageReceived( IoSession session, Object message ) throws Exception
    {
        String str = message.toString();
        if( str.trim().equalsIgnoreCase("quit") ) {
            session.close();
            return;
        }

        Date date = new Date();
        session.write( date.toString() );
        System.out.println("Message written...");
    }

    @Override
    public void sessionIdle( IoSession session, IdleStatus status ) throws Exception
    {
        System.out.println( "IDLE " + session.getIdleCount( status ));
    }
}

이 클래스에서 사용되는 메쏘드들은 exceptionCaught, messageReceived, sessionIdle 이다. exceptionCaught 는 원격접속을 핸들링하는 일반적인 과정에서 발생하는 예외상황을 처리하기 위해 핸들러에 항상 정의되어야 한다.  이 메쏘드가 정의되지 않으면 예외는 리포트되지 않을 것이다.

exceptionCaught 메쏘드는 오류에 대한 스택추적을 출력하고 세션을 닫을 것이다.  대부분의 프로그램에서 이것은 예외상황에 대한 복구등을 따로 하지 않는 이상 표준적인 작동방법이 될 것이다.

messageReceived 메쏘드는 클라이언트로부터 데이터를 받아 현재시간을 클라이언트에 되돌려 줄 것이다.  클라이언트로부터 받은 메시지가 "quit" 이라면 세션이 닫힐 것이다.  이 메쏘드는 또한 현재시간을 클라인트에 출력하도록 한다.  여러분이 사용한 프로토콜 코덱에 의해서 이 메쏘드로 전달되는 객체(두번째 인자)는 서로 다를 뿐만 아니라 session.write(Object) 메쏘드에서 전달되는 객체도 다를 것이다.  여러분이 프로토콜 코덱을 지정하지 않는다면 IoBuffer 객체를 넘겨받게 되고 IoBuffer 를 작성해야 한다.

sessionIdle 메쏘드는 acceptor.getSessionConfig().setIdleTime( IdleStatus.BOTH_IDLE, 10 ); 에서 지정된 시간동안 idle 상태로 있게될 때 한 번 호출되게 된다.

이제 남은 일은 서버가 리스닝하게 될 소켓주소를 정의하는것과 서버가 실행되도록 작성하는 일만 남았다.  코드는 아래 보여지는 것과 같다:

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.charset.Charset;

import org.apache.mina.common.IoAcceptor;
import org.apache.mina.filter.codec.ProtocolCodecFilter;
import org.apache.mina.filter.codec.textline.TextLineCodecFactory;
import org.apache.mina.filter.logging.LoggingFilter;
import org.apache.mina.transport.socket.nio.NioSocketAcceptor;

public class MinaTimeServer
{
    private static final int PORT = 9123;

    public static void main( String[] args ) throws IOException
    {
        IoAcceptor acceptor = new NioSocketAcceptor();

        acceptor.getFilterChain().addLast( "logger", new LoggingFilter() );
        acceptor.getFilterChain().addLast( "codec", new ProtocolCodecFilter( new TextLineCodecFactory( Charset.forName( "UTF-8" ))));

        acceptor.setHandler( new TimeServerHandler() );
        acceptor.getSessionConfig().setReadBufferSize( 2048 );
        acceptor.getSessionConfig().setIdleTime( IdleStatus.BOTH_IDLE, 10 );
        acceptor.bind( new InetSocketAddress(PORT) );
    }
}

보이는 바와 같이 acceptor.setLocalAddress( new InetSocketAddress(PORT) ); 를 호출하게 된다. 이 메쏘드는 이 서버가 어떤 호스트명과 포트로 리스닝하게 될지 정의한다.  마지막 메쏘드는 IoAcceptor.bind() 를 호출하는 것이다.  이 메쏘드는 지정된 포트로 바인딩하고 원격 클라언트의 프로세스를 시작할 것이다.

Time server 사용하기

이 시점에서 우리는 프로그램을 컴파일하고 사용할 수 있다.  한 번은 컴파일을 해야 어떤 일이 일어날지 테스트해 볼 수 있다.  가장 손쉬운 테스트 방법은 프로그램을 실행하고 telnet으로 접속하는 것이다:

Client Output
Server Output
user@myhost:~> telnet 127.0.0.1 9123
Trying 127.0.0.1...
Connected to 127.0.0.1.
Escape character is '^]'.
hello
Wed Oct 17 23:23:36 EDT 2007
quit
Connection closed by foreign host.
user@myhost:~>
MINA Time server started.
Message written...

다음은 무엇을 하나?

우리의 문서 페이지에서 더 많은 자료를 찾아볼 수 있다. 또한 다른 튜토리얼 이어서 읽어볼 수 있을 것이다.

Mark Webb 작성, 2008년 4월 9일 Mark Webb 최종 에디트.  (view change)

신우석 번역 (^^의역, 오역 다수 발생가능)


반응형

'Computer > Apache MINA' 카테고리의 다른 글

[MINA] Changes Between 2.x and 1.x  (0) 2009.05.19
[MINA] MINA vs Netty  (0) 2009.05.14
[MINA] Download  (0) 2009.05.14
[MINA] Who is "MINA"? What is "MINA"?  (0) 2009.05.14
[MINA] 스터디 시작하기 전에...  (1) 2009.05.14