2013-03-25 2 views
1

나는 (웹 사이트에서) SSL 스트림에서 오는 모든 데이터를 화면에 표시하려고합니다. 데이터가 언제 도착할 지 모르기 때문에 바이트를 읽을 때까지 스트림에서 읽기를 계속하는 다른 스레드를 사용했습니다. 이것은 완벽하게 작동하지만 내 CPU 사용량은 25 %로 점프하고 거기에 머뭅니다 (최대 사용시 1 스레드, PC에 4 스레드 있음). 스레드가 while 루프에 걸려 있기 때문에 다소 이해가되지만, Thread 클래스의 인스턴스가 내 CPU의 전체 스레드를 소비 할 것으로 기대하지는 않습니다 (간단한 클라이언트/서버를 사용할 때 이런 일이 발생하지 않았다고 맹세 할 수 있습니다. 서버 응용 프로그램).SslStream 별도 스레드

스레드가 연결이 초기화되는 즉시 실행되기 시작하면 사용자는 원하는 언제든지 웹 사이트로 데이터를 보낼 수 있으며 응용 프로그램은 응답을 인쇄해야합니다. 이것에 대한 대안 해결책은 무엇입니까? SslStream을 삭제하고 다른 것을 사용해야합니까? 여기

이 별도의 스레드에서 실행되는 코드입니다 :

void ReadDataAsync(Object obj) { 
     byte[] buffer = new byte[65536]; //65536, make sure all bytes can be 
             //from a single packet 
     int bytesRead = -1; 

     while (true) { 
      //It makes sense for sslStream.Read to block until bytes have been 
      //read, but it doesn't. Which is why I'm checking if bytesRead!=0 

      bytesRead = sslStream.Read(buffer, 0, 65536); 

      if (bytesRead != 0) { 
       Console.WriteLine(Encoding.UTF8.GetString(buffer, 0, bytesRead)); 
       buffer = new byte[65536]; 
      } 
     } 
    } 

가 나는 당신의 도움을 주셔서 감사합니다, 당신에게 모두 감사

편집 :
내가 "로 대신하는 BeginRead 및 EndRead를 사용하여 시도 gt "제안. 이를 위해 사용자가 요청을 보낼 때마다 BeginRead를 사용합니다. 모든 데이터가 수신되면 화면에 인쇄됩니다. 이것은 잘 작동하는 것처럼 보이지만 앞으로 문제가 발생할 것인지에 대해 우려하고 있습니다. 패킷이 엉망이 될 가능성이 있습니까? 예를 들어, EndRead가 첫 번째 패킷의 끝에서 0을 반환하지 않고 두 번째 패킷을 계속 읽는 것이 가능한가? 그게 가능하다면 어떻게 해결할 수 있을까요? 받은 데이터는 http 계층의 본문 일 뿐이므로 패킷의 길이를 미리 알기 위해 IP 계층에 액세스 할 수 없습니다.

public void SendData(byte[] message) { 
     sslStream.Write(message); 
     sslStream.Flush(); 

     //Start reading for response (if not already reading) 
     if (sslStream.CanRead) { 
      sslStream.BeginRead(buffer, 0, BufferSize, ReadData, null); 
     } 
    } 

    void ReadData(IAsyncResult ar) { 
     int bytesRead = sslStream.EndRead(ar); 

     if (bytesRead > 0) { 
      //data may be on their way so start reading again 
      message.Append(Encoding.UTF8.GetString(buffer, 0, bytesRead)); 
      sslStream.BeginRead(buffer, 0, BufferSize, ReadData, null); 
      Console.WriteLine("Data received but more may be on their way..."); 
     } else { 
      //All data arrived (Checking if length is more than 0 since all the 
      //data may had already arrived in the previous check (above) 
      if (message.ToString().Length > 0) { 
       Console.WriteLine(message.ToString()); 
       //Clear StringBuilder and reset buffer. 
       message.Clear(); 
       buffer = new byte[BufferSize]; 
      } 
     } 
    } 

다시 한번 감사 while(true)은 일반적으로 나쁜 징조 ... 코드가 최종 조건없이 '꽉'루프에 들어갑니다 경우, 루핑 유지하고 모든 가능한 자원을 소모합니다 보는

답변

1

.

'if'조건이 예상 한대로 작동하는지 다시 확인하십시오. 예를 들어 스트림이 둘 이상의 파트에서 읽혀지면 어떻게됩니까? (예 : 32768의 두 부분). 이것은 전적으로 가능합니다.

문제가 해결되면 Read을 시도하기 전에 스레드를 약간 잠자기 상태로 두어 Thread.Sleep(100)을 사용하십시오.

또는 BeginRead을 사용하여 비동기 IO를 조사해보십시오. this example on MSDN을 참조하십시오.


편집, 일부에게 질문이 대답하기 :

내가 뭔가 잘못 될 수 있다면, 그것은 방어 잘못 때문에 코드 것이라는 점을 의심! 다음 문제에 대한 해결책은 스트림에서 읽은 모든 데이터를 버퍼링하는 것입니다. 그런 다음 다른 스레드가 버퍼에서 전체 패킷을 읽도록 시도하십시오. 버퍼를 동시에 읽거나 쓰지 않도록 잠금을 사용하는 것을 잊지 마십시오.

또한 '단편화 된'동작 (정상적인 동작은 물론)을 다루기 위해 단위 테스트를 작성하는 것도 좋은 생각입니다.

또는 이러한 사항을 처리하는 상위 프로토콜을 조사 할 수도 있습니다. 내가 자주 언급 한 것은 Google의 Protocol Buffers입니다.

+0

100ms 동안 잠자기하면 성능 문제가 해결됩니다. CPU 사용량이 정상 (0 %)으로 돌아 왔습니다. 나는 BeginRead와 EndRead로 당신의 추천을 시도했다. 이를 위해 사용자가 요청을 보낼 때마다 BeginRead를 사용하고 모든 데이터가 수신되면 화면에 인쇄합니다. 이것은 잘 작동하는 것처럼 보이지만 앞으로 문제가 발생할 것인지에 대해 우려하고 있습니다. 여기에 충분한 문자가 없기 때문에 내 메인 포스트를 편집 할 것입니다. 다시 감사합니다. –

+0

또한 스트림은 실제로 여러 부분에서 읽혀집니다. 그것은 패킷의 단편화 때문입니까? 위의 코드는 문제를 해결했지만 패킷이 이렇게 엉망이 될지 궁금합니다. –

+0

고마워요, 제가해야 할 일에 대한 일반적인 생각을 얻었습니다. 당신은 매우 도움이되었습니다. 도와 주셔서 감사합니다. 이것이 해결 된 것으로 표시하는 방법이 있는지 확실하지 않지만 (필자는 여기 새로 왔습니다) 필요한 모든 도움을 받았습니다. 다시 한 번 감사드립니다! –

관련 문제