WCF tcp绑定消息大小

时间:2013-07-10 06:43:37

标签: wcf wcf-binding nettcpbinding

这个问题在这里进行了很多讨论,但没有答案真的准确。 我有一个用nettcpbinding创建的wcf服务。 我想检查在服务器和客户端之间传输的消息大小/发送数据速率/接收数据速率。 该服务是双工通道,通过添加服务引用自动生成客户端代码。 两个应用程序(客户端/服务器)都是用C#.Net 4.0编写的。 使用默认二进制编码器的nettcp绑定和服务器端的配置设置如下:

<bindings>
  <netTcpBinding>
    <binding name="largeMessage"
             receiveTimeout="infinite"
             sendTimeout="24:00:00"
             openTimeout="00:00:10"
             closeTimeout="00:00:10"
             maxReceivedMessageSize="2147483647"
             maxBufferSize="2147483647"
             maxConnections="2000"
             transactionFlow="false"
             listenBacklog="2147483647"
             maxBufferPoolSize="2147483647">
        <readerQuotas maxDepth="128"
           maxArrayLength="200000000"
           maxStringContentLength="2147483647"/>
      <security mode="None" />
      <reliableSession enabled="false" ordered="true" inactivityTimeout="infinite" />
    </binding>
  </netTcpBinding>
</bindings>

该服务是自托管的,并通过创建:

作为控制台应用程序启动
   ServiceHost host = new ServiceHost(serviceObject, addresses);

我使用wireshark获取一般统计信息和传输的tcp数据包,我看到我的数据速率非常高。 所以我想检查在客户端和服务器之间传输的每个消息大小。 为此,我使用了几种技术来测量本论坛中建议的消息大小,但它们都没有提供与wireshark完全相同的大小。

我已经测试了以下内容: WCF - Measuring approximate message sizes programmatically

此链接: http://winterdom.com/2009/07/comparing-text-and-binary-serialization-in-wcf/

并在我的代码中执行了此操作:

    static byte[] SerializeToBin<T>(T obj)
    {
        Message msg = ObjectToMessage(obj);
        MessageEncodingBindingElement mebe = new BinaryMessageEncodingBindingElement();
        mebe.MessageVersion = MessageVersion.Soap12;
        return Serialize(msg, mebe.CreateMessageEncoderFactory());
    }

    static byte[] Serialize(Message msg, MessageEncoderFactory factory)
    {
        MessageEncoder enc = factory.Encoder;
        MemoryStream stream = new MemoryStream();
        enc.WriteMessage(msg, stream);
        return stream.ToArray();
    }

    static Message ObjectToMessage<T>(T obj)
    {
        DataContractSerializer ser = new DataContractSerializer(typeof(T));
        return Message.CreateMessage(MessageVersion.Soap12, "", obj, ser);
    }

它没有给出准确的结果。

然后我尝试添加消息检查器并按照本文中的建议收听之前/之后 - 发送/接收消息 http://devlicio.us/blogs/derik_whittaker/archive/2011/02/03/how-to-intercept-a-wcf-message-to-track-message-size.aspx 并调用此函数:

    private void DetermineAndLogMessageDiagnostics(ref Message message, eMessageDirection messageDirection)
    {
        long sizeInBytes = 0;
        var mb = message.CreateBufferedCopy(int.MaxValue);
        message = mb.CreateMessage();

        var ms = new MemoryStream();
        using (var memWriter = XmlDictionaryWriter.CreateBinaryWriter(ms))
        {
            mb.CreateMessage().WriteMessage(memWriter);
            memWriter.Flush();
            sizeInBytes = ms.Position;
        }

        //Recalculates the updated average and updates the variables
        //sentBytes, averageSentbps, receivedBytes, averageReceivedbps
        RecalculateAverage(bodySizeInBytes, messageDirection);
        Logger.Info("Message '{0}' size: {1} bits / {2} bytes. ({3} KBits). Sent (Total: {4} Bytes, {5:0.00} bps). Received (Total: {6} Bytes, {7:0.00} bps)",
            action,
            sizeInBytes * 8,
            sizeInBytes,
            ((double)sizeInBytes * 8) / 1024,
            sentBytes,
            averageSentbps,
            receivedBytes,
            averageReceivedbps
            );
    }

这也没有给出准确的结果。 当我说不准确时 - 我的意思是大约300 - 500字节差异。但差距并不是一成不变的。

我不想创建自定义绑定,因为我想检查netTcpBinding并且不想更改任何配置。

有没有人有这个问题的准确解决方案?

感谢您阅读这篇冗长的问题说明。

并提前感谢任何建议的解决方案。

1 个答案:

答案 0 :(得分:1)

您将获得准确测量邮件大小的唯一方法是使用自定义邮件编码器。它可以包装原始编码器,此时(在调用WriteMessageReadMessage时,您可以查看邮件大小。

通过使用二进制写入器将消息写入流,您无法获得准确的结果,因为NetTcpBinding使用的二进制编码器在传输过程中使用了一些dictionaries来进一步压缩消息。