2009-12-07 6 views
7

WCF에서 간단한 클라이언트 - 서버 예제를 만들고 싶습니다. 콜백을 사용하여 테스트를 수행했으며 지금까지는 제대로 작동합니다. 다음 인터페이스로 약간 놀았습니다.WCF - 클라이언트 콜백 대 "가입자 목록 유지"에 대한 폴링

[ServiceContract(SessionMode = SessionMode.Required, CallbackContract = typeof(IStringCallback))] 
public interface ISubscribeableService 
{ 
    [OperationContract] 
    void ExecuteStringCallBack(string value); 

    [OperationContract] 
    ServerInformation Subscribe(ClientInformation c); 

    [OperationContract] 
    ServerInformation Unsubscribe(ClientInformation c); 
} 

간단한 예입니다. 조금 조정. 서버가 문자열 콜백을 실행하도록 요청할 수 있습니다.이 경우 서버가 문자열을 역순환하고 가입 된 모든 클라이언트 콜백을 호출합니다.

이제, 다음과 같은 질문이 있습니다. 모든 클라이언트가 서버에 "등록"되고 서버가 클라이언트가 여전히 살아 있는지 묻는 시스템을 구현하려는 경우 콜백 (그래서이 "stringcallback"대신에 일종의 TellTheClientThatIAmStillHereCallback). 콜백에서 통신 상태를 확인함으로써 클라이언트가 죽었는지 "알 수 있습니다". 이 비슷한 :

Subscribers.ForEach(delegate(IStringCallback callback) 
        { 
         if (((ICommunicationObject)callback).State == CommunicationState.Opened) 
         { 
          callback.StringCallbackFunction(new string(retVal)); 
         } 
         else 
         { 
          Subscribers.Remove(callback); 
         } 
        }); 

내 문제, 다른 방법에 넣어 :

  • 는 서버 (필자는 노트북의 플러그를 당겨)
  • 클라이언트 A가 사망 3 클라이언트가있을 수 있습니다 서버가 종료되어 온라인으로 돌아옵니다.
  • 새 클라이언트가 나타납니다.

기본적으로 콜백을 사용하여 클라이언트의 "아직 살아있는 상태"를 확인 하시겠습니까? 아니면 폴링을 사용하고 "클라이언트에 대해 얼마나 오랫동안 들으 셨는지"추적 하시겠습니까?

+0

어떻게 WCF 서버에 연결하고 있습니까? TCP를 사용하고 있습니까? 그러면 풀링을 구현하는 방법이 바뀔 것입니다. –

답변

0

WCF 및 콜백 나는 폴링을 사용하고 싶지 않았지만, "reilable"프로토콜을 사용하고 있었다. 그래서 클라이언트가 죽으면, 타임 아웃되어 추락 할 때까지 서버를 정지시킬 것이다.

이것이 가장 정확하고 우아한 해결책인지는 모르겠지만 서비스에서 클라이언트 프록시를 나타내는 클래스를 만들었습니다. 이 클래스의 각 인스턴스에는 클라이언트 프록시에 대한 참조가 포함되어 있으며 서버가 클래스의 "message"속성을 설정할 때마다 콜백 함수가 실행됩니다. 이렇게하면 클라이언트가 연결을 끊었을 때 개별 래퍼 클래스가 시간 제한을받으며 서버의 리스너 목록에서 자신을 제거하지만 서비스는이를 기다릴 필요가 없습니다. 이것은 클라이언트가 살아 있는지 판단하는 것에 대한 질문에 실제로 응답하지 않지만, 문제를 추가하는 서비스를 구성하는 또 다른 방법입니다. 클라이언트가 언제 죽었는지 알 필요가있는 경우, 클라이언트 랩퍼가 리스너 목록에서 스스로 제거 할 때를 선택할 수 있습니다.

0

전선을 통해 WCF 콜백을 사용하지 않았지만 프로세스 간 통신에 사용했습니다. 나는 같은 스레드에서 의존하는 호출이있을 때 보내지는 호출의 호출이 같은 스레드에서 끝나고 서비스가 멈추는 문제가 발생했습니다.

현재이 문제를 해결하기 위해 수행해야하는 문제 일 수 있습니다.

는 ConcurrencyMode.Multiple는 클라이언트가 죽을 때까지 잠금 서버와 당신을 도움이 될 것 자체 스레드의 각 호 처리를하게

[ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Multiple)] 
public class WCFServerClass 

WCF 서버 구현 클래스의 서버와 클라이언트에이 속성을 넣어 시간 초과 될 때까지.

가 나는 또한 클라이언트 측에서 스레딩 문제이 없음을 확인하기 위해 클라이언트 측에서 스레드 풀을 사용하는 것이 확인했다

3

당신은을 통해 연결 상태로 대부분의 변화를 감지 할 수있는 Closed, Closing하고, Faulted 이벤트는 ICommunicationObject입니다. 콜백을 설정할 때 동시에 연결할 수 있습니다. 이것은 폴링보다 확실히 좋습니다.

IIRC의 경우 이벤트는 이후에 실제로 을 발생시킵니다 (성공적으로 콜백을 사용하지 못했습니다). 따라서 클라이언트가 사라지면 (예 : 하드 재부팅 또는 전원 끄기) 즉시 통보되지 않습니다. 그러나 당신은 있어야합니까? 그렇다면 왜?

WCF 콜백은 언제든지 실패 할 수 있으며 항상 마음 속으로이를 유지해야합니다. 클라이언트와 서버가 모두 문제가 없더라도 예외 또는 네트워크 중단으로 인해 오류가 발생한 채널로 인해 계속 발생할 수 있습니다. 또는 마지막 설문 조사와 현재 작업 사이에 클라이언트가 언젠가 오프라인 상태가되었을 수도 있습니다. 요컨대 콜백 작업을 방어 적으로 코딩하는 한 (좋은 연습입니다), 위의 이벤트를 연결하면 대개 대부분의 디자인에 충분합니다. 클라이언트가 응답하지 않는 것을 포함하여 어떤 이유로 든 오류가 발생하면 Faulted 이벤트가 클린업 코드를 실행하고 실행합니다.

이것은 수동/지연 접근 방식으로, 폴링 또는 연결 유지 방식보다 코딩 및 네트워크 채터 링이 덜 필요합니다.

+0

이것은 비슷한 기능 (어느 정도 자주 사용됨)이 필요할 때마다 수행 한 작업입니다. – kyoryu

2

안정적인 세션을 사용하도록 설정하면 WCF는 내부적으로 연결 유지 제어 메커니즘을 유지 관리합니다. 숨겨진 인프라 테스트 메시지를 통해 다른 쪽 끝이 아직 있는지를 정기적으로 확인합니다. 이러한 검사의 시간 간격은 ReliableSession.InactivityTimeout 속성을 통해 영향을받을 수 있습니다. 예를 들어 속성을 20 초로 설정하면 ICommunicationObject.Faulted 이벤트는 다른 쪽에서 서비스 고장이 발생한 후 약 20 ~ 30 (최대) 초 후에 발생합니다.

일시적으로 서비스가 중단 된 후에도 클라이언트 응용 프로그램이 항상 "자동 연결"상태로 유지되도록하려는 경우 반복적으로 새 프록시 인스턴스를 만들려고 시도하는 작업자 스레드 (스레드 풀에서)를 사용할 수 있습니다. Faulted 이벤트가 발생한 후 클라이언트 측에서 세션 시작 작업을 호출합니다.

어쨌든 작업 스레드 메커니즘을 구현 중이므로 오류 이벤트를 무시하고 클라이언트 응용 프로그램의 전체 수명 동안 작업자 스레드를 루프시킬 수 있습니다. 스레드가 반복적으로 프록시 상태를 확인하게하고 상태에 오류가 발생할 때마다 복구 작업을 시도합니다.

첫 번째 또는 두 번째 방법을 사용하면 서비스가 실행될 때마다 모든 클라이언트 응용 프로그램 인스턴스가 "자발적"서비스 메시지를 수신 할 수 있도록 서비스 버스 아키텍처 (mediator 패턴)를 구현할 수 있습니다.

신뢰할 수있는 세션 "as such as"가 세션 가능 바인딩을 사용하고 ServiceContractAttribute.SessionMode, ServiceBehaviorAttribute.InstanceContextMode, OperationContractAttribute.IsInitiating 및 OperationContractAttribute를 적용하여 올바르게 구성된 경우에만 작동합니다. 의미있는 방식으로 속성을 이스케이프 처리).