【问题标题】:How to calculate size of message stream sending by WCF Server to client如何计算 WCF 服务器向客户端发送的消息流的大小
【发布时间】:2016-01-14 09:26:40
【问题描述】:

从服务器端,有时我们发送的数据非常大,超出了客户端 NET TCP 绑定中定义的限制。在这种情况下,我们会在客户端收到通信异常。如果我在客户端增加绑定参数 MaxReceivedMessageSize 的大小,问题就会得到解决,但我们不确定 WCF 服务器将发送多少数据给我们,并且它可以再次超过客户端 MaxReceivedMessageSize 中定义的限制。

有什么方法可以让我知道 WCF 服务器要发送给客户端的消息流的实际大小,以便如果大小超过客户端定义的大小,以便在发送之前,我可以修剪服务器端的消息内容达到该限制。

【问题讨论】:

  • .Net 中(很遗憾)您无法测量对象的(真实)大小。

标签: c# .net wcf


【解决方案1】:

字节流的大小取决于所使用的编码器,不同的编码器产生不同大小的字节流。

我编写了一个 MessageInspector,它会重写消息/流以计算最终字节流的大小。一旦您在客户端中配置了此检查器,它将打印文本编码器与您配置的编码器(MTOM、二进制或 GZip)创建的消息大小的差异。 Inspector 的发送方法如下:

public object BeforeSendRequest(ref System.ServiceModel.Channels.Message request, IClientChannel channel)
{
  var mb = request.CreateBufferedCopy(int.MaxValue);  
  request = mb.CreateMessage();  
  var ms = new MemoryStream();

  // Dump message size based on text encoder.
  using (var memWriter = XmlDictionaryWriter.CreateTextWriter(ms))
  {
    mb.CreateMessage().WriteMessage(memWriter);
    memWriter.Flush();
    Console.WriteLine("Message size using text encoder {0}", ms.Position);
  }

  ms = new MemoryStream(); 

  if (gzipEncoding != null)
  {// GZip Special case
    var encoder = gzipEncoding.CreateMessageEncoderFactory().CreateSessionEncoder();
    encoder.WriteMessage(mb.CreateMessage(), ms);
    Console.WriteLine("GZip encoded size {0}", ms.Position);
    return null;
  }

  // just wrap the message – and wrapper will do the trick.

  request = new WrappingMessage(request);

  return null;
}

public class WrappingMessage : Message
{
  Message innerMsg;  
  MessageBuffer msgBuffer;

  public WrappingMessage(Message inner)
  {
    this.innerMsg = inner; 
    msgBuffer = innerMsg.CreateBufferedCopy(int.MaxValue); 
    innerMsg = msgBuffer.CreateMessage();
  }

  public override MessageHeaders Headers
  {
    get { return innerMsg.Headers; }
  }

  protected override void OnWriteBodyContents(XmlDictionaryWriter writer)
  {
    innerMsg.WriteBodyContents(writer);
  }

  public override MessageProperties Properties
  {
    get { return innerMsg.Properties; }
  }

  public override MessageVersion Version
  {
    get { return innerMsg.Version; }
  }

  protected override void OnWriteMessage(XmlDictionaryWriter writer)
  {
    // write message to the actual stream using encoder..

    base.OnWriteMessage(writer); 
    writer.Flush();

    // write message to MemoryStream (using encoder) to get it’s size.
    var copy = msgBuffer.CreateMessage();
    DumpEncoderSize(writer, copy);
  }

  private static void DumpEncoderSize(System.Xml.XmlDictionaryWriter writer, Message copy)
  {
    var ms = new MemoryStream(); 
    string configuredEncoder = string.Empty; 
    if (writer is IXmlTextWriterInitializer)
    {
        var w = (IXmlTextWriterInitializer)writer; 
        w.SetOutput(ms, Encoding.UTF8, true); 
        configuredEncoder = "Text";
    }
    else if (writer is IXmlMtomWriterInitializer)
    {
      var w = (IXmlMtomWriterInitializer)writer;
      w.SetOutput(ms, Encoding.UTF8, int.MaxValue, "", null, null, true, false);
      configuredEncoder = "MTOM";
    }
    else if (writer is IXmlBinaryWriterInitializer)
    {
      var w = (IXmlBinaryWriterInitializer)writer;
      w.SetOutput(ms, null, null, false);
      configuredEncoder = "Binary";
    }

    copy.WriteMessage(writer);
    writer.Flush();
    var size = ms.Position;
    Console.WriteLine("Message size using configured ({1}) encoder {0}",  size,configuredEncoder);
  }
}

【讨论】:

    猜你喜欢
    • 2015-01-05
    • 2013-06-24
    • 2017-01-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-07-15
    相关资源
    最近更新 更多