Win32 API나 MFC와 마찬가지로 .NET Framework에서도 비동기 방식으로 소켓 통신을 하기 위한 방법을 제공한다. 그 방법은 MSDN 내에 비동기 서버 소켓 사용과 비동기 클라이언트 소켓 사용에 관한 아티클에 상세하게 소개 되어 있다.

이 글에서 소개하고자 하는 AsyncSocketClient와 AsyncSocketServer는 .NET Framework에서 제공하는 비동기 소켓을 좀 더 사용하기 쉽게 만든 일종의 Wrapper 라이브러리라고 할 수 있다. 물론, .NET Framework 자체에서 소켓을 좀 더 고수준화한 TcpClient와 TcpListener란 클래스도 제공하지만; 제약이 많다;

물론, Socket에서 제공하는 모든 부분까지 구현한 것은 아니고; Connect, Close, Send, Receive, Accept 정도만 제공하는 것으로 소스를 공개함으로써 누구나 수정, 재배포가 가능하도록 하였다(다시 말해서; 자기가 필요한 부분은 추가로 구현해서 써도 상관없다.); 하지만, 가급적이면 저의 흔적을 말살하지 않기를..ㅠㅠ;

아, 그리고 이 라이브러리는 100% TCP 기반으로 구현되어 있다; UDP는 제공하지 않는다;

이 라이브러리가 .NET Framework에서 제공하는 소켓 클래스보다 편리한 부분은 소켓에서 발생하는 Connect, Close, Accept, Error, Send, Receive 등을 이벤트화 하였기에; 폼이나 다른 클래스에서 소켓을 핸들링 하는 것이 쉬워졌다; 다시 말해서, 폼이나 클래스에서 이벤트 핸들러만 재정의하면 소켓 이벤트를 처리할 수 있다;

사용자 삽입 이미지

위 그림에서 알 수 있듯이, 본 라이브러리는 기본적으로 AsyncSocketClass란 하나의 부모 클래스와 클라이언트 소켓 파트를 구현한 AsyncSocketClient, 서버 소켓 파트를 구현한 AsyncSocketServer로 이루어져 있다;

자식 클래스들을 좀 더 자세히 살펴보면 다음과 같다;

사용자 삽입 이미지
AsyncSocketClient는 public method로 Connect, Close, Send, Receive가 지원된다; 하지만; Receive는 특수한 경우를 제외하고는 개발자가 직접 호출할 필요는 없다; (이 부분은 나중에 좀 더 자세하게 설명하도록 한다..) 왜냐하면; 기본적으로 연결이 성공하면 데이터 수신을 위해 자동적으로 수신 대기 상태가 되기 때문이다;

만약, 데이터 수신을 성공하면, OnReceive 이벤트를 재정의 하여, 이 이벤트 핸들러에서 수신한 데이터를 지지고 볶고 하면 된다.OnConnect, OnClose, OnSend 모두 같다;

아래는 AsyncSocketClient를 이용해 구현한 샘플 프로그램의 코드 일부(이벤트 재정의 부분)이다.
사용자 삽입 이미지

여기서 중요한 것은 AsyncSocketClient 생성자의 인자로 숫자 0이 들어갔는데; 이는 다수의 AsyncSocketClient 인스턴스들을 생성을 가졍했을 때, 각각을 식별하기 위한 ID라고 할 수 있다.

그리고 그 아래 OnConnect 이벤트 핸들러가 있는데;
인자로 object sender와 AsyncSocketConnectionEventArgs e가 들어간다.

sender는 AsyncSocketClient로 캐스팅해서 쓰면, 이벤트가 발생한 소켓 클라이언트 자신이다;
(AsyncSocketClient worker = (AsyncSocketClient)sender;)

AsyncSocketConnectionEventArgs는 이벤트가 발생한 소켓 클라이언트의 ID 등을 포함하고 있다;

사용자 삽입 이미지

OnReceive를 살펴보면 넘어오는 Event 인자가 소켓의 ID, 수신한 바이트 수(ReceivedBytes), 수신한 데이터(ReceivedData)가 포함되어 있음을 알 수 있다. 참고로 위의 코드는 수신한 데이터가 byte[] 타입이기 때문에, string으로 캐스팅하기 위한 Encoding.... 코드가 포함되어 있다.

그 다음 AsyncSocketServer로 넘어가면;

AsyncSocketServer는 public method로 Listen, Stop이 지원된다; 만약 Client의 접근이 Accept 되면, OnAccept 이벤트가 발생하므로, OnAccept 이벤트를 재정의 하여, Client를 처리하면 된다;

사용자 삽입 이미지

AsyncSocketServer에서 가장 중요한 부분은 클라이언트 소켓의 접속을 처리하는 OnAccept 부분이다.

OnAccept에서 넘어오는 Event 인자는 접속이 허가된 소켓(e.Worker) 인스턴스가 포함되어 있다;

따라서, OnAccept 이벤트 핸들러에서는 AsyncSocketClient를 그대로 이용하기 위해, 이벤트 핸들러 내의
첫 줄과 같은 코드가 필요하다; 또한; 클라이언트의 ID가 중복되지 않도록, 새로운 ID도 부여한다.

그리고 그 다음이 앞서 언급한 AsyncSocketClient가 Receive를 호출해야할 특수한 상황이다;
구현 방법에 따라서; 이 부분은 Accept 코드 내에서 처리할 수도 있었지만; 어짜피 개발자가 이벤트 핸들러 연결도 필요하기 때문에; 그냥 이렇게 구현하였다.

끝으로 새로 생성한 클라이언트 소켓들을 미리 정의한 이벤트 핸들러와 연결하는 코드들이 나오고;
끝으로 클라이언트 리스트에 Add한다. (다수의 클라이언트 접속 가능 예를 들기 위해서 이렇게 했음);

좀 더 편리한 개발을 위해서는; MSDN 수준의 Class Specification을 쓰고 싶었지만; 시간 및 기타 여건이 허락되지 않는 관계로 이만 줄임!

대신에 라이브러리 및 예제 소스를 공개하니; 이를 이용하면 되지 않을까... 무책임하게 생각해봅니다;

다운로드: http://www.nohungry.net/Data/AsyncSocket.zip
크리에이티브 커먼즈 라이센스
Creative Commons License

Trackback

Trackback Address :: http://www.nohungry.net/tt1/trackback/160

Comments

  1. 카논 2010/03/09 10:52

    좋은 정보 감사합니다.
    서버/클라에 대한 구현 팁을 좀더 알려주셧으면 하는..
    초보자에게 정말 많은 도움이 될거 같습니다.

    perm. |  mod/del. |  reply.
    • 노헝그리 2010/03/09 17:33

      저도 아는 것이 없지만; 매우 기초적인 내용으로 조금씩 쓰려고 생각 중이었습니다;

      날개발자지만; 명색이 직딩이다보니~ 잘 안되지만; 틈틈이 써보도록 하겠습니다~^^;

What's on your mind?

댓글 입력 폼
[로그인][오픈아이디란?]

[C#] Auto FTP Uploader

2010/03/03 15:29
사용자 삽입 이미지

 회사에서 맡은 프로젝트 중... 실시간으로 생성되는 데이터를 원격의 FTP 서버에 전송해야할 일이 생겼다.

 상용 FTP 클라이언트 프로그램에서 일종의 매크로 기능을 사용하면 이와 같은 기능을 대신할 수 있지만; 상용 프로그램을 쓰는 것도 부담 스럽고; 내가 원하는대로 커스터마이징 하는 것이 불가능해서 그냥 만들었다.

Auto FTP Uploader의 로직은 매우 심플하다; 특정 Source Folder를 설정하고, 업로드 할 FTP 주소와 계정 정보를 입력해둔 다. Auto FTP Uploader는 Source Folder의 Rename 이벤트를 감지하여, 이벤트가 발생하면, 원격 FTP 주소에 업로드 한다.

 Source Folder의 Create 이벤트를 감지할 경우, 파일 작성이 완료되는 시점을 알 수 없으므로, 데이터를 생성하는 부분에서 파일이 작성되는 시간 동안에는 확장자를 TMP로 만들고, 파일 작성이 완료되면 확장자를 DAT로 바꾸게 하였기에 Rename 이벤트를 감지하도록 했다. (Temp Folder와 Complete 폴더는 원격 FTP 서버의 요구 사항에 의해 만든 것으로 파일이 작성되면 원격 FTP 서버에 동일한 파일명의 Dummy File을 업로드 한다.)

 프로그램 자체는 뭐 특별한 기능은 없지만; .NET Framework를 이용하면 간단한 FTP를 구현하는 것은 일도 아니라는 생각이 든다. 또, C#을 처음 접하는 이들에게는 C#을 이해하는데 도움이 되지 않을까 생각한다.

 이 프로그램에 사용된 주요 프로그래밍 테크닉은 다음과 같다.

 1. 파일 입/출력
 2. FtpWebRequest 클래스의 사용법
 3. 간단한 Thread의 사용 예
 4. ManualResetEvent, Monitor를 이용한 동기화 기법
 5. 델리게이트(delegate)를 이용한 클래스 또는 폼 간의 이벤트 발생 및 전달

 코멘트가 상세히 포함되어 있지는 않지만; 복잡한 로직은 거의 없고, 가급적 모듈별로 분리하도록 노력하였기 때문에 크게 어려움은 없지 않을까 생각해본다...;

사용자 삽입 이미지

소스 다운로드 : http://www.nohungry.net/Data/FTPUploader.zip

수정 및 재배포 자유, 영리적 목적의 사용도 자유! 단, 출처만 밝혀주세요;
크리에이티브 커먼즈 라이센스
Creative Commons License

Trackback

Trackback Address :: http://www.nohungry.net/tt1/trackback/159

Comments

What's on your mind?

댓글 입력 폼
[로그인][오픈아이디란?]

 D/B에서 데이터를 가져오는 경우, 데이터를 저장 또는 변경하는 경우에 그 데이터가 많다면... 일반적인 동기 방식으로 처리할 경우, 프로그램에서는 매우 난감한 상황이 발생할 수 있다.

 데이터를 처리하기 전까지 소위 프로그램이 멍 때리는 상황... 다른 모듈의 동작까지 블럭(Block)이 되고, UI 마저 "응답 없음"이란 상태에 놓일 수 있다.

 이에 대한 해결책이 바로 비동기 방식으로 D/B를 처리하는 것이다.

 C# 아니 엄밀히 말하면 .NET에서는 데이터베이스 뿐만아니라 네트워크 등 다양한 경우에 대한 비동기 메소드(Method) 등을 지원한다. 데이터베이스 관련해서는 크게 ExecuteReader와 ExecuteNonQuery 동작에 대한 비동기 함수들을 지원한다. 두 함수의 차이는 SELECT와 같은 Transaction-SQL을 처리할 수 있는 함수라는 것과 UPDATE, INSERT, DELETE와 같은 Non-Transaction-SQL을 처리할 수 있는 함수라는 것이다.

 만약 앞서 설명한 함수들을 이용할 경우, 이 함수가 결과를 반환할 때 까지 나머지 모듈들은 블럭이 된다. 반면에, 이에 대한 비동기 함수들인 BeginExecuteReader-EndExecuteReader, BeginExecuteNonQuery-EndExecuteNonQuery를 사용하면 블럭이 되는 현상을 방지할 수 있다.

 함수의 간단한 사용 방법은 다음과 같다.

사용자 삽입 이미지

 모든 비동기 함수는 반드시 Begin~으로 시작하는 함수와 End~로 시작하는 함수가 쌍을 이루어야 된다.

간단한 설명을 위해 이 함수에 D/B Connection과 Close까지 포함되고, 데이터를 읽어오기 위한 코드도 포함되어 있지만.. 엄밀히 말하면 이들도 각각 분리되어야 한다.

 특히, D/B로 부터 읽어온 데이터를 처리하는 부분(Grid에 데이터를 넣든지, 그래프로 그리던지)은 별도의 함수로 구현해서 Thread로 처리하는 것이 바람직하다. 왜냐하면, 프로그램이 멍 때릴 정도로 읽어와야할 데이터가 많다면.. 필히 이 데이터를 처리하는 부분을 단순히 처리할 경우에도 단순히 문제가 될 수 있다.
크리에이티브 커먼즈 라이센스
Creative Commons License

Trackback

Trackback Address :: http://www.nohungry.net/tt1/trackback/148

Comments

What's on your mind?

댓글 입력 폼
[로그인][오픈아이디란?]

사용자 삽입 이미지

Visual Studio 2005로 작성한 멀쩡히 돌아가던 내 소스를 새로 설치한 PC에 옮겨서 빌드를 했더니, 저런 어처구니 없는 오류가 나왔다.

근데, 아무리 찾아봐도... 저런 파일은 없었다; 아.. 뭐지? Visual Studio 2005가 잘못 깔렸나?

구글을 찾아봐도 안 나온다; 범인은 바로... 아이콘(ico) 파일 때문이었다;

해결 방법은... 아래 그림과 같이 솔루션 탐색기에서 해당 프로젝트 명에서 우클릭한 후, 속성을 선택한다.

사용자 삽입 이미지

그리고 리소스에서 아이콘을 원래 있던 아이콘에서 기본 아이콘으로 빌드하니... 오류가 생기지 않았다.
사용자 삽입 이미지

문제가 발생한 원인은 이게 끝!

근데 도무지... 이게 왜! 생기는지는 나도 알 수 없다. 아이콘 파일도 해당 경로에 정확히 있는데 말이다;

혹시 아이콘이 잘못 만들어졌다면... 내 PC에서도 안되어야 하는데; 참;
크리에이티브 커먼즈 라이센스
Creative Commons License

Trackback

Trackback Address :: http://www.nohungry.net/tt1/trackback/144

Comments

What's on your mind?

댓글 입력 폼
[로그인][오픈아이디란?]

최근에 강좌란에 이와 관련한 내용이 없는 것 같아, 간단한 지식이지만 올립니다.

설치 및 배포 프로젝트는 간단히 말해서 Install Shields나 Install Factory같이 사용자를 위한 셋업 프로그램을 만들수 있도록 제공되는 기능입니다.

프로그래머는 이 설치 및 배포 프로젝트를 이용해 사용자가 보다 편리하게 프로그램을 설치할 수 있도록 도움을 줄 수 있습니다.

그럼, 설치 및 배포 프로젝트에 대해서 보다 상세하게 알아보도록 하겠습니다.

아래 그림과 같이 배포를 목적으로한 어떤 프로젝트가 있다고 가정해보겠습니다. 

우리는 이 프로젝트가 속한 솔루션에 설치 및 배포 프로젝트를 추가합니다.

프로젝트 추가에 성공하면, 우리는 솔루션 탐색기에 다음과 같이 설치 프로젝트가 추가된 것을 확인할 수 있습니다.

그럼 이제 이 설치 프로젝트에 우리가 배포하고자 하는 프로젝트를 추가합니다. 추가하는 방법은 다음과 같습니다.

설치 프로젝트(위에서는 Setup이란 이름의 프로젝트)를 선택한 상태에서 마우스 우클릭을 한 다음, 메뉴가 나타나면, 추가 - 프로젝트 출력을 선택합니다. 

다음과 같은 항목이 나타나면, 우리는 우리가 추가하고자 하는 프로젝트를 선택하고, 확인을 누릅니다.

창이 닫히고 나면, 설치 프로젝트 아래, 발견된 종속성에는 Microsoft.NET Framework이란 항목이 추가가 되어 있고, 프로젝트 아래에는 HelloWorld의 기본 출력(활성)이란 항목이 새로이 추가된 것을 확인할 수 있습니다.

이 때, 발견된 종속성에는 만약 배포하고자 하는 프로젝트에 .NET Framework에서 제공하는 참조(DLL 등) 이외에 추가적인 참조가 존재한다면, 자동적으로 포함이 됩니다. 하지만, 가끔 추가가 되지 않는 경우도 있는데, 이 때는 직접적으로 추가를 해야합니다. 

그럼 이제 속성 창을 살펴보도록 하겠습니다. 속성창의 항목들은 기본적으로 속성 이름을 통해 그 역할을 직관적으로 이해할 수 있습니다.

이 속성들 중에서 매우 중요한 2가지 항목을 꼽자면, 바로 RemovePreviousVersionVersion이 아닐까 싶습니다.

RemovePreviousVersion은 새로운 배포 버전을 설치할 때, 이전 버전의 프로그램을 제거하고 설치할 것인지를 설정하는 속성입니다. 이 때, 버전은 프로그램의 버전이 아닌, 셋업 프로그램의 버전을 보고 판단합니다.

따라서, 이전 셋업 프로그램의 Version이 1.0.0이었다면, 새로 배포할 때는 이 버전을 업그레이드 해줘야 합니다.

Version 항목의 값을 수정하면, 다음과 같은 창이 나타나는데, "예"를 선택합니다.

만약, "예"를 선택하지 않은 경우, 이전 버전을 제거하지 못하는 경우가 발생합니다.

 

그럼 이제, 파일 시스템 항목에 대해서 살펴보겠습니다.

일 시스템 항목은 우리가 배포하고자 하는 항목을을 사용자 시스템의 어느 곳에 위치시킬 것인지를 결정하는 속성이라 이해하면 됩니다.

예를 들어, 프로그램의 실행 파일은 응용 프로그램 폴더에 두고, 실행 파일의 바로 가기는 사용자 바탕화면에, 그리고, 도움말 등은 사용자 프로그램 메뉴에 추가한다는 식으로 말입니다.

설치 프로젝트에 우리가 배포하고자하는 프로젝트를 추가하면, 디폴트 값으로 응용 프로그램 폴더에 실행 파일이 추가됩니다.

만약, 우리가 이 실행 파일의 바로가기를 바탕화면에 추가하고 싶다면?

그림에서 HelloWorld의 기본 출력(활성)에서 마우스 우클릭을 한 다음, 바로 가기 추가를 선택하여 바로 가기를 만듭니다. 그리고 이 바로가기를 드래그 & 드롭을 이용해 사용자 바탕화면으로 이동시키면 됩니다.

이 때, 주의해야할 사항은 기본적으로 바로가기의 이름은 HelloWorld의 기본 출력(활성)의 바로가기란 다소 어색한 이름으로 만들어집니다. 만약, 이 상태로 설치 프로그램을 만들어, 설치하면 바탕화면에 이 어색한 이름 그대로 만들어지게 되는 것이죠.

그러므로 HelloWorld같이 바로가기의 이름을 수정하여 배포하는 것이 덜 어색하겠죠..^^.

아, 그리고 한가지 더.. 기본적으로 바로가기의 속성창에 보면 Icon 속성에 '없음'이라고 되어있습니다.

이 상태로 배포하면 당연 바탕화면의 바로 가기는 아무런 아이콘이 없는.. (엄밀히 말하면 도스 창 형태의 아이콘을..) 상태로 사용자 바탕화면에 추가되게 됩니다. 그다지 보기 좋지 않겠죠..^^

여기까지 하셨다면, 가장 기본적인 인스톨 프로그램을 완성하실 수 있게된 것입니다.

하지만, 아직 부족한 점이 몇 몇 보입니다. 예를 들어, 고객의 정보를 입력 받는 창을 만들고 싶다던지, 프로그램이 설치되고 나면, 라이센스(EULA)에 관한 텍스트 파일을 보여준다던지, 회사의 홈페이지가 나타나게 하고 싶은데 말입니다.

이와 같은 내용은 다음 강좌에서 설명할 수 있도록 하겠습니다. 아울러, 이 설치 프로젝트를 보다 커스터마이징할 수 있는 Installer 클래스에 대해서도 알아보도록 하겠습니다.

- 이상 데브피아 강좌란에 내가 썼던 글-ㅁ-;

크리에이티브 커먼즈 라이센스
Creative Commons License

Trackback

Trackback Address :: http://www.nohungry.net/tt1/trackback/106

  1. Subject : Visual Studio .NET 2005에서 설치용 프로그램 만들기

    Tracked from 건축환경연구실 Building Environment Laboratory 2010/03/10 09:33 del.

    프로그램을 개발한 다음, 사용자가 설치해서 사용할 수 있도록 하기 위해서는 '설치용 프로그램'(일명 setup 프로그램)을 만들어야 한다.Visual Studio .NET 2005에서는 솔루션에 '설치 프로젝트'를 추

Comments

  1. 하늘바다 2007/10/12 13:01

    흠.... 좋은정보~ㅎㅎ

    perm. |  mod/del. |  reply.
  2. acaran 2007/10/17 21:52

    오...-_- 요샌 데브피아에 강좌도 쓰는가?

    어느덧 절대 고수의 경지에 올랐구려~ ㅋ

    perm. |  mod/del. |  reply.
  3. kwangho 2009/03/04 21:23

    시작화면을 로고 띄울때 쓰려고 하는데
    인스톨쉘처럼 멋지게 나오게는 안되는건가요:??

    perm. |  mod/del. |  reply.
    • 노헝그리 2009/03/04 22:49

      음~ 아무래도 Install Project를 만드는 독립적인 툴인 Install Shield에 비해서 많이 부족한 것이 사실입니다;

What's on your mind?

댓글 입력 폼
[로그인][오픈아이디란?]

저도 특정 테이블에서 데이터를 가져오는 것이 아니라, 데이터를 재가공한 후, 크리스탈 레포트로 출력하는 형식이었는데,

다음과 같이 진행하였습니다..^^

우선 님이 크리스탈 레포트에 출력하고자 하는 형식의 데이터셋 파일(*.xsd)을 만드세요. 그러면 원래 마법사가 뜨면서 Connection String도 넣어라고 하고, 나오죠? 거기서 취소를 하고 도구상자에서 DataTable을 하나 끌어와서 만듭니다.

그 DataTable을 임의로 MyTable이라고 하기로 하죠.
그리고 ID랑 Name이란 2개의 칼럼을 만들었다고 가정하겠습니다..^^ 그리고 저장을 합니다.

그럼 이 xsd 파일은 크리스탈 리포트 형식(*.rpt) 파일의 기반이 됩니다.
그러면, CrystalReportSource와 CrystalReportViewer를 각각 생성하고, cs와 cv라고 명명했다고 하죠.

그럼 rpt파일은 xsd파일을 이용해서 생성된 것이고, cs는 이 rpt파일을 기반으로 생성됩니다. 이해가 되시나요?^^;;

cv의 보고서 소스는 바로 cs를 선택하시면 되겠죠.. 그럼.. 크리스털리포트뷰어에 ID와 Name으로 구성된 페이지가 나올겁니다..

그럼 이제 내용을 채워야겠죠.. 내용을 채우는 순서는 다음과 같습니다.

1. DataTable 타입의 객체를 CrystalReportSource에 바인딩시킨다.
2. CrystalReportViewer의 ReportSource에 CrystalReportSource를 할당한다.
3. 그리고 CrystralReportViewer를 Refresh한다.

그럼 먼저 DataTable 객체를 선언하고, 정의해보면..

DataTable dataSrc = new DataTable();

dataSrc.Columns.Add("ID");
dataSrc.Columns.Add("Name");

dataSrc.Rows.Add(new string[]{"23", "Michael Jordan"});
dataSrc.Rows.Add(new string[]{"10", "Pele"});

이렇게 하시면 됩니다..^^

그럼 이제 이 객체를 CrystalReportSource에 바인딩시켜야겠죠.
아까 CrystalReportSource를 생성하고, 이름을 cs로 했다고 했으니...

cs.ReportDocument.SetDataSource(dataSrc);
cs.DataBind();

하면 됩니다.. 그리고 CrystalReportViewer의 ReportSource에 cs를 할당하고, 보고서를 새로 그려주면 됩니다.

cv.ReportSource = cs;
cv.RefreshReport();

-끝-

너무 길게 그리고.. 두서없이 쓴 것 같네요..^^; 그럼 즐프하세요.

-------------------------------------------------------------------------------------------
내가 예전에 데브피아에 쓴 답글..
근데, 시간이 흘러.. 갑자기 나도 써야하니.. 기억이 안나서 찾는다고 고생했다..
그래서 내 블로그에 남겨둠..-_- 이 한심한 기억력이란.. 쯧-ㅁ-

크리에이티브 커먼즈 라이센스
Creative Commons License

Trackback

Trackback Address :: http://www.nohungry.net/tt1/trackback/104

Comments

  1. 2007/10/04 09:05

    예전에 크리스탈리포트 한다고 자료찾고 공부했던 기억이..ㅋ

    perm. |  mod/del. |  reply.
    • NOhungry 2007/10/04 15:43

      크리스탈리포트 좀 갈쳐주세요-ㅁ-

      아.. 갑자기 이걸 해야되는 상황인데.. DB에서 다른 것들은 다 되는데.. 이미지만 안 불러진다는 사실-ㅁ-!!!!

  2. 2007/10/05 09:08

    이미지경로로는 못불러오구 DB자체에 이미지를 바이너리형태로 저장해서 불러왔었던것 같아요 -0-;;
    너무 오래전에 했던것이라...;;

    perm. |  mod/del. |  reply.

What's on your mind?

댓글 입력 폼
[로그인][오픈아이디란?]

.NET Framework 3.0

2006/10/26 13:43

회사에서 정기 구독하는 <월간>마소를 읽다가 .NET Framework 3.0이 배포되었다는 사실을 알게 되었다.
사실, .NET Framework 3.0은 윈도우즈의 차세대 버젼인 윈도우 비스타(일명: 롱혼)에 기본적으로 포함되어 내년에 정식 출시될 것이라고 한다.

어쨌거나, .NET Framework 3.0의 핵심적인 키워드를 꼽자면 WinFX라고 할 수 있을 것 같다. 우리는 지금까지 MS-DOS 환경을 거쳐 Win16 Application, Win32 Application을 개발해왔는데, 이제 WinFX로 넘어간다고 보면 된다.

MS는 WinFX로 Win32 Application의 진화를 선언하면서 몇 가지 획기적인 변화를 시도하는데, 그것은 바로 WPF, WCF, WWF, WCS라고 할 수 있다.

응?! 무슨 말이냐고-ㅁ-
WPF는 기존의 네모로만 규정되던 Windows Application을 넘어 화려한 UI 구현이 가능케 한다. 3D 화면뿐만이 아니라 조작성을 포함한 Application의 사용 편의성도 보장할 수 있으며, 웹 Application과 윈도우즈 Application의 경계를 거의 허무는듯한 시도를 하게 된다. (WPF의 더 자세한 내용은 다음 기회에...)

어쨌거나, 한마디로 요약하자면 Application의 UI에 획기적인 변화를 도모한 것이 바로 WPF, Windows Presentation Foundation이다.

WCF는 다양한 표준화 기술을 공통으로 사용하기 위한 클래스 라이브러리라고 볼 수 있다. (이에 대한 보다 자세한 내용도 다음에..)

그리고, 개인적으로 가장 쇼킹한 것 중 하나였던 WWF, Windows Workflow Foundation.
이 녀석은 프로그램의 플로우 변화에 따른 유연성을 제공한다.
개개의 프로그램과 내부 흐름을 분리시켜, 흐름이 바뀌더라도 프로그램 코드의 변화는 거의 없도록 유지할 수 있도록 한다. (이에 대한 자세한 내용도 다음에-_-)

개인적으로 받은 느낌이라면, 최근 이슈가 되고 있는 Object Oriented Paradigm에서 Event 중심의 패러다임으로 바뀌어간다는 걸까?! 어쨌든, 다음 동영상을 보면 더욱 도움이 되지 않을까 싶다.

http://www.microsoft.com/korea/eseminar/Seminar_player7.aspx?number=1074&asf=300K

크리에이티브 커먼즈 라이센스
Creative Commons License

Trackback

Trackback Address :: http://www.nohungry.net/tt1/trackback/42

Comments

  1. acaran 2006/10/26 17:51

    아, 증말 이전공 왜 택했을까-_- 새로 배워야할것이 날로 쏟아지네-_-

    perm. |  mod/del. |  reply.
  2. NOhungry 2006/10/27 10:09

    그러게나 말일세-_- 뭐 좀 이제 적응이 되나 싶음, 또 새로운 녀석이 나타나니.ㅠㅠ 정말 후덜덜하오

    perm. |  mod/del. |  reply.
  3. UnlimiT 2006/10/30 10:20

    공부 열심히 하는구려...

    perm. |  mod/del. |  reply.

What's on your mind?

댓글 입력 폼
[로그인][오픈아이디란?]

[C#] Cross Thread Problem

2006/10/20 17:35

서두는 제외하고, 바로 예를 들어 설명하도록 하겠다. (편의 상 반말로...)

A란 프로그램은 여러 개의 Thread가 돌고 있다. 그 중 Thread T1은 B란 프로그램과 소켓 통신을 위해 사용되는데, T1은 B에서 전송하는 메시지를 처리한다. 그리고 처리된 메시지는 바로 텍스트 박스 컨트롤에 표시된다.

프로그래머는 단순히, 다음과 같이 코드를 썼다.

ThreadFunc T1()
{
    while(1){
           ....
           // B가 보낸 메시지를 받는다.
           int nMessage = GetSocketMessage();
           
          // 메시지를 텍스트 박스에 표기한다.
           txtBoxControl.Text = nMessage.ToString();            
    }
}
    
그랬더니 Cross Thread Problem이란 메시지가 뜨며, 프로그램이 제대로 수행될 수 없다고 나온다. 과연, Cross Thread Problem이란 무엇인가 (물론, 위의 코드가 정확히 Cross Thread Problem을 발생하는 것은 아니다.. 하지만 그럴 가능성을 내재하고 있는 코드라고 할 수 있다.)?!

MSDN에 따르면,
전문적인 프로그램은 응답성 있는 사용자 인터페이스를 유지하기 위해 worker thread들을 사용하게 된다(*hyperthreading 또는 Multiple CPU들의 최대화를 위해서..). 하지만, .NET에서 이 문제는 특별히 쉬운 문제가 아니다, 왜냐면, Windows Forms 컴포넌트들은 thread safe 하지 않기 때문이다(특별히 번역할 말이 없어서-_-.. Thread들에 대해 안전하지 않다 정도의 뉘앙스일까나..?).

.NET의 어떤 버젼에서는 thread들 내부에 GUI 컴포넌트의 함수를 호출하려고 할 경우, 예외를 발생시킬 수 있다. 하지만, 종종 내가 의도한 바와 다른 이상한 결과를 내는 것으로 끝날 수도 있다(예외는 발생 안했지만, 내가 의도한 결과와 다르게 나올 수 있다는 말이다).

해결 방법은?!
만약, 다른 thread로부터 GUI 컴포넌트를 호출하고 싶다면, 직접적으로(directly) 호출할 수는 없다. 대신에 컨트롤 클래스로부터 상속받은 invoke 함수를 통해 간접적으로(indirectly) 실행하고자 하는 컴포넌트의 함수를 호출할 수 있다.

다른 invoke 함수와는 달리, 컨트롤 클래스의 invoke 함수는 데이터 corruption을 피해 호출을 동기화할 수 있도록 보장해준다.

컨트롤의 invoke 함수를 호출하기 위해 필요한 것은 invoke 함수의 인자로써 호출하고자 하는 함수를 delegate로 작성해서 넘겨야 한다. 그리고 invoke 함수의 인자로 넘어가는 함수에 필요한 인자는 object 배열로 넘겨야 한다.

예를 통해서 살펴보자!
예제 프로그램은 다른 프로그램에서 소켓을 통해 날려주는 탭 컨트롤의 인덱스를 받아, 현재 프로그램의 탭을 변경하는(그러니까 탭 화면을 바꾸는) 기능을 포함하고 있다.

즉, 다른 프로그램에서 전송하는 메시지를 처리하는 함수가 Thread로 동작하고 있고, 이 Thread 내부에서 탭 컨트롤의 탭을 변경하는 상황이 발생하기 때문에, Cross Thread 문제가 발생하였다(참고로 말하면, 각 탭에도 탭에 어떠한 데이터를 표현하기 위한 다른 Thread들도 동작하고 있기 때문에, Cross Thread 문제가 매우 발생하기 쉬운 구조다.)

예제 코드를 보면!
우선 WaitMessage()란 함수는 다른 프로그램에서 Socket을 통해 전송하는 메시지를 처리하기 위한 Thread 함수다. 이 때 받아들이는 메시지는 현재 프로그램의 탭 컨트롤의 인덱스이다. 이 Thread 내부에서 탭 컨트롤의 탭을 변경하기 위해 바로, SelectTab() 함수를 호출할 경우, Cross Thread 문제로 인한 Exception이 발생한다.

DoWork()는 이러한 문제를 회피하기 위한 함수다. 자세한 내용은 아래 코드를 보면서 얘기하자.
                                           ....

  DoWork() 함수는 앞서 WaitMessage() 함수에서 다른 프로그램으로부터 전송받은 탭 인덱스를 파라미터로 받아 현재 프로그램의 탭을 변경하는 역할을 수행한다. 또한, DoWork() 함수는 앞서 언급한 Cross Thread 문제를 회피하기 위해 컨트롤 클래스의 Invoke 함수를 사용하는데, Invoke 함수를 사용하기 위해서는 필연적으로 delegate를 선언해야 한다(delegate에 대한 상세한 내용은 다른 기술 문서를 참조하기 바란다.)

예제에선 ChangeTab이란 delegate를 선언하고, DoWork() 함수에서 사용한다.
DoWork() 함수에선 탭 컨트롤의 InvokeRequired 속성을 체크해 true일 경우, Invoke() 함수를 사용한다.
앞서 선언한 delegate의 파라미터로 탭 컨트롤의 SelectTab() 함수를 넘기고, Invoke() 함수에는 delegate와 SelectTab() 함수에 필요한 인자(탭 인덱스)를 함께 파라미터로 넘긴다.



결론
지금까지 간략하게 Cross Thread Problem에 대해 기술해보았다. 보다 깊은 내용보다는 왜 문제가 발생하고, 어떻게 해결하느냐에 대한 기술만 해놓았기 때문에, 보다 자세한 내용을 알고 싶다면, MSDN을 참조하기 바란다.


덧, hyperthreading에 대한 보다 자세한 내용은 http://blog.naver.com/subellia1?Redirect=Log&logNo=100011680762의 article을 참조하기 바란다.

크리에이티브 커먼즈 라이센스
Creative Commons License

Trackback

Trackback Address :: http://www.nohungry.net/tt1/trackback/39

Comments

  1. acaran 2006/10/21 16:13

    아이고 머리야-_- 무슨말인지 하나도 몬알아묵겠네 그랴~ -_-

    perm. |  mod/del. |  reply.
  2. 조병수 2008/06/18 16:02

    모르는 부분을 잘 설명해 주셔서 감사해요~~

    perm. |  mod/del. |  reply.
  3. 김형준 2009/12/31 11:17

    감사! ^^

    perm. |  mod/del. |  reply.
  4. 최익필 2010/02/08 14:21

    완전 감사합니다!

    perm. |  mod/del. |  reply.

What's on your mind?

댓글 입력 폼
[로그인][오픈아이디란?]

C++ Platform SDK Function에서 제공하는 ShellExecute와 동일한 동작을 하는 녀석이 C#에도 있다.
물론, C#에서도 ShellExecute를 가져와서 쓸 수도 있지만..

사용법은 다음과 같당.

// 실행시키고자 하는 프로세스의 주소를 넘긴다.
System.Diagnostics.ProcessStartInfo process =
new System.Diagnostics.ProcessStartInfo(@"D:\SmartMailService.exe");          

// 프로세스의 실행 방식을 설정한다.
// Verb는 프로세스의 동작 방식을 가리킨다.

process.UseShellExecute = true;
process.Verb = "open";

// 프로세스를 실행한다.
System.Diagnostics.Process.Start(process);  

       

크리에이티브 커먼즈 라이센스
Creative Commons License
TAG

Trackback

Trackback Address :: http://www.nohungry.net/tt1/trackback/33

Comments

  1. UnlimiT 2006/09/21 02:25

    new를 했는데 delete는 안해도 되는가부지?
    아...C++에만 익숙해져서 그런 생각이 나는건가....

    perm. |  mod/del. |  reply.
  2. NOhungry 2006/09/21 09:15

    도현이형~ 그건 C#도 Java랑 마찬가지로 Garbage Collection을 하기 때문이죠.

    perm. |  mod/del. |  reply.
    • MrGeek 2006/10/17 01:17

      대신 가끔 특정 인터페이스를 구현해
      Dispose와 같은 메서드를 준비해야 할 필요가 있습니다.

  3. 2006/09/21 11:15

    c#... 그 모양새가 c의 탈을 쓴 JAVA 같구려~

    perm. |  mod/del. |  reply.
    • MrGeek 2006/10/17 01:18

      대충 C# 언어스펙에 관한 책들을 보면
      C의 유연함과 JAVA의 객체지향 VB의 간단함 이라는
      세 언어의 큰 장점을 엮어 만든 언어라고들 합니다.

      사실 C#에 관해선
      1.0부터 3.0까지 봐야할것이 산더미같죠

      한번 배워보시렵니까?

What's on your mind?

댓글 입력 폼
[로그인][오픈아이디란?]

메일 자동 발송 프로그램

2006/09/14 14:58

건축물과 교량에 대한 웹모니터링 시스템을 구축하던 차... 모니터링된 결과를 리포트로 작성하여 주기적으로 메일을 자동 발송하는 기능을 하는 프로그램이 필요해.. 구현한 프로그램이다.

Language는 새로운 것을 익혀보고자 하는 마음에 C#으로 했다. 근데 확실히 MFC보다 껍떼기는 이쁘게 만들어주는 것 같다.ㅋ

[와방 심플한 인터페이스]


원래 프로그램의 만든 목적은.. 연구용이었기 때문에.. 디자인부터 초 심플하게 만들었다-ㅁ- 그러다.. 심경의 변화를 일으켜 덕지덕지 기능을 하나씩 갖다붙이며.. 환경 설정 버튼까지 만들었다.

환경 설정 화면(1)



받는 사람을 추가, 삭제, 편집이 가능하며, SMTP를 설정할 수 있다. 보내는 사람도 등록 가능하며, 자동 발송 시간과 자동 발송 간격은 콤보 박스 리스트를 이용해 선택이 가능하다.

환경 설정 화면(2)

메일 설정 탭을 누르면.. 메일 제목, 내용, 첨부 파일을 추가 가능하다. 첨부 파일은 드래그 & 드롭 기능을 지원하기 때문에.. 탐색기에서 파일을 끌어다 붙이면 된다. 그리고, 확인 버튼을 누르면 환경 설정이 완료된다.

트레이 아이콘을 이용해서...





자동 발송 기능이 활성화되었을 때는 오렌지 색이 불이 들어오고, 그렇지 않을 때는 회색으로 나오게 하였다. 그리고 최소화 버튼을 누르면.. 트레이 아이콘만 나타나고 창이 사라지고.. 트레이 아이콘의 우클릭을 통해 프로그램의 제어가 가능하당..

그리고 사실 내가 구현한 기능은 아니지만-ㅁ- 프로그램을 셋업 시키면.. 다음에 프로그램을 다시 실행할 때, 내가 지정한 특정 웹사이트에 업그레이드된 버젼이 있으면.. 자동으로 업그레이드도 된다. (.NET의 위력-ㅁ-)

짧은 개발 기간으로 아직 자질구레한 버그가 많을 것으로 예상하고 있다.. 필요한 사람도 없을거라고 보여지지만 소스는 비공개이당(회사 업무에 적용될 수 있기 때문)..

프로그램 역시.. 스팸 메일 발송등-ㅁ- 악용 될 우려가 있어서.. 공개를 참기로 했다.ㅋ (사실-ㅁ- 공개할 수준의 프로그램도 아니라 판단했음.ㅋㅋ)

크리에이티브 커먼즈 라이센스
Creative Commons License

Trackback

Trackback Address :: http://www.nohungry.net/tt1/trackback/30

Comments

  1. acaran 2006/09/14 23:42

    이걸로 나한텐 스팸보내지 마오 ㅋㅋ

    perm. |  mod/del. |  reply.
  2. 2006/09/15 11:06

    왜 이런걸 보면.. 걱정이 먼저 되지?

    perm. |  mod/del. |  reply.
  3. NOhungry 2006/09/15 11:17

    ToAll/ 무슨 걱정?!ㅋ 내가 설마 스팸 보낼까봐서?ㅋㅋ

    perm. |  mod/del. |  reply.
  4. 2006/09/21 11:16

    스팸보다 더 무서운.. JANGGO~ 덜덜덜.. -_-;;

    perm. |  mod/del. |  reply.

What's on your mind?

댓글 입력 폼
[로그인][오픈아이디란?]