작성중 ...

'Expired > Java Works' 카테고리의 다른 글

왜 Java NIO는 사용하기 힘든가?  (2) 2011.12.23
Java로 구현하는 웹기반 원격제어 프로그램  (8) 2009.04.19
자막(smi) 파일에서 대본 추출 프로그램  (6) 2008.11.09
NIO 강좌 - 3  (0) 2008.02.09
NIO 강좌 - 2  (0) 2008.02.09
결론부터 말하면 NonBlocking의 원리, Network 프로그래밍일 경우 OS에서 동작하는 Socket의 동작 방식을 모르기 때문이다.

Java의 Standard IO의 경우 사실 단순하다.
하나의 Connection에 대해서 하나의 Thread가 1:1로 대응되어,
개발시 하나의 Connection에 대한 처리 로직이 명확하고, 다른 Connection에 대해 독립적이기 때문이다.

쉽게 말해 개발자가 개발하기 쉬운 구조다.

하지만 NIO의 경우 다수의 Client Connection을 극단적인 경우 하나의 Thread 만으로도 처리할 수 있는 구조이다.

NonBlocking에 대한 심도 깊은 이해가 필요하다.
사실 NonBlocking은 의미적으로는 간단하다.
NonBlocking Method를 호출할때 일반 IO와 달리 Blocking 되지 않고 즉시 Return됨을 의미한다.

하지만 Blocking IO만 접해왔던 개발자들에게 즉시 Return이라는 것은 쉽게 이해할 수 없는 부분이다.

왜냐하면 read(buffer) 라는 method를 call해서 int형으로 넘겨받은 값이, 실질적으로 client에 전송된 byte의 수를 의미하는 것인데, 이것은 달리 해석하면, data 전송이후 실질적으로 client가 해당 data를 consume한 것이 확인 되었을때 알 수 있는 값이기 때문이다.

쉽게 말해서 blocking method 호출시 최소한 작업 완료에 대한 응답값이 필요하다.
서버가 특정 data를 전송했을때, client로 부터 data가 consume되었다는 프로토콜 구조적인 확인이 필요하고, 이때 client의 처리가 지연될 경우 method 호출로 인해 blocking 되는 시간은 길어진다고 볼 수 있다.

다시 본론으로 돌아와서,
그렇다면 NIO 의 write(buffer) 를 호출했을때 어떠한 원리로 blocking 없이 즉시 return 값을 받을수 있을까?

이것을 이해하기 위해서는 OS의 Socket에 대한 이해가 필요하다.
더 자세히 말해 Socket Buffer에 대한 이해가 절대적으로 필요하다. 

결론부터 얘기하면,
Kernel Level의 모든 Socket Object는 자체적인 Read/Write Buffer를 가진다.
Socket Buffer로 넘겨진 data는 실질적으로 OS의 Kernel로 그 제어권이 넘어간 것이라 할 수 있다.
Application Level에서 Socket Buffer의 Data가 넘어가는 순간 실질적인 Data 전송의 스케쥴링은 Socket을 컨트롤 하는 OS에 달렸다고 볼수 있다. (물론 Application Level에서 Socket Buffer의 크기를 조절하여, 간접적인 Data 전송 스케쥴도 가능하긴 하다)
NIO의 핵심 메카니즘은 Socket Buffer에 단순히 Data를 Write하고 Read하는 역할 밖에는 하지 않는다.

단순히 메모리상의 특정 영역(Java Memory Area)에서 OS의 영역(Socket Buffer in Kernel)으로 데이터를 Write/Read하는 작업만을 하기때문에, 실질적으로 Blocking이 없다고 볼 수 있다.

예측할 수 없는 Data가 불규칙적으로 오고가는, Socket Buffer의 Data를 효과적으로 감시하기 위해서는, Polling이 아닌 Event기반의 감시자(Monitor Object)가 필요한데, 그 역할을 하는 것이 NIO의 Selector Object이다.

Selector에 대한 자세한 설명은 다음 강좌에 연재하겠다.

어찌되었건, NIO의 핵심은 구현 관점에서 NonBlocking Call과 Event기반의 처리라 볼 수 있다.
특징은 기존 IO에 비해 구현은 훨씬 복잡해지면서 Thread의 수를 최소화 할 수 있어서 대량접속에 대한 처리에 대해 쓰레드의 Context Switching 비용의 부담에서 벗어 날 수 있다.

물론 구현이 복잡해 지는 만큼, Design(설계)시 고려사항이 많아지며, 필수적이고 잘 알려진, Network, Thread,  I/IO 관련 Design Pattern에 대한 이해가 필수적이다.

-글 : 김영곤(gonni21c@gmail.com)
다음편에 계속..

/** 본 내용과 관련 하여 대학생 졸작, 프로젝트 관련 문의 메일은 사절입니다 **
** 그동안 문의메일만 수십통 왔습니다 **
** 20세기에나 먹혔을 법한 과제 아이템을 아직도 할려고 하는 분들, 부끄러운줄 아셔야 합니다 **/


Simple remote control application based on Java.

반나절 걸려 대충 완성한 웹기반의 원격접속 제어 프로그램입니다.
Windows 에서만 test 해봤는데 파일 경로 문제로 Linux에서는 약간의 수정이 필요할 듯 하네요..

자바에서는 응용프로그램의 UI Test 용으로 Robot 라는 class를 제공합니다.
Robot를 이용하여 화면영역, Keyboard, mouse 등을 api를 통해 제어할 수 있습니다..



위의 프로그램을 다운 받아서 아래와 같이 실행하면 현재 화면 웹서버가 가동됩니다.


default로 8181 포트에서 동작하지만 사용자가 임의로 포트를 설정할 수 도 있습니다.
위의 명령어는 8989 port에서 웹서버를 가동 시킵니다.

브라우저를 열고 주소창에 다음과 같이 입력합니다.



그러면 아래와 같은 현재 캡쳐된 바탕화면이 뜹니다.


이미지의 특정 부분을 클릭하면, 로컬 pc에서 마우스 포인터가 화면상 지정위치와 같은 위치에서 클릭이 일어납니다.
(내부적으로 이미지 클릭좌표는 자바스크립트로 추출, HTTP GET protocol spec으로 서버와 동작합니다.)
물론 대충 만들어서 화면의 갱신속도는 일반 사용프로그램과 비교시 매우 느린 편입니다.
또한 현재 지원 되는 이벤트는 마우스 클릭뿐입니다.

하지만 별도 프로그램 필요없이 별도의 브라우저만 열어서 집이나 회사의 PC를 원격제어 할 수 있다는 점에서 괜찮은 시도가 아닌가 생각됩니다..(^^흐뭇..)
브라우저가 내장된 PDA에서도 접속해서 쉽게 사용할 수 있으니까요..

향후 키입력이나, 드래그앤 드뢉, 분할 이미지 전송, Session 기반 사용자 AA, 시스템 트레이 등을 구현할 예정입니다.

현재의 구현상태로 주식HTS 프로그램 뛰워두고 입력이 많이 필요치 않은 정적인 작업으로 쓰기에 큰 부족함은 없을 듯 하네요.. 직장내에서 몰래 주식질 하는 묘미란..ㅎㅎ

** 참고로 웹서버 부분의 구현은 최범균님의 NIO기반 Simple http server 코드를 약간 수정하였습니다.
** 코드는 정리후 공개하도록 하겠습니다.
** 급하신 분들은 첨부 파일을 역컴파일 하셔도 되겠습니다..ㅋ

김영곤(gonni21c@gmail.com)

드라마나 영화로 영어공부 할 때
자막 파일에 두개의 언어가 포함된 경우,
영어공부를 하는 입장에서 하나로 묶어서 출력해서 보고 싶다는 생각이 드는건 저 뿐이 아니라는 생각이 드네요..ㅎ

다행히 smi 파일이 tag구조라..
제가 만들어둔 YGHtml parser를 이용해서 한시간만에 자막 추출 프로그램을 만들어 보았습니다..

해당프로그램 다운로드

이 프로그램을 실행시키기 위해선 Java Virtural Machine이 pc에 설치되어 있어야 합니다.
없으신 분들은 적절한 검색으로 JVM 환경을 pc에 setting 합니다.

파일을 다운받고 임의의 폴더에 저장합니다.
콘솔에서 명령어로           java -jar smi2view.jar          를 입력합니다.

아래와 같은 Simple한 화면이 뜨고, Open을 누르면 파일 선택창이 뜹니다.
변환을 원하는 smi 파일을 선택후..


Convert 버튼을 누르면 아래와 같이 영어와 한글이 적절히 Mix된 Text를 확인 할 수 있습니다.
Drag&Copy후 메모장이나 기타 워드 프로그램에 Paste해서 출력해서 사용하면 될 것 같네요..

아시는 분들은 알겠지만 프랜즈 자막입니다..^^


한시간 만에 급조된 프로그램이라, 퀄리티가 현저히 떨어지니 정말로, 꼭, 꼭 필요한 분들만 이 프로그램의 사용에 도전해 보도록 합시다..ㅎㅎ


김영곤(gonni21c@gamil.com)
아래의 문서를 번역 및 요약하였습니다.
http://www.cs.brown.edu/courses/cs161/papers/j-nio-ltr.pdf

------------------------------------------------------------

3. 채널과 버퍼(Channels and Buffers)

 3-1. 개요
 Channel과 Buffer는 NIO의 핵심 Object로 모든 I/O시에 사용된다.
 Channel은 original I/O와 유사하다.
 NIO의 모든 데이터는 어디든 Input, Output 될 수 있으며 모든 데이터는 Channel Object를 통해 이동된다.
 
 Buffer는 일반적으로 Container역할을 하는 Object이다.
 채널을 통해 이동되는 모든 데이터는 처음에 Buffer상에 로드된다, 즉 채널로 읽어들인 데이터는 Buffer로 읽을 수 있다.
 
 3-2. Buffer란 무엇인가?
 Buffer는 Write하거나 읽기위한 데이터가 저장되는 Object로 Original I/O에는 없는 NIO만의 특별한 개념이다
 NIO엣의 모든 data는 Buffer를 통해서만 Access하거나 사용할 수 있다
 Buffer는 기본적으로 배열이다.(A buffer is essentially an array)
 일반적으로 bytes 배열의 형태를 취하며, 다른 type의 배열로도 사용될 수 있다.
 물론 단순 배열이 아니라, 데이터의 처리를 위해 특별한 기능이 추가된 배열이라 보는것이 맞을 것이다.

 3-3. Buffer의 종류
  일반적으로 사용되는 Buffer는 ByteBuffer이다. 하지만 사용자는 용도에 따라서 아래의 Buffer를 사용할 수 있다.
  - ByteBuffer
  - CharBuffer
  - ShortBuffer
  - IntBuffer
  - LongBuffer
  - FloatBuffer
  - DoubleBuffer
  모든 Buffer는 Buffer Interface의 상속을 받는 형태이다.

 3-4. Channel이란 무엇인가?
  Channel은 데이터를 쓰거나 읽을수 있는 객체이다.
  Original I/O와 비교했을때 NIO는 Stream과 유사하다.
  앞서 언급했듯이 모든 데이터의 access는 Buffer object를 통해서만 가능하며, Channel에 직접 데이터를 쓰거나 읽을 수 없다.

 3-5. Channel의 종류
  Channel은 양방향(bi-directional)이라는 측면에서 stream과는 다르다.
  Stream이 inputstream이나 outputstream과 같이 단방향성 data의 이동이 있을수 있는 반면, Channel은 단일 object로 read와 write를 동시에 할 수 있다. 이것은 운영체제(특히 UNIX 계열)의 IO특성을 잘 반영한 모델이라 볼 수 있다.
 
 
 
아래의 문서를 번역 및 요약하였습니다.
http://www.cs.brown.edu/courses/cs161/papers/j-nio-ltr.pdf

-----------------------------------------------------------

2. Java I/O의 개념
 
2-1. Java IO와의 차이
 기존 IO는 Stream을 이용한 입출력 이었으나 NIO는 block I/O라는 방식이 사용되었다.

2-2. 왜 NIO가 좋은가?
 NIO는 Native Code의 사용없이도 고성능(속도의 측면이 강함)의 I/O를 사용할 수 있게한다.

2-3. Stream vs Blocks
 Original IO와 NIO의 가장 큰 차이는 '데이터가 어떻게 패키징(package)되고 전송(transmit)되느냐'이다.
 앞서 예기했듯 IO는 Stream을 사용하고 NIO는Block을 사용한다
 
 - Stream 방식
 Original IO input/output시에 데이터의 전송단위는 1byte이다. 물론 Buffer를 사용하지만 buffer를 쓰더라도 궁극적으로 하나의 바이트씩 produce와 consume이 발생한다. 이방식의 성능은 그리 좋지 못하다.
 
 - Block 방식
 block-oriented I/O system의 경우 데이터를 블록의 단위로 다룬다(deal with in blocks). block화된 데이터는 단 한번의 처리단위 시간 동안 일괄 처리된다. 블록으로 데이터를 처리하는것이 stream(byte 기반)으로 처리하는것 보다 훨씬 빠르다. 물론, 빠른만큼 개발자의 구현은 기존 IO보다 힘들어 진다.

+ Recent posts