我有一个NET.TCP WCF服务器和客户端应用程序,并希望在服务器端组件中为每个连接的客户端提供带宽,TTL等的统计信息。
要获得TTL我可以实现一种新的方法在客户端和服务器之间跳转并测量时间差,并测量流量我可以简单地计算我的消息中的字节但我想知道是否有任何内置的统计信息提供我需要的ServiceHost。
计算我的对象中的字节数也可能会产生误导,因为绑定将为数据应用二进制编码。
答案 0 :(得分:4)
结合this博客文章并浏览在线文档我已实施了消息检查器,自定义行为并将其应用于我的服务。
由于我的服务是Duplex,要捕获所有流量,我需要在服务器端端点和回调客户端运行时添加消息检查器。许多在线示例似乎都缺少这一点。
自定义检查器
public class EndPointMessageInspector : IDispatchMessageInspector, IClientMessageInspector
{
static long _bytesWritten = 0;
static long _bytesRead = 0;
public object AfterReceiveRequest(ref Message request, IClientChannel channel, InstanceContext instanceContext)
{
MessageBuffer buffer = request.CreateBufferedCopy(Int32.MaxValue);
request = buffer.CreateMessage();
_bytesRead += buffer.CreateMessage().ToString().Length;
return null;
}
public void BeforeSendReply(ref Message reply, object correlationState)
{
if (reply != null)
{
MessageBuffer buffer = reply.CreateBufferedCopy(Int32.MaxValue);
reply = buffer.CreateMessage();
_bytesWritten += buffer.CreateMessage().ToString().Length;
}
}
public void AfterReceiveReply(ref System.ServiceModel.Channels.Message reply, object correlationState)
{
// No replies expected from Duplex call backs
}
public object BeforeSendRequest(ref System.ServiceModel.Channels.Message request, IClientChannel channel)
{
if (request != null)
{
MessageBuffer buffer = request.CreateBufferedCopy(Int32.MaxValue);
request = buffer.CreateMessage();
_bytesWritten += buffer.CreateMessage().ToString().Length;
}
return null;
}
}
自定义服务行为
[AttributeUsage(AttributeTargets.Class)]
public class GatherThroughputBehaviour : Attribute, IServiceBehavior, IEndpointBehavior
{
#region IServiceBehavior Members
public void AddBindingParameters(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase, Collection<ServiceEndpoint> endpoints, BindingParameterCollection bindingParameters)
{
}
public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
{
for (int i = 0; i < serviceHostBase.ChannelDispatchers.Count; i++)
{
ChannelDispatcher channelDispatcher = serviceHostBase.ChannelDispatchers[i] as ChannelDispatcher;
if (channelDispatcher != null)
{
foreach (EndpointDispatcher endpointDispatcher in channelDispatcher.Endpoints)
{
EndPointMessageInspector inspector = new EndPointMessageInspector();
endpointDispatcher.DispatchRuntime.MessageInspectors.Add(inspector);
}
}
}
}
public void Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
{
}
#endregion
#region IEndpointBehavior Members
public void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters)
{
}
public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime)
{
}
public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher)
{
endpointDispatcher.DispatchRuntime.MessageInspectors.Add(new EndPointMessageInspector());
endpointDispatcher.DispatchRuntime.CallbackClientRuntime.MessageInspectors.Add(new EndPointMessageInspector());
}
public void Validate(ServiceEndpoint endpoint)
{
return;
}
#endregion
}
将行为应用于我的服务
[GatherThroughputBehaviour]
public class TunnelServer : IMyContract
{
...
}