C# SendMessage IPC :: iopeni - Think of C#



뜬금이 없다.. 랄까? 갑자기 웬 API??랄까? 이젠 쓸 일도 없는 녀석을 왜??? 랄까? 암튼 좀 그렇다.

작금의 상황은 이런 SendMessage보다... 더 좋은 모델들이 많이 있다. 굳이 SendMessage를 쓰는 것은... ㅜ,.ㅜ;; 좀 절망 이라고 할까.... 물론 가볍고 빠르다는 장점으로 인해 이 SendMessage를 사용하는 분들도 많이 있다.


어찌되었든.. 이 SendMessage라는 녀석을 이해 하려고 하면 기본 지식 부터 정리 하는 것이 좋을 듯 하다. 


옛날 DOS 시절을 생각 하면 그 땐 너무 행복한 시절이었다. 이런 SendMessage같은 녀석들이 없었으니 말이다. 하긴 그땐 인터럽트 때문에 어려웠다.


우리가 사용하고 있는 윈도우은 멀티 태스킹 환경이라는 것은 뭐 설명하지 않아도 다들 알고 있는 내용일 것이다. 모르는 사람들을 위한 팁으로 멀티 태스킹 환경이라는 것은 동시에 여러개의 프로그램을 실행 할 수 있는 환경 이라는 소리다. 


여러개의 프로그램이 동시에 실행 된다면 각각의 프로그램은 메모리 영역을 할당 받게 되는데 이는 보호되고 있어서 해당 프로그램 이외에 다른 프로그램은 메모리 영역에 접근 할 수 없다. (옛날 윈도우 3.1 또는 윈도우 95 시절에 윈도우가 무수히 블루 스크린을 띄웠는데 이게 이 메모리 영역의 침범으로 인한 오류로 컴퓨터를 재부팅 해야 하는 시절도 있었다. 지금은 거의 없어진 증상이지만...)


이렇게 여러개의 프로그램이 실행되어 있는 상황에서 각각의 프로그램들이 특정 데이타를 공유 할 필요성이 대두 되었고 여러개의 프로그램이 데이타를 공유 할 수 있는 방법을 통칭 IPC(Inter-process Communication)라고 한다.


그러하기에 IPC라는 것은 여러가지 방법을 가지게 될 것이다. 프로세서간 정보만 공유 하면 되는 것이기에 소켓 또는 파일 또는 레지스트리등을 사용할 수도 있을 것이다. 정말 많은 방법이 있을 것이므로 우리는 이 많은 방법들 중에 어떤 방법을 선택 해야 하며, 이때 고려 해야 할 요소들이 있는데 대충 다음과 같다.


1. Network을 고려 해야 하는가?

   1-1 통신 하려고 하는 대상의 OS가 같은가?

   1-2 통신 하려고 하는 대상의 OS종류는 한가지 인가?

2. 통신의 속도가 중요하게 고려 되어야 하는가?

3. 반복적 정보 공유 인가?

4. 통신하고자 하는 정보의 사이즈는 큰가? 작은가?


여러가지 고려 요소를 생각 하여 방법이 정해 지면 추 후 방법을 바꾸고자 할 경우 무척 어려운 상황이 발생 되므로 처음 선정 할때 부터 주의를 요해야 한다.


그럼 우리가 사용하는 Windows 환경에서의 메시지 전송 방법엔 어떤 방법들이 있는지 보자. 


1. 메지시 : 사용자 정의 메시지로 정보 전달 한다.

2. 클립보드 : 중앙 저장소를 이용한 대량의 정보 교환

3. DDE : Do Data Exchange를 이용한 지속적 정보 교환

4. 파일 맵핑 : 파일 맵핑을 이용한 메모리 공유

5. 메일 슬롯 : 메일 슬롯 사용

6. 파이프 : 파이프 사용

7. 윈속 : 소켓 사용

8. RPC, RMI : Remote Procedure Call, Remote Method Innovation 을 이용한 방법

9. COM, DCOM, COM+, WebService, WCF 등을 이용한 방법.


뭐 이 포스트에서 이야기 되지 않은 다른 방법들도 많을 것이다. 사실 IPC라는 것이 데이타를 공유만 하면 되는 것이기에 그 목적에만 맞으면 IPC라고 할 수 있을 것이다.


오늘의 포스팅 목적은 사실 위 많은 IPC 중에 메시지에 해당하는 내용을 살펴 볼 것이다.


메시지는 사실 정보를 교환 할 수 있는 방법중에 가장 간단하고 가장 가볍고 가장 빠른 방법이다. 이 메시지를 이용하기 위하여 우리는 OS에 대한 어느 정도 기초적 지식을 습득해야 한다. 


가장 처음 이해 해야 되는 내용은 Message Queue 이다.


일단 힘들게 그림 그린 메시지의 흐름도 부터 확인 하자.




메시지 큐는 여러분이 키보드를 이용하여 입력 하거나 마우스를 가지고 아이콘을 클릭 하거나 하는 일련의 동작들이 담기게 되는 일종의 자료 구조 이다. 이 메시지 큐는 무한 루프를 돌면서 사용자의 입력을 기다리게 된다.


메시지루프의 형태는 다음과 같다.



GetMessage 함수는 메시지 큐로 부터 메시지를 가지고 온다. DispatchMessage는 WndProc 함수가 메시지 구조체에 들어 있는 윈도우 핸들을 이용할 수 있도록 메시지 데이터를 WndProc함수로 보낸다. 결국 우리는 메시지를 가로채기 위해 WndProc함수를 Override 하여 재정의 사용한다. 


TranslateMessage()는 DispatchMessage 전 키보드 또는 입력 메시지를 전 처리 할 수 있다. 이 함수는 PreProcessMessage로 보낸다. PreProcessMessage를 Override 하여 재정의 사용한다. 매개 변수에는  WM_KEYDOWM, WM_SYSKEYDOWN, WM_CHAR 및 WM_SYSCHAR 값을 사용할 수 있다. 


다음 그림을 통해 메시지 루프를 조금 더 자세히 들여다 보자. 


이 그림에서 주의 깊게 보아야 할 항목은 PostMessage는 시스템 메시지 큐에 담긴다는 것이다. 이 때문에 SendMessage와 PostMessage가 몇가지 다른 특성을 보이게 된다. 


첫번째 차이점은 PortMessage는 비 동기 이다. (메시지 큐로부터의 응답을 기다리지 않는다.) SendMessage는 동기 이다. (메시지 큐로부터의 응답을 기다린다.)


이쯤 공부 했으니.. 이제 샘플을 보자. 


위의 샘플은 WM_COPYDATA 메시지를 이용하였다 이것은 메시지 전송을 할 경우 간단한 문자 메시지를 교환 하더라도 아주 복잡한 방법이 동원 되어야 하기 때문에... (이 예제는 다음 사이트에서 볼 수 있다. http://www.pinvoke.net/default.aspx/user32/SendMessage.html ) 윈도우에 추가된 메시지 이다.


두번째 차이점이 여기에 있다. PostMessage는 시스템 메시지큐에 들어가기 때문에 이 WM_COPYDATA 메시지를 사용할 수 없다.


추가적인 사항으로 SendMessage를 이용한 Broad-Casting 이다. 말 그대로 브로드 캐스팅이면... 여러개의 프로그램에 동시에 메시지를 날릴 때 이용 하는 방법 이란 것을 알 수 있을 것이다. 



위 예제 에서 주의 깊게 보아야 할 항목은 RegisterWindowMessage 이다. MSDN - https://msdn.microsoft.com/ko-kr/library/vstudio/ms644947(v=vs.110).aspx에서 확인 할 수 있다.


참고로 약간의 설명을 하자면 다음과 같다. RegisterWindowMessage는 응용 프로그램에서 정의한 메시지를 등록하고 그 메시지가 중복되지 않도록 해서 이미 등록된 다른 메시지와 충돌이 일어나지 않도록 한다. 


두 가지 별개의 프로그램에서 메시지를 주고 받으면서 의사 교환을 할 때 일반적인 (WM_USER, WM_USER + 1 등) 메시지 번호를 사용하는 것은 안전하지 않다. 


갑자기 정리 하게된 내용이 너무 많다... 아 배고파~~~~~ 


Posted by 프로그래머란 카페인을 코드로 변환하는 기계다
,