2012-07-29 5 views
17

지난 주에 조사한 문제로 해결 방법을 찾지 못했습니다. 동일한 질문을하지만 답변을 얻지 못한 게시물을 찾았습니다. 다른 사람들에게도 도움이되기를 바랍니다.스트림을 종료하지 않고 WCF 서비스에서 중단하는 방법은 무엇입니까?

WCF 서비스 내에 stream이 포함 된 개체를 반환하는 서비스가 있습니다. 나는 basicHttpBinding을 사용하여 스트리밍 전송 및 Mtom을 클라이언트에 전송합니다.

클라이언트는 WCF 서비스를 호출하고 응답 개체를받은 직후 프록시를 닫습니다.

다음으로 클라이언트는 WCF 서비스에서 가져온 스트림을 읽고 로컬 디스크의 파일에 기록합니다. 이 모든 것은 잘 작동합니다.

제 문제는 클라이언트가 작업을 중단하고 WCF 서비스에서 데이터 다운로드를 중단하려는 경우입니다. 스트림에서 .close()을 호출하면 (예 : serverReply.DataStream.Close();) WCF 서비스에서 스트림이 끝날 때까지 전체 스트림을 차단하고 읽습니다. 스트림이 상당히 클 수 있으며 네트워크가 항상 빠르지는 않습니다.

이것은 네트워크 리소스 사용에 대해 매우 바람직하지 않습니다.이 리소스는 더 이상 사용하지 않는 데이터에 기본적으로 낭비됩니다. basicHttpBinding은 WCF 서비스 서버에 두 개의 동시 TCP 연결 만 허용하므로 기본적으로 스트림이 끝날 때까지 다른 연결 시도를 차단합니다.

동시 연결 수를 늘릴 수는 있지만 문제 해결을위한 여지가 있기 때문에 문제가 될 수 있습니다.

예를 들어, 20 개의 다운로드가 중단되어 데이터를 다운로드하는 중입니다. 송금을 완전히 중지해야합니다.

클라이언트에서 스트림 개체는 보통 Stream 클래스이므로, 닫기 메서드 만 있고 다른 것은 없습니다.

프록시 개체에 .close() 또는 .abort()을 호출해도 도움이되지 않으며 .dispose() 또는 다른 방법을 사용하여 프록시를 파괴하지도 않습니다. 서버 쪽에서는 OperationContext.OperationCompleted 이벤트를 처리하지만 stream의 데이터가 끝까지 읽힐 때까지는 발생하지 않습니다.

그렇다면 완전히 스트림을 닫지 않고 스트림을 닫거나 중단하려면 어떻게해야합니까?

+0

행운이 있나요? – Schultz9999

+0

정말 큰 파일을 보내는 동안 같은 문제가 발생했습니다 ... 정말 분명한 것을 놓치고있는 것처럼 보입니다. 해결 방법으로 청킹을 구현해야 할 것입니다. –

답변

0

binding.MaxBufferSize을 가지고 놀았습니까?

<bindings> 
    <wsHttpBinding> 
    <binding name="default" maxReceivedMessageSize="2147483647" maxBufferPoolSize="2147483647" 
      closeTimeout="00:01:00" openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00" > 
     <readerQuotas maxArrayLength="2147483647" maxBytesPerRead="4096" maxNameTableCharCount="16384" 
        maxDepth="64" maxStringContentLength="2147483647" /> 
    </binding> 

    </wsHttpBinding> 
</bindings> 

나는 ANF 버퍼 길이 시간 제한을 최소화하고 중단 시도하거나 가까이 어떻게 볼 것입니다 :
는 예컨대 당신의 app.config 파일 설정으로 장난 노력했다.

+1

나는 그것을 시도했지만 도움이되지 않습니다. 일단 서버가 스트림 전송을 시작하면 모든 것이 클라이언트에 수신 될 때까지 중지되지 않습니다. 프록시를 닫는 것은 아무 것도하지 않습니다. 의사 소통을 중단시킬 명백한 방법이없는 것 같습니다. 클라이언트가 스트림 읽기를 중단하면 tcp window zero가 서버로 돌아가는 것을 볼 수 있습니다. 그리고 서버는 클라이언트가 다시 읽을 준비가되었는지 확인하기 위해 주기적으로 윈도우 제로 프로브를 전송합니다. 그리고 물론 클라이언트는 창 제로를 다시 보냅니다. 이것은 프로세스가 종료 될 때까지 계속됩니다. – Yev

+0

HttpClient 클래스 만 사용하여 스트림을 읽으려고 시도 했습니까? 스트림을 닫을 수 있는지 확인 했습니까? –

+0

WCF 서비스를 호출하지 않고 어떻게 할 수 있습니까? 좀 더 조사를 해봤는데 클라이언트 측에서 스트림을 닫을 방법이 없다고합니다. 다른 접근 방식을 시도했습니다. 다른 서비스 인 제어 서비스를 만들고 거기에서 스트림을 닫으려고했습니다 (서버 쪽). 그러나 운이 없다. 무언가가 작동하지 않습니다. 닫히지도 처분되지 않습니다. – Yev

1

조사한 결과, closeTimeout이 만료 될 때까지 WCF 클라이언트가 스트림에서 계속 읽는 것으로 나타났습니다. 그러면 연결이 중단됩니다. 문제를 최소화하기 위해 클라이언트에서 closeTimeout을 줄일 수 있습니다.

참고 : 스트림을 try/catch 블록에 배치하는 코드를 래핑해야합니다. stream.Dispose() 메소드는 not throwing exceptions in Dispose method의 가이드 라인을 제동하는 TimeoutException을 발생시킵니다.

0

나는 닫은 후에 버퍼를 수신 중일 뿐이라고 생각합니다. maxBufferSize를 더 낮은 값으로 설정해야합니다.

스트림을 랩핑하고 읽기를 무시하여 서버에서 읽는 데이터의 양을 제한하고자 할 수도 있습니다. 낮은 대역폭 클라이언트를 사용하는 경우 작은 청크를 사용하고 실제로 읽은 값과 일치하도록 읽기 방법에서 해당 개수를 반환하십시오. 이렇게하면 버퍼의 채우기 속도가 제한됩니다.

이 주제에 대한 내 자신의 테스트는 NeverEndingStream을 작성하고 항상 데이터를 반환하는 것과 관련이 있습니다. 어떤 시점에서 클라이언트에서 close를 호출하면 거의 즉각 close가 서버에서 호출되었습니다. 이것은 버퍼가 끝날 때까지 스트림을 읽을 수 없으므로 버퍼가 비게되었다는 것을 의미합니다.

여전히 문제가 발생하면 재정의 한 스트림에서 Read 메서드의 타이밍을 추적하는 것이 좋습니다. currentReadtime - lastReadTime이> x 인 경우 대신 Close를 호출하고 예외를 throw 할 수 있습니다. 그것은 그것을 확실히 죽일 것이다.