다음과 같은 폼으로 헤더파일을 만들어 주면, #ifndef 전처리 문으로 인해

2번째 선언시에 _CLASS_ 상수가 정의 되어 있어서 중복선언을 막아준다. 

 

전방선언 하고 헤더를 소스파일 cpp에 넣어서 교차포함을 피하는 방법도

있기는 하지만,이것저것 오류가 나는 경우가 굉장히 많았다.

 

이 방법이 그냥 단순무식 하면서도 편하게 코딩 할 수 있는 방법인듯 하다.

 

// class 헤더의 선언

// "class.h"

 

 #ifndef _CLASS_

 

#define _CLASS_                   

#include "포함할 헤더파일"

[클래스 및 함수 선언]

 

#endif

    

 

 

 

 

 

 

 

 

 

 

 

 // class 소스파일

// "class.cpp"

 

#include "stdafx.h"

#include "class.h"

 

[클래스 및 함수 정의]

 

미리 컴파일 된 헤더파일을 사용하면 헤더에 헤더를 포함해 주지 않아도

stdafx.h에 선언된 클래스를 class.h에서 사용 할 수 있다.

 

단, 소스파일에서 stdafx.h를 반드시 추가시켜 줘야 미리 컴파일 된 헤더를 사용할 수 있다.

참고로 stdafx.h 이전에 포함 된 헤더파일은 모두 무시 되니, 이 점을 꼭 고려해야 한다.

 

Posted by 굿쟌
,

 C# 으로 외부 SDK를 DllImport해서 사용하는 도중에 아래와 같은 런타임 에러가 발생했다.

 

 

"CreateSceneInstance'에 대한 호출 결과 스택이 불안정하게 되었습니다. 관리되는 PInvoke 시그니처와 관리되지 않는 대상 시그니처가 일치하지 않기 때문인 것 같습니다. 호출 규칙 및 PInvoke 시그니처의 매개 변수와 관리되지 않는 대상 시그니처가 일치하는지 확인하십시오."

 

라는 런타임 에러인데... SDK가 외국 회사 SDK라서 물어보기도 애매한데 에러가 나서 당황했지만, SDK에 포함되어 있는 샘플 프로그램과 하나하나 비교해보니 샘플 프로그램은 닷넷 2.0으로, 내가 짜는 프로그램은 닷넷 4.0을 기준으로 설정되어 있는 것을 확인 했다.

 

그래서 내가 만든 프로젝트도 닷넷 2.0으로 설정을 바꾸니 이 에러 없이 정상 동작 한다.. ㅎㅎ

 

 

 

인터넷에서 검색을 해봐도 이 에러가 발생했을 때, 닷넷 프레임 워크 3.5이하 버전으로 대상 프레임 워크를 변경하면 된다는 답변이 있었다.. 그래도 뭔가 이렇게 끝내려고 하니 안 닦고 나온 기분이라 좀더 검색을 해봤는데, 이 문제의 원인은 DLL파일을 Import할 때 함수 호출규약 CallingConvention을 DLL파일과 동일하게 설정해 주지 않았기 때문이란다.

 

닷넷 4.0부터는 DllImport할 때 CallingConvention을 지정하지 않는 경우 무조건 __stdcall로 간주하고 함수를 가져오는데, 이 때문에 dll에 들어 있는 함수와 실제 부르려고 하는 함수간 호출규약이 다르면 이런 에러가 날 수 있다고 한다.

 

이제 함수를 부를 때 아래와 같이 실제 CallingConvenction을 명기해주면, 정상적으로 런타임 에러 없이 프로그램이 동작한다.

 

출처 : 다음 블로그 어딘가 impactlife라는 분이 남기신 댓글에서 이 정보를 얻었다. 2013년에 올리신 답변이 2015년에

         어떤 초보 개발자를 구했다. 감사하다는 말을 남긴다.

 

Posted by 굿쟌
,

postgresql 관련 서적이 다양하지 않아 wrox사에서 출판된 beginning database with postgresql을 알라딘에서 중고서적으로 구해 보고 있다. 상당히 오래 전의 postgresql을 대상으로 책이 씌여졌기 때문에 설치 부분이나 pgAdmin III같은 부분들이 반영되지 않았지만, sql문법이나 기본 데이터베이스 관련 지식은 변함 없기 때문에 이 책도 썩 나쁘지는 않다.

 

그런데, 테스트 데이터 베이스 샘플을 구축하기 위해 Wrox사에서 출판한 "beginning database with postgresql" (빨간 바탕에 아저씨 두명) 의 소스코드를 다운 받을려고 책에서 설명한대로 Wrox사 홈페이지에 들어가 보면, 황당하게도 해당 서적에 대한 서적검색도 안되고 소스코드도 찾아 볼 수가 없는데 이 문제 때문에 한참을 구글링을 했다.

 

결론부터 말하자면, 해당 서적에 대한 판권이 Apress사로 넘어가게 되면서 이 책의 소스코드도 apress사로 넘어가게 되었단다. ㅎㅎ..

 

http://www.apress.com/9781590594780

 

아래 싸이트에 들어가면 여전히 서적에서 제공하는 sql파일과 소스코드를 다운 받을 수 있다.

 

참고로 sql문서는 처음 그대로 돌리면 에러가 발생한다.

아마도 postgresql 버전이 변경되면서 읽을 수 있는 Date 포맷이 변경되어서 인지, sql파일의 date를 받아들이지 못하는 현상이 발생하기 때문이다..이 에러 같은 경우는 사용자가 날짜를 2014-12-12와 같은 포맷으로 변경해주면 책에서 소개하는 테이블 셋을 간단히 만들수 있다.

Posted by 굿쟌
,

최근에 다른 회사랑 일하면서 특정 파일을 다른 서버로 옮겨야 할 경우가 생겼다. 그런데 그 다른 서버가 사용하는 OS가 리눅스라서 윈도우 공유폴더를 못쓰는 바람에 OS와 상관없이 소켓만 열 수 있으면 파일 교환이 가능한 FTP에 대해서 공부하게 되었다.

 

처음에는 이 FTP규약을 배워서 직접 FTP서버를 구현할려고 햇는데 공부하다보니 구지 내가 바퀴를 발명해서 수레를 만들 필요는 없다는 것을 깨닳았다. 이미 너무 잘 구현된 FTP서버가 많이 있어서 설치하고 사용만 하면된다.

 

특히나 요번에는 FileZilla를 사용하려고 하는데, 윈도우 서비스 형태로 돌아가는 프로그램으로 구지 윈도우 로그인을 하지 않아도 돌아가는 점, 무엇보다도 무료 라이센스를 가진 프리웨어로 상업적인 용도로 사용해도 쇠고랑을 차지 않는다는 점이 마음에 들었다.

 

FileZilla 설치하고 설정하는 것은 뭐.. 인터넷에 그냥 한번만 검색해도 쭈루룩 나오는 내용이고 설명창에 설명이 잘되어 있어서 설정하기 쉬우니까 ( 관련사항에 대해서 알고 있다면..) 여기서는 넘어가기로 한다..

 

어찌됐든, 이 FIleZilla로 FTP를 한번 구성해 보았다.

FTP 서버의 구성은 아래와 같은데, 이 구성에 기인하여 425 에러가 발생하므로 잘 봐야한다.

 

 

 

간단히 설명하자면 FileZilla가 설치된 서버는 공유기를 통해 인터넷에 연결되어 있고 공유기는 공인 IP 125.7.198.200을 DDNS testSvr.iptime.org에 매칭해서 사용하고 있다. 그리고 공유기 설정을 통해 DMZ 기능을 사용하고 있는데, 이것은 예를 들어, 어떤 호스트에서 testSvr.iptime.org:6658 에 접속을 하게 되면 이 접속을 Port Forwarding하여 실제로는 내부망의 192.168.1.99 :6658에 접속이 되도록 하는 기능이다.

 

그리고 FTP서버에 접근하려고 하는 클라이언트는 공유기를 통해 인터넷에 접속이 가능한 상태이나, 클라이언트쪽 공유기에는 별다른 설정이 되어있지 않아 외부망에서 이 클라이언트 단의 포트에 직접적으로 접근 할 수는 없는 상태이다.

 

문제 원인을 파악하기 위해서는 FTP 작동방식 중에 passive, active mode. command connection, data connection에 대한 이해도. 필요하다. 아래 그림을 참조해보자..

 

 

 

위에 있는 그림은 Active-Connection 방식이고 아래 방식은 Passive Connection 방식이다.

 

FTP는 TCP/IP기반의 통신규약으로 총 2개의 TCP/IP 소켓 커넥션을 맺는다.

그 두개의 커넥션중 하나는 FTP서버와 클라이언트 단에 통신을 위한 Command Connection,

나머지 하나는 실제 파일이나 검색결과 전송을 위한 Data Connection이다.

 

전화로 다른 부서 사람에게 "누구누구 씨. 그 표좀 팩스로 보내주세요" 라고 전화했더니, 팩스로 표가 그려진 종이가 전달되었다면, 전화가 command Connection, 팩스가 Data Connection이라고 할 수 있겠다..

 

어찌 되었든 passive와 active 방식은 이런 Data Connection을 어떻게 맺는 가를 기준으로 구분된다. Passive와 Active라는 의미는 FTP 서버에 접속하는 Client 단을 기준으로 생각하면 되는데, 먼저 Active Connection  방식을 살펴보자면...

 

먼저 클라이언트가 21번 포트에 command connection을 맺을 수 있도록 FTP서버가 소켓을 열어놓고 기다리고 있으면, 클라이언트는 이 소켓에 연결요청을 하여 command Connection을 맺는다. 그리고 이 command connection을 이용하여 어떤 파일을 전송받기 위해 클라이언트는 새로운 포트 5151을 열고 PORT 명령을 통해 FTP서버단에 자기가 개설한 5151포트번호를 알려준다. 그러면 FTP 서버는 이 5151 포트에 접속하여 파일을 건내준다.

 

즉, active 방식은 클라이언트가 주체적으로 (active) 포트를 만들고 FPT서버가 이 포트로 들어오길 기다린다. (드루와 드루와)

 

반대로 passive 방식은 FTP서버 포트에 접속해서 command connection을 맺는 것 까지는 동일하나 데이터 전송을 위한 소켓을 수동적 (passsive)으로 FTP 서버가 열기를 기다렸다가 이 포트에 접속하여 데이터를 전송 받는다. (pasv명령을 통해 FTP서버가 클라이언트에게 서버가 개설한 포트 정보를 건내준다.)

 

아참.. 그러고보니 제일 중요한 문제가 뭔지 이야기를 안했군..

문제가 뭐였냐 하면.. FTP서버를 위에 그림처럼 구성하고, 클라이언트 PC에서 윈도우 cmd창에 ftp를 쳐서 FTP 루트 폴더에 뭐가 들었는지 dir명령어로 살펴 볼려고 하면, 아래와 같이 에러 메시지가 뜨고서는 data connection이 만들어지지 않았다고 하는 것이다.

 

이 말을 할려고 참 멀리도 돌아왔다.

뭐, 문제의 원인은 간단했다. 위에도 설명했지만 클라이언트가 active 모드로 FTP에 접속해서 data connection을 맺으려고 포트를 개설하고 그 정보를 FTP서버에 전송하면 서버는 이 포트로 드루와 드루와를 할 수 없다.

 

왜? FTP서버는 클라이언트가 개설한 포트 번호와 FTP클라이언트가 실행되고 있는 호스트의 IP정보를 가지고서는 인터넷상에 연결된 PC중에 어떤놈이 이 PC인지 알아낼 도리가 없다. 클라이언트 에서 제공하는 주소 정보는 단지 로컬 IP와 개설한 포트 정보이기 때문에...

 

즉 아래와 같이 PORT명령으로 전송되는 data용 소켓 정보는 인터넷 상에서 이 PC를 찾는데 아무 도움이 안된다. (멍청하게 로컬 IP 192.168.1.100와 포트 정보 2자리를 넘겨준다.)

 

 

따라서 FTP 서버는 data connection을 만들수 없어서 에러가 발생한다.

 

그럼 어떻게 해야 할까? 그렇다 Passive 모드로 data connection을 맺도록 하면 된다.

그래서 인터넷을 찾아보면

 

quote pasv를 치세요~

 

라는 답변을 볼 수 있는데...

 

 

무슨 고약한 심보인지는 모르겠는데, 결론부터 말하자면 윈도우 cmd창에서 실행 할 수 있는 ftp.exe에서는 Passive 모드가 지원이 안된다. -_-;

 

심지어 "여러분 cmd창에서 passive 모드가 안된다고 알고 있는데 사실 됨. 잘못된 사실을 알고 계신거임" 하는 어떤 서양인의 답변을 보기도 했는데 안된다. 안된다. 안된다. 이 답변 때문에 반나절을 더 구글링 했다.

 

그런 글들에서 시도 해보라고 하는건

 

quote pasv

 

를 명령행에 쳐보라는 건데 이 quote pasv 명령의 의미는 FTP규약에 정의되어 있는 명령 단위 조각을 직접 실행하겠다는 의미이고, pasv는 서버에서 포트하나 열고 포트정보를 전송한다는 의미이다. (ftp 콘솔에 쳐 넣는 명령어는 실제로 pasv나 post와 같은 단위 조각 명령어들의 집합이다.)

 

따라서 quote pasv를 치고 dir명령을 치면 다음과 같은 일이 벌어진다.

 

ftp>quote pasv

   서버에서 포트 열고 포트정보 전송

ftp>dir

   근데 뭐 어쩌라고 나는 active로 내가 포트 열고 전송할꺼야

   POST 포트정보 (POST는 서버로 클라이언트 단의 포트정보 전송하는 단위 명령)

   서버에서는 이 주소는 뭐지? 접속 안되네 에러 내자.

 

...

처음엔 나도 설마 어떤 인간이 "여러분 cmd창에서 passive 모드가 안된다고 알고 있는데 사실 됨. 잘못된 사실을 알고 계신거임" 이라는 글까지 올렸는데 이게 안될까 하고 계속 다른 곳을 검색해 봤는데, 이게 사실이다. -_-

 

위에 로그를 보자. quote pasv로 pasv 소켓은 열렸지만, 다음 dir 명령 (PORT + LIST)는 active 모드로 실행이 된다. ㅋㅋㅋㅋㅋㅋㅋㅋㅋ....ㅋㅋ.......ㅋ

 

하지만 내 반나절이 아까워서 애써 위 로그를 무시하고, 구글에서 검색 하다가 결국 이런 곳까지 찾고 나서야 비로소 나의 노력이 부질 없었구나 하고 인정 할 수 잇었다.

 

 

http://passive-ftp.com 이라고 ftp.exe와 동일한 방식으로 작동하되 passive 모드를 지원하는 콘솔을 파는 웹싸이트다.. 허허.. 무려 29.9$에 이 프로그램을 팔고 있다..

 

ftp.exe가 passive 모드가 됐으면 이런걸 개발해서 파는 싸이트가 있었을까? 허허.. 

 

결론적으로..어떤인간이 passive모드 지원한다고 달콤하게 틀린 정보를 써놨지만, 안된다. 즉, 이번 오류의 원인은 ftp 구성상 passive 모드를 사용해야 하는데 active mode를 사용했다는 것이고, 이걸 해결하려면 passive 모드를 사용하는 다른 프로그램을 사용해야 한다. ftp.exe는 passive모드를 지원하지 않는다.

Posted by 굿쟌
,

마일스톤의 XProtect는 Windows Service 형태인 XProtect Event Service를 가지고 있다. 이 서비스는 클래스 라이브러를 만들어 특정 폴더에 놓아 주면, 이 dll를 가져다가 추가 기능을 실행시켜 주는 플러그인 방식을 따르고 있다. 

 

이 플러그인이 실행되는 곳은 XProtect Evet Service라는 Windows Service이고 따라서 디버깅을 위해서는 이 Windows Service가 실행되는 프로세스에 Visual studio를 연결하여 디버깅을 하면된다.

 

하지만 보통 적용하고자 하는 서버에는 Visual studio가 없다보니 디버깅을 하기 어렵고 그렇다고 또 무거운 Visual studio를 깔아서 디버깅 하기는 귀찮아 간단한 로그를 파일로 남기는 기능을 추가 하여 어떤 방식으로 동작하는지 로그를 통해 검사하곤한다.

 

그런데 가끔은 이 Event Service가 실행되고, 플러그인도 적용 된 것이 확실한데 로그가 안남는 경우가 있다. 이것은 Windows Service가 실행되고 있는 사용자(?)와 관련된 문제인데, 만일 Windows Service가 파일을 만들고자 하는 경로에 대한 파일 쓰기 권한이 없는 경우 이런 문제가 발생한다.

 

(로그를 주었는데 왜 먹지를 못하니..)

 

이런 경우, 간단하게 해당 폴더의 속성에서 Windows Servicer가 가지고 있는 계정을 쓰기에 대한 권한을 가진 사용자로 추가 시켜주면 된다.

 

 

 

Posted by 굿쟌
,