Reputation: 21
This subject is discussed a lot around here but no answer is really accurate. i have a wcf service that i've created with nettcpbinding. i wanted to examine the messages sizes/sent data rate/received data rate that are being transferred between the server and client. The service is a duplex channel and the client code is auto-generated by adding a service reference. Both applications (client/server) are written in C# .Net 4.0. The nettcp binding that is using the default binary encoder and the configuration settings on the server side is as follows:
<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>
The service is self hosted and is started as a console application by creating:
ServiceHost host = new ServiceHost(serviceObject, addresses);
i used wireshark to get a general statistics and the tcp packets that are transferred and i saw that i have a very high data rate. So i wanted to examine each message size that is transferred between client and server. For this i used several techniques for measuring messages sizes that are suggested in this forum but none of them give the exact same size as the wireshark does.
i already tested the following: WCF - Measuring approximate message sizes programmatically
this links: http://winterdom.com/2009/07/comparing-text-and-binary-serialization-in-wcf/
and did this in my code:
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);
}
it doesn't give accurate results.
Then i tried to add a message inspector and to listen to the Before/After - Send/Receive messages as suggested in this article http://devlicio.us/blogs/derik_whittaker/archive/2011/02/03/how-to-intercept-a-wcf-message-to-track-message-size.aspx and called this function:
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
);
}
This also doesn't give accurate results. When i say not accurate - i mean around 300 - 500 bytes differences. But the gap is not constant.
i didn't want to create a custom binding because i wanted to examine the netTcpBinding and didn't want to change any configuration.
Does anyone have an accurate solution for this matter?
Thank you for reading this long question description.
And thanks in advance for any suggested solution.
Upvotes: 2
Views: 1935
Reputation: 87298
The only way where you'll get an accurate measurement of the message size is to use a custom message encoder. It can wrap the original encoder, and at that point (on the calls to WriteMessage
and ReadMessage
you can look at the message sizes.
You don't get accurate results by writing the message to a stream using the binary writer because the binary encoder used by the NetTcpBinding
uses some dictionaries to further compress the message during transmission.
Upvotes: 1