私はクライアントサーバーチャットアプリケーションを設計しています(実際はそうではありませんが、私がそうであるふりをしましょう:))、そして私は私が経験したいくつかの競合状態に少し戸惑っています。
次のコードがあるとしましょう。
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メソッドから期待どおりに戻り、ReceiveMessageの片道呼び出しをブロックしていません)
このコードを修正する2つの方法があります:
- FaultContractを削除し、BroadcastMessageメソッドをoneway=trueとして宣言します
- メッセージを全員にブロードキャストしますが、最初の送信者
私の最初の推測では、クライアント側はサーバーが戻るのを待っていたため、サーバーからの着信ReceiveMessage呼び出しを処理できなかったため、サーバーがブロックされましたが、ReceiveMessageは一方向として宣言され、サーバーをデバッグすると次のようになります。 ReceiveMessageへの呼び出しをブロックしません
さて、私の質問:
どうしたの?
これを修正する他の方法はありますか?(おそらくバインディング構成を調整することによって?)
修正2を選択したとしましょう(つまり、送信者にブロードキャストしないでください)。自分のBroadcastMessage呼び出しが終了するのを待っている間に、サーバーがReceiveMessageコールバックを呼び出した場合(他の誰かが私にメッセージを送信したため)はどうなりますか?
OneWay呼び出しは完全に一方向ではなく、サーバーはまだ反対側からのHTTP応答を待機していることを読みました。これについての詳細はありますか?具体的には、クライアントは、遠隔通話でブロックされたときに、そのようなhttp応答に応答できますか?
編集:サーバー側でConsole .net 3.5、クライアント側でWinforms .net 3.5