.NET 런타임에 대한 실제 진입점은 문서화되지 않은 일부 클래스와 인터페이스에서 발생합니다(번역: 물론 Reflector를 사용하여 J를 볼 수 있습니다). Microsoft를 제외하고 이러한 인터페이스에 대해 아는 사람은 거의 없으며 Microsoft 직원도 관심이 없습니다. 이러한 세부 사항에 대해 이야기하는 것은 이러한 구현 세부 사항이 ASP.NET을 사용하여 응용 프로그램을 개발하는 개발자에게는 거의 쓸모가 없다고 생각합니다.
작업자 프로세스(IIS5의 ASPNET_WP.EXE, IIS6의 W3WP.EXE)는 .NET 런타임 및 ISAPI DLL을 호스팅하며, 작업자 프로세스는 COM 개체의 관리되지 않는 작은 인터페이스를 호출하고 궁극적으로 호출을 ISAPIRuntime 클래스로 보냅니다. 인스턴스에 대해(주석: 원문은 ISAPIRuntime 클래스의 인스턴스 하위 클래스이지만 ISAPIRuntime 클래스는 봉인된 클래스이므로 작성자의 사무적인 오류로 의심되거나 여기서 하위 클래스가 하위 클래스를 의미하지는 않습니다.) 런타임 항목은 문서화되지 않은 이 클래스가 IISAPIRuntime 인터페이스를 구현합니다(호출자 사양의 경우 이 인터페이스는 COM 인터페이스임). IUnknown을 기반으로 하는 이 기본 COM 인터페이스는 ISAPI에서 ASP.NET으로 확장된 미리 결정된 인터페이스입니다. 인터페이스 및 해당 호출 서명(Lutz Roeder의 뛰어난 .NET Reflector 도구 http://www.aisto.com/roeder/dotnet/ 사용)은 이 단계별 프로세스를 탐색하는 좋은 방법입니다.
그림 3 - 이 인터페이스를 더 자세히 살펴보려면 Reflector를 열고 System.Web.Hosting 네임스페이스를 가리킵니다. ISAPI DLL은 호스팅된 COM 인터페이스를 호출하여 ASP.NET에 대한 액세스를 엽니다. ISAPI ECB를 가리키는 링크입니다. 이 ECB에는 요청을 수신하고 응답을 IIS로 다시 보내는 데 사용되는 전체 ISAPI 인터페이스에 액세스하는 기능이 포함되어 있습니다
. (IIS6에서 직접 관련됨) (IIS5의 명명된 파이프를 통해) 이 클래스를 살펴보면 다음 서명이 있는 ProcessRequest 함수를 찾을 수 있습니다:
[return: MarshalAs(UnmanagedType.I4)]
int ProcessRequest([In] IntPtr ecb,
[In, MarshalAs(UnmanagedType.I4)] int useProcessModel)
ecb 매개변수는 ISAPI 확장 제어 블록(확장 제어 블록)으로 ProcessRequest 함수에 관리되지 않는 리소스로 전달됩니다. 요청 및 응답 개체와 함께 사용되는 기본 입력 및 출력 인터페이스입니다. ISAPI ECB에는 서버 변수, 양식 변수에 대한 입력 스트림, 클라이언트에 데이터를 다시 쓰기 위한 출력 스트림과 같은 모든 하위 수준 요청 정보가 포함되어 있습니다. ISAPI 요청으로 액세스할 수 있는 리소스에 액세스하기 위한 모든 기능은 관리 코드에 대한 이 리소스(ecb)의 초기 진입점 및 종료점입니다.
이 모드에서 ISAPI 확장은 요청을 즉시 반환합니다. 그러나 ECB는 현재 요청의 수명 동안 계속 사용할 수 있습니다. ECB에는 요청이 처리되었음을 ISAPI에 알리는 메커니즘이 포함되어 있습니다(ecb.ServerSupportFunction 메서드를 통해)(주석: 추가 정보) , ISAPI 확장 개발에 대한 문서를 참조하세요. 이 비동기 처리 방법은 ISAPI 작업자 스레드를 즉시 해제하고 ASP.NET에서 관리하는 별도의 스레드에 처리를 전달하여 ecb
에 대한 참조를 받습니다
.서버 변수 및 POST 데이터와 같은 현재 요청에 대한 정보를 수신하기 위해 내부적으로 사용합니다. 또한 요청이 완료되거나 제한 시간이 만료될 때까지 ecb는 액세스 가능한 상태로 유지됩니다. 요청 처리가 완료될 때까지 계속해서 통신합니다. 출력은 ecb.WriteClient()를 사용하여 ISAPI 출력 스트림에 기록되고 요청이 완료되면 ISAPI 확장에 알림이 전송되고 ECB가 해제됩니다.
.NET
클래스는 본질적으로
효율적이고 관리되지 않는 ISAPI ECB를 둘러싼 매우 "얇은" 래퍼이기 때문에 이 구현은 매우 효율적입니다.
.NET 런타임이 로드되었습니다. 여기서는 이 프로세스에 대한 문서를 찾지 못했고 기본 코드에 대해 이야기하고 있으므로 ISAPI DLL을 디컴파일할 수 있는 좋은 방법이 없습니다. 알아내십시오(.NET 런타임을 로드하는 코드).
제가 할 수 있는 가장 좋은 추측은 ISAPI 확장이 ASP.NET에 매핑되는 확장에 대한 첫 번째 요청을 받으면 작업 프로세스가 .NET 런타임을 로드한다는 것입니다. 런타임이 존재하면 관리되지 않는 코드는 지정된 가상 디렉터리에 대한 ISAPIRuntime 인스턴스가 아직 존재하지 않는 경우 이를 요청할 수 있습니다. 각 가상 디렉터리에는 독립 애플리케이션(ASP.NET 프로그램 참조)이 있는 경우 자체 애플리케이션 도메인(AppDomain)이 있습니다. ISAPIRuntime은 시작 프로세스부터 항상 애플리케이션 도메인에 존재했습니다. 인스턴스화(주석: ISAPIRuntime의 인스턴스화를 참조해야 함)는 COM을 통해 수행되는 것 같습니다. 이는 인터페이스 메서드가
처음 실행될 때
COM 호출 가능 메서드로 노출되기 때문에 수행됩니다.가상 디렉터리에 대한 요청이 오면 System.Web.Hosting.AppDomainFactory.Create() 함수가 호출되어 ISAPIRuntime의 인스턴스를 만듭니다. 이렇게 하면 응용 프로그램의 시작 프로세스가 시작됩니다. 이 호출은 응용 프로그램의 유형, 모듈 이름 및 가상 디렉터리 정보를 받습니다. HttpRuntime 인스턴스(주석: 원본 텍스트는 이 HttpRuntime 파생 개체이지만 HttpRuntime은 봉인된 클래스로 의심됩니다. 원본 텍스트에서는 오류임)은 새 응용 프로그램 도메인에서 생성됩니다. 각 가상 디렉터리(즉, ASP.NET 응용 프로그램이 호스팅됨)는 별도의 응용 프로그램 도메인에서 호스팅되며 특정 ASP가 실행될 때만 로드됩니다. .NET 프로그램이 요청됩니다. ISAPI 확장은 이러한 HttpRuntime 개체의 인스턴스를 관리하고 요청된 가상 디렉터리를 기반으로 내부 요청을 올바른 HttpRuntime 개체로 라우팅합니다.
그림 4 - ISAPI 요청은 문서화되지 않은 일부 클래스, 인터페이스 및 많은 팩터리 메서드 호출을 사용하여 ASP.NET의 HTTP 파이프라인으로 전송됩니다. 각 웹 응용 프로그램/가상 디렉터리는 자체 응용 프로그램 도메인에서 실행되며 호출자(주석: ISAPI DLL)는 참조를 유지 관리합니다. ASP.NET 요청 처리를 트리거하기 위해 IISAPIRuntime 인터페이스에 연결합니다.