IT 이모저모

C # 역방향 레시피 - 2

exien 2018. 3. 6. 17:40

254 자체 서명 인증서를 사용하는 Web 서버에 HTTPS를 통해 액세스 할

AuthenticationException를 직접 확인하는 방법

 HTTPS는 연결을 시작할 때 서버 제시 한 서버 인증서의 유효성이 검증됩니다. 이 때 서버가 제시 한 인증서의 유효성을 확인할 수없는 경우 (즉, 서버가 올바른 연결이라고 인정되지 않는 경우) WebException (내용은 AuthenticationException)가 발생되어 통신에 실패합니다.

 System.Net.ServicePointManager 클래스의 ServerCertificateValidationCallback 정적 이벤트 콜백을 등록하면 .NET Framework에 의한 검증 후 자신의 검증 처리를 추가 할 수 있습니다.

연결 대상 호스트가 제시 한 인증서의 지문이 알려진 것이라면 연결 허용
using System ; using System . IO ; using System . Net ; using System . Net . Security ; class VerifyTestCert { // 알려진 테스트 인증서의 지문 const string ExpectedFingerprint = "4F-F6-5E-E3-CE-B0- 99-BD-68-6D-ADBA-EC-16-B8-D1-5C-30-75-6A " ; 
 
 
 
 

 
     

 // 정적 생성자에서 ServicePointManger 콜백을 설정하는 static VerifyTestCert () { // ServerCertificateValidationCallback는 .NET Framework에 의한 검증 후 // 호출하여 검증 결과를 무시할 수 ServicePointManager . ServerCertificateValidationCallback = // cert는 X509Certifacte 클래스 객체 // chain은 X509Chain 클래스의 객체 // sslPolicyErros는 SslPolicyErrors 열거 형 // true를 반환하고 연결 처리가 계속된다. false를 반환과 // WebException이 throw되는 ( sender , cert , chain , sslPolicyErros ) => { if ( sslPolicyErros == SslPolicyErrors
  
  
   
    
    
    
    
    
    
      
       . None ) { // .NET Framework에서 정책 오류가 발견되지 않으면 OK return true ; } // 오류에도 인증서 해시가 기존의 지문과 // 일치하고 있으면 OK라고하는 return ExpectedFingerprint == BitConverter . ToString ( 
      cert . GetCertHash ()); }; } static void Main ( string [] args ) { // 인수로 연결을 바꾸는 var request = WebRequest . CreateHttp ( args [ 0 ]);
      
        
     
     
     
        
   
 
   
  
   
  request . UserAgent = "sample web client" ; 
  request . Accept = "* / *" ; using ( WebResponse response = request . GetResponse ()) using ( var reader = new StreamReader ( response . GetResponseStream ())) { Console . WriteLine ( reader . ReadToEnd ()); } } }    
   
     
  
   
  
 

"시험을 행할 때,이 요리법을 알아두면 의외로 편리합니다"

제 16 장 프로세스와 스레드

286 지정된 시간 처리를 중지하려면

Task.Delay 정적 메소드를 이용하면

 연속 작업을 수행하는 데 문제가 있기 때문에 일시적으로 처리를 중단하고 싶은 것이 있습니다.

 예를 들어, 웹 스크래핑하는 경우에는 연속해서 데이터를 검색하면 서비스 거부 공격으로 간주 될 수 있습니다. 따라서 인간이 브라우징 할 때와 마찬가지로 몇 페이지 액세스 했더니 몇 초 간격을두고 있습니다.

 이러한 경우에는 Task.Delay (밀리 초)을 이용합니다. Task.Delay는 .NETFramework 4 이상 유효하므로 그 이전 버전에서는 Thread.Sleep (밀리 초)을 이용하여 정지합니다. 이 두 API의 차이는 Thread.Sleep이 그대로 호출 한 스레드 자체를 휴면 상태로하는 반면 Task.Delay은 실행중인 스레드를 다른 프로세스에 할당 할 수있는 상태로하는 것입니다. 따라서 Task.Delay 쪽이 스레드를 점유하지 않는 분 효율적입니다.

Web 서버에 액세스 간격을 1 초 간격으로하는
static async Task ReadFromWeb ( string root ) { using ( var client = new HttpClient ()) { foreach ( var uri in GetLinks ( root , await client . GetStringAsync ( root ))) { Console . Write ( uri ); // Web 서버 에서 uri를 얻을 var response = await client . GetAsync ( 

    
 
    
  
   
   
   uri ); Console . WriteLine ( $ "... {response.StatusCode}" ); 
   await Task . Delay ( 1000 ); // 최소 1 초 동안이 스레드를 개방 } } }
    
  
 

"이 방법을 알고에서 Thread.Sleep을 쓸 때 손이 떨리고 있습니다. 이것은 자원의 낭비 뭐야, (웃음)"

제 17 장 예외 처리

293 특정 속성 값을 가진 예외 만 잡으려면 (예외 필터를 사용하고)

catch와 when을 이용하기

"catch (예외 형 변수 이름)"에 이어 "when (조건)"를 작성하면 catch 절에서 지정한 예외의 형태로하고 when 절에서 지정한 조건에 일치하는 catch 블록이 실행됩니다.

인서트 결과에 따라 예외를 상위에 보낼지 여부 결정
try { 
 cmd . ExecuteNonQuery (); // insert table의 실행 return InsertSucceeded ; } catch ( SQLException e ) when ( e . Number == 2601 ) { return RetryByUpdate ; // 호출 한 메소드에 update 문을 준비시키는 } // Number 속성이 2601 이외 SQLException은 상위에 전파된다
 
  

     

   

"C # 7 형식에 따라 처리를 분기하는 패턴 매칭이 도입 될 예정 들었 기 때문에, Elixir 패턴 매칭 작성을 닮은 것도 있고, catch when 기술을 유용하고 비슷한 구문에서 실현하는 것이 아닐까 예측하고 있으면 조금 빗나가 버렸습니다.하지만 catch를 사용하고있는 사람이라면 이미 패턴 매칭 예습 수 있기 때문에 안심하고 C # 7 패턴 매칭을 활용할 수 있네요 "

제 18 장 메타 프로그래밍

299 필드 이름을 지정하여 필드에 액세스하려면

FieldInfo 개체를 얻을 수 있으며 GetValue / SetValue 메소드를 이용하면

 객체의 필드를 취득 / 설정하려면 개체 유형 (Type 클래스의 객체)의 GetField 메서드를 호출하여 얻은 FieldInfo 개체의 GetValue / SetValue 메서드를 사용합니다.

필드에 액세스하기
class Test { public int counter = 3 ; internal string name = "abc" ; public static readonly string classDesc = "xyz" ; } ... var test = new Test (); // public 필드는 Type.GetField에 필드 이름 을주는 var counter = typeof ( Test ) GetField ( "counter" ); // 비 public 필드는 제 2 인수에 BindingFlags.NonPublic | BindingFlags.Instance 

   
   
     


  

 

//을주는 var name = typeof ( Test ) GetField ( "name" , BindingFlags . NonPublic | BindingFlags . Instance ); // 필드 값을 검색하려면 FieldInfo.GetValue 대상 개체를 제공 Console . WriteLine ( $ "{counter.GetValue (test)}, {name.GetValue (test)}" ); // 필드에 값을 설정하려면 FieldInfo.SetValue 대상 개체와 가치를 부여 
counter . SetValue ( test , 48 ); 
name . SetValue ( test
 
    


 , "ABC" ); Console . WriteLine ( $ "{test.counter}, {test.name}" ); // public 필드는 Type.GetField에 필드 이름을 준다 (정적 필드인지는 불문) var classdesc = typeof ( Test ) GetField ( "classDesc" ); // 정적 필드의 FieldInfo.GetValue / SetValue의 제 1 인수는 null를 제공 
classdesc . SetValue ( null , "XYZ" ); // readonly 여부는 관계 하지 Console . WriteLine ( Test . classDesc ); 


 
 

 // => XYZ (readonly는 컴파일시의 제약 때문에 영향을주지 않는다)

"이전의 레시피 (026)에서 readonly로 수식 필드는 다시 할당 할 수 없기 때문에 안전하다고 말하면서,이 제조법은 readonly도 바뀐다 고합니다 (웃음). 스스로 자신의 머리에서 다리로 쏘 빠지는 구조를 가지고 언어는 프로그래머를 신뢰하는 기분 좋은 언어 네요. 그것을 할 수없는 언어는 기분으로도 실제적으로도 조금 모자 름입니다 "

제 19 장 프로그램 개발 지원

306 디버그 (추적) 출력을 파일로 내보내려는

Listeners 속성에 청취자를 설정하기

 Debug 클래스 Trace 클래스의 WriteLine은 WriteLineIf 등의 메소드 대상은 각 클래스의 Listeners 속성에 추가 된 청취자에 의해 결정됩니다.

 기본 리스너는 Windows API를 OutputDebugString 함수를 호출 DefaultTraceListener가 설정되어 있습니다.

 이 설정은 구성 파일 (.exe.config)에서 변경할 수 있습니다.

구성 파일에서 추적 출력 파일을 지정하는
<configuration> <system.diagnostics> <! - 요소 이름은 trace하지만 Debug 클래스 수신기도 설정된다 -> <trace autoflush = "false" > <listeners> <remove name = "Default" > <! - C : \ temp ¥ traceOut.log에 출력하는 TextWriterTraceListener를 설정

  
    
   
      
    
     name 속성은 뭐든지 좋은 (청취자의 Name 속성에 설정) -> <add initializedata = "c : ¥ temp ¥ traceOut.log" name = "fileListener" type = "System.Diagnostics.TextWriterTraceListener" > <! - - 콘솔 (표준 출력)에 추적 출력하려면 다음 설정을 사용하는
       
    
     <add name = "consoleListener"type = "System.Diagnostics.ConsoleTraceListener"/>
    -> </ add> </ trace> </system.diagnostics>
   
  
 

"이번에 꽤 잘 조사한 결과가 반영되어있는이 조리법이다. 이렇게 주면 좋을지 기뻐할 것이 많은 것이 아닐까요. 저도 이것을 발견했을 때 너무 기뻤어요 "

제 20 장 Windows 환경

315 이벤트 로그에 쓰고 싶다

이벤트 로그에 출력하는 방법

 이벤트 로그에 출력하려면 다음 단계를 취합니다.

  1. 제 1 인수에 응용 프로그램 이름, 제 2 인수에 로그 파일 이름을 지정하고 CreateEventSource 정적 메서드를 호출하여 프로그램을 등록합니다. 제 2 인수를 null로하면 Application 로그에 출력됩니다.
  2. EventLog를 new로 객체를 만듭니다.
  3. (2)에서 만든 EventLog 개체의 Source 속성 (1)에서 지정한 응용 프로그램 이름을 설정합니다.
  4. (2)에서 만든 EventLog 개체 WriteEntry 메서드를 호출하여 로그를 출력합니다.

이벤트 로그 출력 단계에 대한주의 사항

 EventLog.CreateEventSource 및 미등록시 SourceExists 실행하려면 관리자 권한이 있어야합니다. 이것은 액세스하려면 관리자 권한이 필요한 Security 로그를 포함한 모든 로그를 검색하여 동일한 이름이 출현하고 있지 않은지 확인하는 것입니다. 그래서 사용자 권한에서 실행되는 프로그램 내용은 위의 (1)의 처리는 다른 처리와 별도로 설치 등으로 제공하는 것이 좋습니다.

 일단 응용 프로그램 이름을 등록하면 이후 Security 로그 이외에 대해서는 사용자 권한으로 쓰기가 가능합니다.

이벤트 로그에 기록
// using System.Diagnostics;가 필요 const int IOErrorEvent = 101 ; // EventID (정수) const short CatOperationFailed = 10 ; // 카테고리 (정수) ... if (! EventLog . SourceExists ( "EvLogTest" )) // 응용 프로그램 이름이 미등록이면 등록 { // Application 로그를 이용하는 경우, 제 2 인수는 null이된다. 그렇지 않으면 로그 이름을 지정 EventLog . CreateEventSource ( "EvLogtest" , null ); // CreateEventSource 정적 메소드는 관리자 권한이 있어야 실행할 수 없다 }
     
    

  
 
   
  

// 로그 쓰기 오류 발생은 드문 경우라는 전제에서 EventLog는 using로 둘러싸 using ( var log = new EventLog ( )) { 
  log . Source = "EvLogTest" ; // CreateEventSource에 등록 된 응용 프로그램 이름을 설정 // 문자열만을주는 정보 수준의 쓰기 연산 
  log . WriteEntry ( $ "IO Error {errorNumber}" ); // EventLogEntryType 열거 형 문자열 및 이벤트 로그 종 (오류, 경고 및 정보)를 지정 
  log . WriteEntry ( $ "IO Error {errorNumber}" , EventLogEntryType . Error );
     
   
  
   
  // int 형의 제 3 인수로 응용 프로그램 정의 이벤트 식별자를 쓸 // 2 인자 다음의 호출은 0이된다 
  log . WriteEntry ( $ "IO Error {errorNumber}" , EventLogEntryType . Error , IOErrorEvent ); // short 형태의 제 4 인수로 응용 프로그램 정의 로그의 카테고리를 지정할 수 // 3 인수 다음 호출은 '없음'이 될 
  log . WriteEntry ( "start EvLogTest app" , EventLogEntryType . Information , IOErrorEvent , CatOperationFailed ); }
   
          
  
   
          

"Win32API를 사용하여 이벤트 로그를 출력하는 것은 의외로 귀찮은입니다. 메시지의 템플릿을 포함하는 DLL을 준비하여 미리이를 사용하도록 등록 해 두지 않으면 안됩니다. 그렇지 않으면 이벤트 로그에 "메시지의 세부 정보를 찾을 수 없습니다"라는 오류 메시지가 나옵니다. 그런데 .NET Framework에는 기본 템플릿이 준비되어 있어요. 이것은 굉장히 도움이됩니다 .Win32API 번거 로움으로부터 이벤트 로그 를 외면하고, .NET Framework에서는 잘 해줄 수있게되어 있다고 깨닫지군요 "

편리 해져가는 C #을 잡을 계속하는 것이 중요

"C # 자꾸 자꾸 쓰고 쉽게되어 있기 때문에 변화를 따라 잡을 가세요 .C # 1의 경우 기억 한 것 이외는 인정하지 않는다는 것은 어리석은하고 잡을 않아도 제대로 움직 이니까 OK라고 도 다릅니다. 만약 직장에서 개발을하고 있다면, 새로 들어온 사람의 작성을 따라갈 수 없게되거나 사내에서 정해져있는 오래된 쓰는 법을 규칙으로 강제하는 것입니다. 모두 곤란 하죠 .

arton 씨
arton 씨

 적어도 C # 4까지 작성, 즉 람다 식을 이용한 쓰기는 이해하고 사용할 수있게합시다. 비동기 처리하면 갑자기 C # 5 async / await에서 들어가는 것도 있습니다입니다, 최신 C # 6 세부적으로 개선되고 있습니다. 분명히 내가 C # 7는 더 잘 될 것입니다. 물론 항상 옳은 것은 아니고, 지적하려고 생각하면 C # 2의 익명 메소드 나 C # 3의 SQL 구문처럼 빌어 먹을 것도 있습니다. 그러나 그러한 것은 익명 메소드에 대한 람다 식과 같이 다음 버전에서 제대로 대안이 나올지, LINQ의 메소드 형식 + 람다 식과 같이 처음부터 있어야 것도 준비되어 있습니다. 모두 람다 식 네요. 마찬가지로이 책에서 Tuple가 편리하다고 생각 기억해서 C # 7이 등장했을 때 Tuple가 업데이트되면 책에서 얻은 지식은 이전 버전 전용으로 자르는 그런 생각을 할 수있게되어달라고 원하는 네요 "

'IT 이모저모' 카테고리의 다른 글

Barrier 란? - 1  (1) 2018.03.07
간단하고 빠른 XML 파서 : RapidXML  (0) 2018.03.06
C # 역방향 레시피 - 1  (0) 2018.03.06
수동으로 설치하는 방법  (0) 2018.03.06
사용할 수없는 UWP API  (0) 2018.03.06