0

WCFを使用してメッセージフレーミングを実装する方法を理解しようとしています。目標は、Tcpを介して独自の形式を処理できるサーバーをWCFで作成することです。net.TcpバインディングはSOAP専用であるため、使用できません。

次の形式のメッセージを受信するカスタムチャネルを作成する必要があります。メッセージの例は「5abcde」です。特に、カスタムチャネルでフレーミングを行う方法がわかりません。

ここにいくつかのサンプルコードがあります

class CustomChannel: IDuplexSessionChannel
{
private class PendingRead
{
    public NetworkStream Stream = null;
    public byte[] Buffer = null;
    public bool IsReading = false;
}

private CommunicationState state = CommunicationState.Closed;
private TcpClient tcpClient = null;
private MessageEncoder encoder = null;
private BufferManager bufferManager = null;
private TransportBindingElement bindingElement = null;
private Uri uri = null;
private PendingRead pendingRead;

public CustomChannel(Uri uri, TransportBindingElement bindingElement, MessageEncoderFactory encoderFactory, BufferManager bufferManager, TcpClient tcpClient)
{
    this.uri = uri;
    this.bindingElement = bindingElement;
    this.tcpClient = tcpClient;
    this.bufferManager = bufferManager;     
    state = CommunicationState.Created;
  }

public IAsyncResult BeginTryReceive(TimeSpan timeout, AsyncCallback callback, object state)
{
    if (this.state != CommunicationState.Opened) return null;

    byte[] buffer = bufferManager.TakeBuffer(tcpClient.Available);
    NetworkStream stream = tcpClient.GetStream();
    pendingRead = new PendingRead { Stream = stream, Buffer = buffer, IsReading = true };
    IAsyncResult result = stream.BeginRead(buffer, 0, buffer.Length, callback, state);
    return result;
}
public bool EndTryReceive(IAsyncResult result, out Message message)
{
    int byteCount =  tcpClient.Client.EndReceive(result);
    string content = Encoding.ASCII.GetString(pendingRead.buffer)

     // framing logic here

     Message.CreateMessage( ... )
}   

}

したがって、基本的に、EndTryReceiveを初めて使用すると、保留中の読み取りバッファ「5ab」からメッセージの一部を取得できます。次に、2回目は、残りのメッセージを取得できます。問題は、EndTryReceiveが最初に呼び出されたときに、Messageオブジェクトを作成することを余儀なくされることです。これは、チャネルスタックを上る部分的なMessageがあることを意味します。

私が本当にやりたいのは、バッファに完全なメッセージ「5 abcde」があることを確認することです。これにより、EndTryReceiveでメッセージを作成すると、完全なメッセージになります。

WCFでカスタムフレーミングを行っている例はありますか?

ありがとう、Vadim

4

2 に答える 2

3

ワイヤレベルでのフレーミングは、WCFチャネルモデルが実際に気にするものではありません。それを処理するのはあなた次第です。

これが意味するのは、トランスポートチャネルが受信時に「全体」のメッセージを返すようにするのはあなたの責任であるということです(ストリーミングは少し変更されますが、ある程度までしか変更されません)。

あなたの場合、チャネルの受信操作を基盤となるソケットの受信操作に直接変換しているようですが、それでは、独自のフレーミングルールを適用する機会が得られないためです。

したがって、実際には、チャネルでの単一の受信操作は、基盤となるソケットでの複数の受信操作に非常によく変換される可能性があり、それは問題ありません(そして、すべての非同期を実行できるため、その部分に影響を与える必要はありません)。

つまり、基本的に問題は次のようになります。プロトコルフレーミングモデルはどのようになりますか?ここでは大げさな推測ですが、メッセージの前に長さがあり、長さが10進文字列としてエンコードされているように見えますか?(迷惑に見えます)。

その場合の最善の策は、トランスポートバッファの着信データ(たとえば、最大64KBのデータなど)を用意し、各受信操作でバッファをチェックして、の長さを抽出するのに十分なバイトが含まれているかどうかを確認することです。着信メッセージ。その場合は、バッファから必要な数のバイトを読み取るか、バッファをフラッシュしてソケットからできるだけ多くのバイトを読み取ります。プロトコルの動作によっては、実際に必要になる前に部分的なメッセージを読んでしまう可能性があるため、注意が必要です。

于 2009-12-07T20:54:41.220 に答える
0

私はthomasrに同意します。基本的なインスピレーションは、Microsoftテクノロジサンプル「ChunkingChannel」にあります。

于 2013-06-03T23:13:16.667 に答える