문제

저는 클라이언트-서버 채팅 애플리케이션을 디자인하고 있습니다(사실 저는 그렇지 않지만 그렇다고 가정하겠습니다 :)). 제가 경험한 몇 가지 경쟁 조건 때문에 약간 당황스럽습니다.

다음 코드가 있다고 가정해 보겠습니다.

public interface IServer
{
  [OperationContract(IsOneWay = false)]
  [FaultContract(typeof(ChatException))]
  void BroadcastMessage(string msg);
}

public class Server : IServer 
{
  void BroadcastMessage(string msg) // I'm not mentionning the try/catch/throw FaultException here for readability purposes
  {
    foreach (IClientCallback c in callbacks){
      c.ReceiveMessage(msg);
    }

  }
}

public interface IClientCallback
{
  [OperationContract(IsOneWay = true)]
  void ReceiveMessage(string s);
}

다음은 바인딩 구성의 일부입니다.

<endpoint address="" 
binding="netTcpBinding" 
bindingConfiguration="DuplexBinding" 
contract="IServer" />

 <binding name="DuplexBinding" sendTimeout="00:01:00">
   <reliableSession ordered="true" inactivityTimeout="00:05:00" enabled="true"/>
   <security mode="None">
     <transport clientCredentialType="Windows" protectionLevel="EncryptAndSign" />
     <message clientCredentialType="Windows" />
   </security>
 </binding>

이것은 물론 일종의 의사 C#이므로 명확성을 위해 관련 없는 코드를 많이 제거했습니다.

이제 요점은 다음과 같습니다.이 코드는 작동하지 않습니다.BroadcastMessage를 호출하면 메서드가 반환되지 않고 결국 클라이언트 측에서 시간 초과가 발생합니다.서버 측에서 디버깅하면 모든 것이 괜찮아 보입니다. (예상한 대로 정확히 BroadcastMessage 메서드에서 반환되며, 어떠한 ReceiverMessage 단방향 호출도 차단하지 않습니다.)

이 코드를 수정하는 두 가지 방법은 다음과 같습니다.

  1. FaultContract를 제거하고 BroadcastMessage 메서드를 oneway=true로 선언합니다.
  2. 최초 발신자를 제외한 모든 사람에게 메시지를 브로드캐스트합니다.

내 첫 번째 추측은 클라이언트 측이 서버가 반환되기를 기다리고 있었기 때문에 서버에서 들어오는 ReceiverMessage 호출을 처리하는 데 사용할 수 없었기 때문에 서버를 차단했지만 ReceiverMessage는 단방향으로 선언되었으며 서버를 디버깅하면 다음과 같이 표시됩니다. ReceiverMessage에 대한 호출은 차단되지 않습니다.

이제 내 질문은 다음과 같습니다.

  • 무슨 일이야?

  • 이 문제를 해결하는 다른 방법이 있나요?(어쩌면 바인딩 구성을 조정하여?)

  • 수정 2(즉, 발신자에게 다시 브로드캐스트하지 않음)를 선택한다고 가정해 보겠습니다. 내가 BroadcastMessage 호출이 완료되기를 기다리는 동안 서버가 내 ReceiverMessage 콜백을 호출하면(다른 사람이 나에게 메시지를 보냈기 때문에) 어떻게 될까요?

  • OneWay 호출이 완전히 단방향이 아니며 서버가 여전히 상대방의 HTTP 응답을 기다리고 있다는 내용을 읽었습니다.이에 대한 자세한 내용이 있나요?구체적으로, 클라이언트가 원격 호출에서 차단되었을 때 그러한 http 응답에 응답할 수 있습니까?

편집하다:서버측 콘솔 .net 3.5, 클라이언트측 Winforms .net 3.5

도움이 되었습니까?

해결책

아마도 동기화 컨텍스트로 인해 교착 상태처럼 들립니다.클라이언트는 무엇입니까?윈폼?WPF?WCF는 winforms 및 WPF에 대해 "UI 스레드로 전환"을 의미하는 동기화 컨텍스트를 존중합니다.당신이있는 경우 만들기 UI 스레드에 대한 차단 요청이 발생하면 게임이 종료됩니다.

UI 스레드가 들어오는 요청을 처리할 수 있도록 백그라운드 스레드에서 WCF 요청을 수행해 보세요.이것은 다음을 사용하는 것만큼 간단할 수 있습니다. ThreadPool, 아니면 어쩌면 BackgroundWorker.

다른 팁

서비스의 구체적인 구현에 이 속성을 추가해 보세요.

[System.ServiceModel.ServiceBehavior(UseSynchronizationContext=false)]
public class Server : IServer {}

둘째, WCF 추적을 켜서 WCF 구현 내부에서 슬픔을 안겨주는 일이 일어나고 있는지 확인해보세요.추적에 들어가서 발생한 실제 오류 메시지를 발견했을 때만 의미가 있는 몇 가지 정말 이상한 오류가 있었습니다.

WCF 서비스 추적

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top