SimpleIsBest.NET

유경상의 닷넷 블로그

닷넷의 발견: HttpListener 클래스

by 블로그쥔장 | 작성일자: 2007-01-08 오전 3:33:00
이 글은 오래된 전에 작성된 글입니다. 따라서 최신 버전의 기술에 알맞지 않거나 오류를 유발할 수 있습니다. 저자는 이 글에 대한 질문을 받지 않을 것입니다. 하지만 이 글이 리뉴얼 되면 이 글에 대한 질문을 하거나 토론을 할 수도 있습니다.

아주 오래 전부터 HttpListner 클래스에 대한 글을 쓰고 싶었습니다만 이제서야 토픽을 쓰는군요... 이 망할 넘의 귀차니즘... 대학다닐 때는 기말시험 보는게 귀찮아서 F를 맞은 적도 많았다는... -_-;

제 친구가 했었던 말 "난 언젠가 잠 때문에 망할 꺼야" 처럼 저도 언젠가 이 귀차니즘 때문에 망하지 않나 싶네요... T_T

Discovery: HttpListener Class

닷넷 프레임워크 2.0에서 System.Net 네임스페이스는 다양한 기능들이 추가 되었다. SMTP 메일에 대한 클라이언트 구현 뿐만 아니라 MIME 타입에 대한 구현 일부, 그리고 HttpWebRequest/HttpWebResponse 클래스의 기능 강화 등이 존재한다. 이 외에 눈길을 끄는 것이 HttpListener 클래스이다. 이 클래스에 대해 제대로 이해하자면 먼저 Http.sys 드라이버에 대해 알아둘 필요가 있다.

Http.sys device driver

Windows Server 2003이 등장했을 때 새로이 등장했던 IIS 6.0은 이전 버전에 비해 전혀 다른 HTTP 프로토콜 구현을 가지고 있었다. IIS 6.0 이전에는 WINSOCK을 기반으로 하여 HTTP 포트(80)를 리스닝(listening) 하였고 HTTP 메시지를 수신하고 송신했었다. (IIS 6.0 Core Architecture 관련 글 참조)

반면 IIS 6.0은 더 이상 WINSOCK을 사용하지 않았다. Windows Server 2003에 새로이 추가된 Http.sys 디바이스 드라이버는 HTTP 프로토콜을 위한 드라이버로서 HTTP 메시지를 수신하고 HTTP 메시지를 전송하는 전담한다. 쉽게 말하면 IIS가 하는 일 중 HTTP Request를 수신하여 이 메시지를 어플리케이션에 전달하여 처리하도록 한 후 그 결과를 다시 클라이언트(웹 브라우저)에게 전송하는 역할을 Http.sys 드라이버가 수행한다는 것이다. 커널 모드 드라이버이기 때문에 WINSOCK에 비해 더욱 빠르게 HTTP Request를 처리할 수 있다.

Http.sys 드라이버는 IIS 6.0 만의 전유물이 아니다. 대부분 그러하듯이 Microsoft는 Http.sys 를 제어하기 위한 API 인 HTTP Server API가 제공된다. IIS 6.0 역시 이 API를 사용하여 구현되어 있다.  HTTP 프로토콜에 관련되어 Windows 가 제공하는 API는 WinInet, WinHTTP, HTTP Server API 등 다양하므로 다음 글을 참고 하기 바란다.

닷넷의 발견

Http.sys 드라이버가 Windows Server 2003에만 포함되었더라면 이 글을 쓸 정도로 중요하게 느껴지지 않았을 것이다. 하지만 Windows XP의 서비스 팩 2에도 Http.sys 가 추가 됨으로써 주요 윈도우 버전들이 모두 Http.sys를 사용할 수 있게 되었다. 비록 Windows XP에 포함된 IIS 5.1이 여전히 WINSOCK 기반으로 작동하지만 Http.sys를 사용하는 어플리케이션을 작성할 수는 있다. 사실 Http.sys를 직접적으로 사용하는 어플리케이션은 아직 보진 못했지만 말이다. Windows XP SP2 상에서 Http.sys 를 이용할 때 주의할 점은 IIS 5.1이 80 포트를 리스닝 하고 있다면 Http.sys를 이용하여 80 포트를 통해 HTTP Request 메시지를 수신하거나 Http Response 메시지를 전송할 수 없다는 점이다. 포트가 쫑나므로 짱구가 아닌 다음엔 당연하게 받아 줘야 한다. 대신 다른 포트를 사용할 수는 있다. (뭐 이것도 당연히 받아 줘야 하게찌?)

Why Http.sys ?

Http.sys 드라이버가 Windows XP를 비롯한 클라이언트 운영체제에서 사용할 수 있는 것을 알았지만 중요한 것은 Http.sys를 어디에 써먹을 것인가에 대한 것이다. Windows XP를 비롯하여 Vista에도 IIS 가 포함되어 있음에도 불구하고 Http.sys를 써야 할 데가 있을까?

IIS 5.1 혹은 IIS 7.0이 Windows XP와 Vista에 포함되어 있더라도 이들은 기본 설치 항목이 아님에 주목해야 한다. 즉, 운영체제가 설치될 때 IIS는 기본적으로 설치되지 않으며 추가적으로 설치를 해야만 한다. 개발자들이야 수동으로 설치를 할 수도 있겠지만 기업의 최종 사용자나 가정의 일반 사용자는 IIS가 뭔지도 모른다. 따라서 클라이언트에 IIS가 기본으로 설치되어 있다는 가정을 하기는 쉽지 않다.

이런 상황에서 HTTP를 사용하는 메신저나 P2P 파일 전송 어플리케이션 혹은 서버에서 어떤 이벤트를 클라이언트에게 알려주는 통지(notification) 기능을 구현해야 한다고 가정해 보자. 최종 사용자에게 IIS를 설치하도록 유도하는 것은 쉬운 일이 아니며, IIS를 메신저나 P2P 프로그램 등에 응용하기란 쉽지 않다. 게다가 TCP Socket 프로그램이 아닌 HTTP를 써야 하는 이유는 대단히 많다. 대표적으로 방화벽 문제를 들 수 있겠다. 대부분의 경우 방화벽은 HTTP 80 포트에 대해서는 대단한 관용을 베풀기 때문이다. 따라서 다양한 상황에서 클라이언트가 파일 전송,메시지 수신, 이벤트 수신을 위해 HTTP 서버 역할을 수행해야 하는 상황이 발생할 수 있다.

HTTP 프로토콜을 SOCKET 프로그래밍으로도 구현할 수 있을 것이다. 필자가 Socket 으로만 HTTP 서버 역할을 하는 간단한 예제를 만들어봤지만 이는 쉬운 일이 아니었으며 HTTP 프로토콜의 극히 일부분만을 구현하는데도 많은 시간을 소요되었다. 게다가 그 신뢰성 마저 높지 않을 것이다. 이런 상황에서 이미 구현되어 있는 HTTP 프로토콜 처리기가 있으면 얼마나 좋을까?

그렇다. Http.sys는 바로 그런 상황에서 사용할 수 있는 대안인 것이다. HTTP Request를 수신하여 어플리케이션에 전달해 주고 어플리케이션의 처리 결과를 클라이언트에게 전달하는 이미 구현되었고 IIS에 의해 사용될 만큼 신뢰도가 높은 모듈이 바로 Http.sys 와 HTTP Server API 인 것이다.

HttpListener Class

Http.sys 드라이버를 사용하기 위한 HTTP Server API는 대단히 아쉽게도 C/C++을 위한 API이다. 다른 API 들은 COM도 지원하고 그러더니 이상하게도 이넘의 API는 그 흔한 인터페이스 조차 없이 쭈욱 C 함수만을 가지고 있을 뿐이다.

닷넷 프레임워크가 어디 핫바지도 아니고... 많은 윈도우 API를 래핑(wrapping) 하고 있는 것이 바로 닷넷 프레임워크 아니던가? 이쯤 되면 눈치를 채는 센스를 가져줘야 한다. 바로 HttpListener 클래스가 HTTP Server API를 래핑 하는 클래스이다. HTTP Server API에 대한 상세한 기능이나 제약점은 MSDN을 찾아 보기 바란다. 물론 "내가 한 C/C++함은 물론이요 한 API 한다"는 사람만이 좌절감을 덜 받을 것임을 상기해 준다.

우리의 관심은 어떻게 System.Net 네임스페이스의 HttpListener 클래스를 잘 요리할 것인가 이다. 복잡한 암호와 같은 API와는 전혀 상관없이 매우 닷넷스럽게 HTTP 서버를 만들 수 있다. ASP.NET과 매우 흡사한 컨텍스트(context)를 제공할 뿐 더러 HttpRequest, HttpResponse와 유사한 객체들도 제공하므로 ASP.NET의 HttpHandler를 작성하거나 커스텀 컨트롤(custom control)을 작성하듯이 웹 서버를 작성할 수 있다.

Creating HttpLisener & Initializing

HttpListener 객체를 생성하는 것은 매우 쉽다. 이 클래스는 달랑 디폴트 생성자(constructor) 만을 가지고 있기 때문에 고민할 필요 없이 객체를 생성하면 된다. 설마 디폴트 생성자가 뭔지 모르진 않겠지? ^^ (매개변수가 없는 생성자이다)

HttpLisener 객체를 생성한 후에 제일 먼저 해야 할 작업은 HttpListener 가 수신할 HTTP Request의 Uri의 Prefix를 설정하는 것이다. 쉽게 말해 생성한 HttpListener 객체가 수신할 Uri이 어떤 값으로 시작하는가를 명시해야 한다는 것이다. 예를 들어 Uri Prefix를 http://localhost:80/MyTemp/ 라고 설정했다면 http://localhost:80/MyTemp/ 로 시작하는 모든 Url은 이 HttpListener에 의해 수신되게 되는 것이다.

리스닝(listening) 할 Prefix를 설정할 때 주의할 점이 몇 가지 있다. 첫째로 주어진 Uri는 정규화된 형태(canonical form)의 값이어야 한다. 즉, Uri의 스킴(scheme; http 혹은 https 설정)과 포트를 모두 명시해야만 한다는 것이다. 특히 HTTP의 기본 포트인 80 포트를 사용하더라도 반드시 80 값을 명시해야만 한다는 점에 유의하자. (필자는 이것 때문에 30분 이상을 헤맸었다.)

    1 HttpListener listener = new HttpListener();

    2 listener.Prefixes.Add("http://localhost:80/MyTemp/");

    3 listener.Prefixes.Add("http://localhost:80/NewTemp/");

    4 listener.Prefixes.Add("http://workman:8080/");

    5 listener.AuthenticationSchemes = AuthenticationSchemes.Basic | AuthenticationSchemes.Anonymous;

리스트1. HttpListener 객체 생성과 초기화

리스트1은 HttpListener 객체를 생성하고 초기화 하는 가장 기초적인 방법을 보여주고 있다. 5번째 라인처럼 인증 방식을 명시할 수도 있다. 사실 서버 측 인증은 HTTP Server API 1.0에서는 지원하지 않는다. 하지만 닷넷 프레임워크 2.0이 서버 인증을 스스로 구현하기 때문에 가능한 것이다. 참고적으로 HTTP Server API 2.0에서는 API 수준에서 인증을 구현하고 있다지만 닷넷 프레임워크는 1.0 API 만을 사용하고 있다.

Getting HTTP Message Context

이제 리스닝 준비가 끝났으니 리스닝을 수행하면 된다. HttpListener 객체의 Start 메쏘드를 호출하면 Http.sys 드라이버는 주어진 Uri Prefix를 가진 HTTP Request 메시지가 도착하는 것을 감시하게 된다. 보다 정확하게 말하면 HTTP Request 큐를 생성하고 주어진 Prefix를 가진 HTTP Request 메시지가 도착하면 이것을 큐에 삽입하기 시작한다.

주) HttpListener가 리스닝을 시작하기 위해서는 관리자 권한을 필요로 한다. Windows Vista 에서 UAC(User Account Control)이 적용되고 있다면 "액세스 거부" 예외가 발생할 것이다. 이를 피하기 위해서는 manifest 를 작성해야만 한다. 관련 글을 참고하기 바란다.

큐에 삽입된 HTTP Request 메시지를 꺼내오는 것은 HttpListener 클래스의 GetContext 메쏘드를 호출하면 된다. 이 메쏘드는 HttpListenerContext 객체를 반환하는데, 이 객체는 ASP.NET의 HttpContext와 매우 비슷한 기능을 수행한다. 즉, HttpListenerContext 객체는 속성으로써 Request 속성과 Response 속성을 제공하고 이들 속성들은 각각 HttpListenerRequest 객체HttpListenerResponse 객체를 노출한다. ASP.NET을 좀 다루어 본 독자라면 이들 객체가 어떤 역할을 수행할지는 너무도 잘 알고 있을 것이다.

    1 listener.Start();

    2 

    3 HttpListenerContext ctx = listener.GetContext();

    4 HttpListenerRequest request = ctx.Request;

    5 HttpListenerResponse response = ctx.Response;

    6 

    7 StreamWriter writer = new StreamWriter(response.OutputStream, Encoding.UTF8);

    8 writer.WriteLine("<html><body>");

    9 writer.WriteLine("<h1>테스트 !!!</h1>");

   10 writer.WriteLine("<p>URL : {0}</p>", request.Url);

   11 writer.WriteLine("<p>User Agent : {0}</p>", request.UserAgent);

   12 writer.WriteLine("<p>Client : {0}</p>", request.RemoteEndPoint.ToString());

   13 if (request.IsAuthenticated) {

   14     writer.WriteLine("<p>사용자 : {0}</p>", ctx.User.Identity.ToString());

   15 }

   16 else {

   17     writer.WriteLine("<p>익명 사용자</p>");

   18 }

   19 writer.WriteLine("</body></html>");

   20 writer.Close();

   21 response.Close();

리스트2. Http 메시지 수신과 간단한 처리 예제

리스트2는 HttpListenerContext 객체를 수신하고 이를 처리하는 간단한 예를 보여주고 있다. HttpListenerRequest 객체를 사용하여 HTTP Request 메시지 정보를 추출하거나 HttpListenerResponse 객체를 사용하여 결과를 렌더링 하는 방식을 잘 살펴보기 바란다. ASP.NET 처럼 편리한 Response.Write 같은 메쏘드는 존재하지 않으며 Page 객체 따위는 존재하지도 않는다는 것을 명심해야 한다. HttpListenerRequest 클래스나 HttpListenerResponse 클래스에 대한 상세한 내용은 그 내용이 상당히 많기 때문에 MSDN을 참고하기 바란다. (쫌 찾아 봐라... 정말 너무들 한다... -_-;)

Cleanup

HttpListener의 사용이 끝났다면 Stop 메쏘드를 호출하여 Url에 대한 리스닝을 중단해야 한다. 그리고 Close 메쏘드를 호출하여 Unmanaged 리소스를 해제하는 센스도 잊지 말자.

    1 // 리스닝을 중단한다.

    2 listener.Stop();

    3 listener.Close();

리스트3. HttpListener 클린업 코드

Advanced Usage of HttpListener

리스트2와 같은 코드는 실제 어플리케이션에 응용하기에는 몇 가지 문제를 안고 있다. 첫째로 이 코드는 단 1회의 HTTP Reuqest 만을 처리한다는 것이다. 즉, GetContext 호출에 의해 하나의 HTTP Request를 읽고 처리하고 있다. 그 이후에 발생되는 HTTP Request 는 죄다 404 NOT FOUND 오류를 유발할 것이다. 두 번째 문제점은 Prefix만이 설정되어 있을 뿐 다양한 URL에 대한 멀티플렉싱(multiplexing)을 전혀 수행하지 않는다. 즉, /MyTemp/Page1.htm 이건 /MyTemp/Page2/htm 이건 /MyTemp/ 로 시작하는 모든 Url에 대해 동일한 결과만이 렌더링 된다는 것이다. 이러한 점들을 해결하려면 조금씩 머리를 써야 한다. 머리는 박치기 할 때만 쓰는 것이 아니라는 점을 상기하자.

Dispatching Request

반복적으로 HTTP Request를 수신하고 처리하기 위한 방법은 다양하다. 가장 간편한 방법으로는 반복문을 사용할 수 있다. while 문을 사용해서 반복적으로 GetContext 메쏘드를 호출하여 HttpListenerContext를 얻고, 이를 처리하여 그 결과를 렌더링 하면 된다. 이 방법은 간단하긴 하지만 여러 Http Request가 동시에 수신되었을 때 이들이 순차적으로 처리된다는 아픔이 있다. 게다가 HTTP 서비스를 우아하게 종료할 뾰족한 방법(즉, while 문을 언제 빠져나갈 것인가에 대한 방법)을 찾기가 영 애매해 지기 마련이다.

이러한 문제는 HttpListener 뿐만 아니라 일반적으로 SOCKET 프로그래밍을 할 때 항상 서버 측에서 유발되는 문제이다. 따라서 HttpListener를 사용할 때도 SOCKET 프로그래밍에서 했었던 동일한 기법들을 사용하면 된다. 즉, 비동기 GetContext 메쏘드들(BeginGetContext 메쏘드 및 EndGetContext 메쏘드)을 사용하거나 다중 쓰레드를 사용하는 방법이 바로 그것이다. 비동기 방식이나 다중 쓰레드를 사용하면 동시성(concurrency) 문제와 서비스의 우아한 종료 문제를 모두 해결할 수 있다.

상세한 예제는 이 글의 범위를 넘어서므로 (조낸 길어지게 될 것이다) 여기서는 다루지 않겠다. (다음에 다룬다는 얘기는 하지 않겠다. 그렇지 않아도 공수표 날려놓은 것이 많아서... -_-; )

Multiplexing HTTP Request

Http.sys 드라이버는 HTTP Request의 Url을 보고 그것이 특정 Prefix와 매치가 되면 적절한 Context 를 만들어 그것을 큐에 집어 넣는 역할만을 수행한다. Url 에 따라 서로 다른 결과를 렌더링 하는 것은 전적으로 어플리케이션의 몫임에 유의할 필요가 있다.

간단한 해결책으로는 HttpListenerRequest 객체의 Url 속성을 이용하여 어떤 Url이 요청되었는가 판단하고 그에 따른 처리를 해주면 될 것이다. 이는 간단하게 생각하면 대단히 간단하고 복잡하게 구현하고자 하면 한 없이 복잡한 구현이 될 것이다. HttpListener를 사용하는 어플리케이션이 요구하는 구현 수위에 따라 간단히 if 문장 한두 개로 처리될 수도 있고 Hashtable 혹은 List<> 등 복잡한 객체들을 사용해야 할 수 있다. 이에 대한 구체적인 사항은 독자들의 상상력에 맡긴다. (아싸... 이젠 막가는구나...)

Help from ASP.NET

리스트2와 같이 HTML을 렌더링 해야 한다면 정말 팍팍한 인생이 될 것이다. ASP.NET에 이미 구현되어 있는 다양한 객체들을 사용할 방법은 없을까? 물론, ASP.NET에 완전한 의존성을 갖지 않는 것들이라면 HttpListener에서도 사용이 가능하다. 예를 들어 ASP.NET의 Page 객체를 항상 요구하는 클래스나 마스터 페이지 같은 것은 사용할 수 없을지라도 HtmlTextWriter 클래스나 Label, Button, DataGrid 같은 객체는 사용이 가능하다.

    1 StreamWriter textWriter = new StreamWriter(response.OutputStream, Encoding.UTF8);

    2 HtmlTextWriter writer = new HtmlTextWriter(textWriter);

    3 writer.RenderBeginTag(HtmlTextWriterTag.Html);        // <html>

    4 writer.RenderBeginTag(HtmlTextWriterTag.Body);

    5 writer.RenderBeginTag(HtmlTextWriterTag.H1);

    6 writer.Write("HttpListener 클래스를 이용한 웹 페이지 예제");

    7 writer.RenderEndTag();    // </H1>

    8 writer.RenderBeginTag(HtmlTextWriterTag.P);

    9 writer.WriteEncodedText("Request Url : ");

   10 writer.WriteEncodedUrl(ctx.Request.Url.AbsolutePath);

   11 writer.RenderEndTag();    // </P>

   12 writer.RenderEndTag();    // </body>

   13 writer.RenderEndTag();    // </html>

   14 writer.EndRender();

   15 writer.Flush();

   16 writer.Close();

리스트4. HtmlTextWriter의 활용

리스트4는 HtmlTextWriter 클래스를 사용하여 HTML을 렌더링하고 있다. HtmlTextWriter가 반드시 ASP.NET에서만 사용되라는 법이 없으므로 이를 사용하여 HTML을 렌더링 할 수 있다. 또한 HtmlTextWriter 객체를 구할 수 있다면 ASP.NET 서버 컨트롤들이 제공하는 RenderControl 메쏘드를 호출하여 HTML을 렌더링 할 수도 있다. 리스트5를 살펴보자.

    1 // writer 변수가 HtmlTextWriter 객체로 초기화 되어 있다고 가정

    2 Label label = new Label();

    3 label.Text = "알라고 하지마.. -_-;";

    4 label.Font.Bold = true;

    5 label.Font.Name = "굴림";

    6 label.Font.Size = new FontUnit(10, UnitType.Point);

    7 label.RenderControl(writer);

    8 

    9 System.Data.DataSet ds = new System.Data.DataSet();  // 편의상 DataSet을 그냥 xml에서 읽었다. 귀찮아서... -_-

   10 ds.ReadXml("Products.xml", System.Data.XmlReadMode.ReadSchema);

   11 

   12 DataGrid dataGrid = new DataGrid();

   13 dataGrid.Font.Size = new FontUnit(9.0, UnitType.Point);

   14 dataGrid.HeaderStyle.BackColor = Color.Black;

   15 dataGrid.HeaderStyle.ForeColor = Color.White;

   16 dataGrid.AlternatingItemStyle.BackColor = Color.Silver;

   17 dataGrid.DataSource = ds;

   18 dataGrid.DataBind();

   19 dataGrid.RenderControl(writer);

리스트5. ASP.NET 서버 컨트롤의 활용

리스트4에서 처럼 일단 HtmlTextWriter를 구성해 놓은 후, ASP.NET 서버 컨트롤을 생성하여 RenderControl을 호출하면 서버 컨트롤에 의해 ASP.NET 과 동일한 HTML 결과물을 얻을 수 있다. 재미 있지 않은가? (나만 재미있나? 된장... -_-)

예제 수행 결과 화면
화면1. 리스트4, 리스트5의 코드를 수행한 결과

Conclusion

닷넷 프레임워크 2.0에 새로이 추가된 HttpListener 클래스에 대해 간략하게(미친게야... -_-) 살펴보았다. HttpListener 클래스는 Windows Server 2003 과 Windows XP SP2 그리고 Windows Vista에 추가된 Http.sys 드라이버를 사용하여 IIS를 사용하지 않더라도 HTTP 서버를 작성할 수 있도록 해준다. HttpListener를 사용하여 웹 서버를 작성하지 않더라도 P2P 시나리오나 메신저, 이벤트 수신기 등 방화벽 때문에 TCP/IP Socket 프로그래밍이 어려운 상황에서 간단하게 HTTP 수신을 할 수 있기 때문에 다양한 응용이 가능하다.

HttpListener를 사용하는 방법은 Socket 프로그램을 작성하는 것과 매우 흡사한 프로그래밍 방식을 취하면 된다. 그러나 HttpListener 클래스는 Request/Response 객체 모델을 지원할 뿐만 아니라 ASP.NET의 일부 클래스까지도 사용할 수 있으므로 상당히 편리하게 파일 다운로드, 동적 HTML 컨텐츠 생성에 응용할 수 있다./p>

설명해야 할 클래스들이 상당한 내용을 갖고 있기 때문에 상대적으로 간단(?)한 이번 포스트는 응가하고 밑 안 닦은 것처럼 찝찝하긴 하다. 하지만 필자가 항상 강조하듯이 눈팅만으로는 절대 실력이 늘지 않는다. 한 줄이라도 코드를 짜봐야 자기의 지식으로 익혀지는 것이며 실력 향상에 도움이 될 것임을 잊지 말자. 뭐 아는 사람은 이미 알겠지만 그런 의미에서 필자는 싸가지 없게도 웬만하면 예제 코드를 제공하지 않는다. 지가 정말 궁금하면 짜 보겠지... 하면서 말이다. 이럴 때 독자들에게 필자가 해주고 싶은 말이 바로...

"강대욱 !!! 코딩 백번 !!!"



Comments (read-only)
#re: 닷넷의 발견: HttpListener 클래스 / 어흥이 / 2007-01-08 오전 9:03:00
헐...가장 밑줄읽고는 출근해서 혼자 웃고 있습니다.
그나저나 포스트 작성 시간이 오전 3:33분이군요.
월욜 아침에 피곤하시지 않으실까요?
언제나처럼 좋은글 감사드립니다.
#re: 닷넷의 발견: HttpListener 클래스 / 탱옹 / 2007-01-08 오전 9:33:00
구동되는 샘플정도는 좀 한그릇 뚝딱 말아주시징~~
일단, 돌려는 봐야할 거 아니겠수 ~~~ㅎㅎ
#re: 닷넷의 발견: HttpListener 클래스 / 위시 / 2007-01-08 오전 9:55:00
ㅋㅋ 서브백번하던 웃찻사 코너 패러디이군요...
코딩백번~~ ㅎㅎㅎ
#re: 닷넷의 발견: HttpListener 클래스 / 블로그쥔장 / 2007-01-08 오전 11:46:00
탱옹// 구동되는 샘플은 10-20줄 코딩하면 나오니 함 해보는 것도 나쁘지 않을 터...
니 게으름을 탓하라...
아놔... 뭐해? 빨랑 코드 한그릇 뚝딱 말지 않고서?
"김탱옹 !!! 코딩 백번 !!!"
#re: 닷넷의 발견: HttpListener 클래스 / 컴맹 / 2007-01-09 오전 11:04:00
오늘에서야 글을 봤네요..
좋은글감사합니다.^^
TV를 안봐서 유머는 이해가 안가지만 글을 잘 봤습니다.
웃찾사두 인터넷에서 찾아서 한번 봐야겠군요.. ^^
#re: 닷넷의 발견: HttpListener 클래스 / lancers / 2007-01-09 오전 11:54:00
이 정도 열심히 썼으면 귀찮을만도 하겠다. ㅋㅋㅋ
#re: 닷넷의 발견: HttpListener 클래스 / 키온 / 2007-01-09 오후 10:27:00
내 몸에 .NET Micro Framework을 설치후, WiFi를 달고 그 다음에 Http.sys를 이용 다양한 http데이터를 수신..캬하,,,이거 완존 Ghost in the shell인데...
#re: 닷넷의 발견: HttpListener 클래스 / 블로그쥔장 / 2007-01-09 오후 10:30:00
키온// 키온엉아... 그정도 되면 거의 병이다...
가까운 병원에 빨리 가봐야 할듯... ㅋㅋㅋ
#re: 닷넷의 발견: HttpListener 클래스 / 담덕대제 / 2007-01-24 오후 3:24:00
글 잘 보았습니다. ^^
#re: 닷넷의 발견: HttpListener 클래스 / 원~ / 2007-01-26 오후 3:03:00
ㅋㅋ..한동안 HPW 때문에 바쁘시다가 요즘 좀 한가하신가 보네요..이렇게 좋은글도 많이 써주시고..글 잘읽었습니다~ 참, 커피는 언제 사드려요???^^; 분당 오심 연락 주세요~~화이팅!!