2013-07-10 81 views
2

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

<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

您可以准确测量邮件大小的唯一方法是使用自定义邮件编码器。它可以换原来的编码器,并在该点(在调用WriteMessageReadMessage你可以看一下消息的大小。

你不使用二进制作家因为写的消息流得到准确的结果NetTcpBinding使用的二进制编码器使用一些dictionaries在传输过程中进一步压缩消息。

+0

[link](http:// zamd。net/2008/08/15/calculate-wcf-message-size /) – sattias

+0

正如我所说的那样,在您的问题中以及链接建议中的转储消息不会使用即使写入时也能压缩消息的字典二进制格式。你真的需要一个自定义的编码器。 – carlosfigueira

+0

谢谢。你的意思是我需要编写一个CustomBinding来创建我的CustomEncoder吗?如果我创建一个CustomBinding,我希望它具有与netTcpBinding相同的配置。这可以做到吗? – sattias