0

我试图了解如何使用 WCF 实现消息框架。目标是在 WCF 中创建一个可以通过 Tcp 处理专有格式的服务器。我不能使用 net.Tcp 绑定,因为这仅适用于 SOAP。

我需要编写一个自定义通道来接收以下格式的消息。示例消息是“5 abcde”。特别是我不确定如何在我的自定义频道中进行取景。

这是一些示例代码

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 可以从待处理的读取缓冲区“5 ab”中获取一条消息。然后第二次它可以得到剩下的信息。问题是当第一次调用 EndTryReceive 时,我被迫创建一个 Message 对象,这意味着会有部分 Message 进入通道堆栈。

我真正想做的是确保缓冲区中有完整的消息“5 abcde”,这样当我在 EndTryReceive 中构造消息时,它就是完整的消息。

有没有人有任何他们如何使用 WCF 进行自定义框架的示例?

谢谢, 瓦迪姆

4

2 回答 2

3

线路级别的框架并不是 WCF 通道模型真正关心的事情。这几乎取决于你来处理它。

我的意思是,您有责任确保您的传输通道在接收时返回“完整”消息(流式传输会改变一点,但仅在一定程度上)。

在您的情况下,您似乎正在将通道上的接收操作直接转换为底层套接字上的接收操作,但这不会发生,因为这不会让您有机会执行自己的框架规则。

所以真的,你频道上的单个接收操作很可能会转化为底层套接字上的多个接收操作,这很好(你仍然可以做所有异步操作,所以它不需要影响那部分)。

所以基本上问题变成了:你的协议框架模型是什么样的?在这里疯狂猜测,但看起来消息是以长度为前缀的,长度编码为十进制字符串?(看起来很烦人)。

我认为在这种情况下您最好的选择是让您的传输缓冲区传入数据(例如,最多 64KB 的数据或其他数据),然后在每次接收操作时检查缓冲区以查看它是否包含足够的字节来提取长度传入的消息。如果是这样,则要么从缓冲区读取尽可能多的字节,要么刷新缓冲区并从套接字读取尽可能多的字节。您必须小心,因为根据您的协议的工作方式,我假设您最终可能会在实际需要它们之前阅读部分消息。

于 2009-12-07T20:54:41.220 回答
0

我同意托马斯。您可以在 Microsoft Technology Sample "ChunkingChannel" 中找到一些基本的灵感。

于 2013-06-03T23:13:16.667 回答