windows2009. 5. 3. 13:48

IIS 를 시작시킬 때에 가끔 이런 에러를 내면서 시작되지 않는 경우가 있습니다.

The process cannot access the file because it is being used by another process.

좀 이상한 에러 메시지처럼 보입니다. 파일? 하지만, 실제로는 파일이 아니라 포트입니다. 즉, 파일이 아니라 IIS 웹 애플리케이션이 포트를 다른 프로세스 때문에 쓸 수가 없는 것입니다. 이런 문제가 발생했을 때에는 99%의 경우 다른 프로세스가 포트를 잡고 있는 경우입니다. 80포트야 웹 서버 전용이니, 다른 프로세스가 사용하는 경우가 별로 없지만, SSL의 443이나 다른 커스텀 포트의 경우 이런 일이 발생할 수 있습니다.

http://support.microsoft.com/kb/890015

마이크로소프트 고객지원 사이트의 위 URL을 참조하시면 해결할 수 있습니다.

즉,

netstat –ano

도스 명령행에서 위 명령어를 사용하면 모든 프로세스와 그 프로세스가 사용하는 포트의 리스트를 보실 수가 있습니다. 그러면 해당 포트를 사용하는 프로세스 ID를 파악할 수가 있습니다. 당연히 그 후에 그 프로세스를 중단시키면 됩니다. ^^

Posted by kkongchi
asp.net2007. 11. 22. 00:00

현재 우리 회사 솔루션의 ASP.NET 웹 애플리케이션에는, 빈번하게 사용되는 개인 정보(혹은 설정값)을 담는 용도로 쿠키를 사용하고 있다. 쿠키는 사실 참 편리하다. 서버의 리소스를 점유하지도 않고, 만료기간만 지정해두면 서버가 다운되건 말건 계속 유지도 되고.. 서버사이드, 클라이언트 사이드 어디서나 쉽게 접속할 수 있기도 하고.

하지만, 솔루션에 대한 보안 감사 끝에.. 쿠키를 제거하기로 결정이 되었다. 사실 보안 측면에서 보자면 쿠키라는 것은 꽤 위험하다. 문제는 이 쿠키가 클라이언트에 저장되는 Plain Text파일인데다가, 모든 Web Server에 대한 Request/Response시에 전송이 된다는 것이다. 즉, 클라이언트에서 이 파일을 열어 볼 수도 있고, 네트워크 패킷을 스니핑해서 내용을 볼 수도 있다. 거기다가 위/변조하기도 당연히 쉽다. 또 일부 국가 - 어딘지는 잘 모른다 - 에서는 법적으로 쿠키를 금지하기도 하고, Internet Explorer등의 브라우저에서도 쿠키를 허용하지 않는 옵션을 장착하고 있기 때문에 어떤 사용자들의 경우 쿠키를 아예 사용할 수 없을 가능성도 있는 것이다.

서두가 장황했는데, 암튼 쿠키를 모두 제거하기로 하고 우리가 선택한 대안은 ASP.NET 세션이었다. 사실 빈번하게 사용되는 사용자 개인의 설정값등을 담아둘 수 있는 가장 이상적인 공간이기도 하고, 쿠키와 매우 유사하게 서버사이드에서 사용할 수도 있기 때문이었다. 하지만 이 ASP.NET 세션에는 한 가지 문제가 있다. 그 문제는 바로, 이 ASP.NET 세션이 기본적으로 쿠키를 사용한다는 것이다.

ASP.NET 세션을 사용하면 생성되는 쿠키는 이렇게 생겼다.

ASP.NET_SessionId=d1ucyg30qyjw1f554szadoqy;

즉, ASP.NET 세션에서 각 사용자를 구분하는 것 자체가 이 쿠키를 사용하는 것이다.

그런데, ASP.NET에는 Cookie-less Session이라고 해서, 쿠키를 사용하지 않고 세션을 사용할 수 있게 해주는 모드 또한 있다. 이것은 별도의 코딩이 필요한 것은 아니고 단지 Web.Config의 SessionState 부분에 Cookieless를 True로 바꿔주기만 하면 된다.

<sessionState
            mode="InProc"
            stateConnectionString="tcpip=127.0.0.1:42424"
            sqlConnectionString="data source=127.0.0.1;Trusted_Connection=yes"
           
cookieless="true"
            timeout="20"
    />

이 Cookie-less Session에 대한 자세한 내용은 Dino Esposito씨의 다음 Article을 보면 알 수 있다.

위 아티클을 보면 알 수 있겠지만, 이 Cookieless Session은 세션을 쓰면서도 Cookie를 완전히 쓰지 않아도 된다는 점에서 나의 고민을 완벽하게 해주는 것이었다. 그러나 나는 몇 가지 문제를 발견했다..-_-;;

첫째로 이 Cookieless Session을 쓸 경우 모든 URL이 조금씩 바뀌게 된다는 것이다. 즉, 요청한 URL이 이렇다면..

http://localhost/CookielessSessionWebSample/Webform1.aspx

실제로 페이지가 열린 다음에는 이렇게 바뀌게 된다.

http://localhost/CookielessSessionWebSample/(mkwgif552tavi2vtxhgq1a45)/Webform1.aspx

위의 URL에 가운데 부분에 이상하게 끼어든 (mkwgif552tavi2vtxhgq1a45)이 바로 쿠키의 SessionID의 역할을 하는 것이다. 즉 쿠키를 쓰는 대신에 URL에 세션ID를 넣어서 사용한다고 생각하면 되겠다.

두번째로 바로 위 사실 때문에 몇가지 제약 사항이 발생한다. Server.Transfer와 Response.Redirect 등을 사용할 때, Root로부터 시작하는 URL 즉 이런 형태 - /RootDir/Somepage.aspx - 를 사용하지 못하며, Full URL - http://ServerName/RootDir/Somepage.aspx - 를 또한 사용하지 못한다. 이 사실은 EggHeadCafe라는 사이트의 한 게시물에서 알게 되었다.

첫번째 문제가 Accept된다면, 사실 대부분의 경우 큰 문제는 없을 것이다. 두번째처럼 만약 코딩을 했다는 것은, 사실 코딩 상에 문제가 있는 거라고 봐야 하니까. 그런데 내 경우는 우리 회사의 솔루션에 저런 것이 없다고 장담하기가 힘들었다는 것이다. 그래서, 우리 솔루션의 경우는 쿠키의 세션ID는 허용하는 방향으로 가기로 했다.

하지만, 쿠키를 완전히 사용할 수 없는 경우가 발생한다면, Cookie-less Session은 매우 좋은 선택이 될 것이다. 그리고 이 Cookie-less Session을 사용한다면 위에서 언급한 코딩상의 주의 사항은 반드시 지켜야 할 것이다.

Posted by kkongchi
asp.net2006. 11. 19. 01:19


특정 폴더에 있는 이미지를 웹 화면에 출력해야 하는데, 그 폴더를 웹 가상 디렉토리로 만들기가 힘든 상황이 있을 수가 있다. 아무래도 웹 가상 디렉토리로 노출되는 것은 보안에 문제가 있을 수 있다는 것을 의미하고, 그 폴더가 이미지 외에도 많은 내부 자료들이 들어있는 공용 스토리지라면 가상 디렉토리로 만드는 것은 좋지 않은 선택이다.

이럴 때, 이미지 파일을 읽어서 웹 화면에 출력해줄 수 있는 ASPX 웹 페이지 코드를 소개한다. 아래 코드는 서버의 파일명을 파라미터로 받아서, 그 파일을 이미지 형태로 웹 화면에 출력하는 코드이다.

일단, ASPX 페이지에는 아무런 HTML 코드가 없어야 한다. 아래와 같이 ASPX 페이지 지시자만 놔두고 모두 삭제하도록 한다.

<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %>

비하인드 코드는 다음과 같다. 아래 코드는 Page_Load 이벤트 핸들러에 두면 된다.

System.Byte[] arrBytes = null; //파일을 바이트로 읽기 위한 변수를 선언
string fileName = null; //파일명을 받을 변수 선언

try
{
  Response.ContentType = "image/jpeg" //Content Type을 반드시 image/jpeg 혹은 image/gif 등의 image 유형으로 지정해야 한다.
  fileName = Request["FileName"];

  if (!String.IsNullOrEmpty(fileName)) //파일명이 전달되지 않았을 때의 분기
  {
   arrBytes = new System.Byte[1000000]; //바이트를 넉넉하게 지정하자. 이 크기가 파일보다 작다면 에러가 발생한다.
   System.IO.FileStream fs = null; //파일을 읽기 위해 파일스트림 선언
   string filePath = fileName;
   string defaultFilePath = "c:\\camels.jpg" //파일이 존재하지 않을 때 사용할 이미지
   if (System.IO.File.Exists(filePath))
   {
     fs = new System.IO.FileStream(filePath, System.IO.FileMode.Open, System.IO.FileAccess.Read, System.IO.FileShare.Read);
   }
   else
   {
     fs = new System.IO.FileStream(defaultFilePath, System.IO.FileMode.Open, System.IO.FileAccess.Read, System.IO.FileShare.Read);
   }

   fs.Read(arrBytes, 0, 1000000);
   fs.Flush();
   fs.Close(); //파일스트림객체는 사용한 후에 반드시 해제해야 한다.

   Response.Clear();
   Response.OutputStream.Write(arrBytes, 0, arrBytes.Length); //웹 Response에 파일을 직접 쓴다. 이로써 이미지가 출력된다.
  }
  else
  {
   throw new Exception("파일명이 지정되지 않았습니다");
  }
}
catch (Exception ex)
{
  Response.Write(ex.ToString());
}


이 ASPX 페이지는 다음과 같이 사용하면 된다.

<img src="default.aspx?FileName=C;\\Camels.jpg"/>


사실, 이렇게 이미지를 웹 페이지로 출력하는 방법은 그렇게 좋은 방법은 아니다. 사실은 HttpHandler를 사용하는 것이 더 좋다. HttpHandler를 사용하는 방법은 Dino EspositoImage Generation Service for ASP.NET 1.1를 참조하기 바란다.

그리고, 위 샘플 코드는 파일 경로가 GET 파라미터로 완전히 보이기 때문에 그냥 사용하면 안된다. 적어도 파일 명 앞의 경로는 Config 파일에 두는 방법을 사용하길 바란다.

Posted by kkongchi