Communication between processes using WCF and F #

I would like to make simple messaging between two lengthy F # processes using F #. They will regularly exchange information every approx. 5 seconds. So far I have reached this point:

#r "System.ServiceModel" #r "System.Runtime.Serialization" //#r @"d:\DLL\Protobuf\protobuf-net.dll" #time "on" open System.ServiceModel [<ServiceContract>] type IService = [<OperationContract>] // [<ProtoBuf.ServiceModel.ProtoBehavior>] abstract Test: float [] [] [] -> string type Service () = interface IService with member o.Test data = sprintf "Hello, %A" data let server = System.Threading.Thread (fun () -> let svh = new ServiceHost (typeof<Service>) svh.AddServiceEndpoint (typeof<IService>, NetNamedPipeBinding(), "net.pipe://localhost/123") |> ignore svh.Open () ) server.IsBackground <- true server.Start() let scf: IService = ChannelFactory.CreateChannel (NetNamedPipeBinding(), EndpointAddress "net.pipe://localhost/123") let rnd = System.Random () let arr = Array.init 100 (fun i -> Array.init 10 (fun j -> Array.init 10 (fun k -> rnd.NextDouble() ))) printfn "%s" (scf.Test arr) 

I get many different exceptions, mainly due to various WCF security restrictions.

My questions

  • What do I need to do at least to get it to work?
  • Did I write the code correctly to make the message as fast as possible?
  • I tried to enable the ProtoBuf serializer (see ProtoBehavior in the code) to make serialization even faster. Did I do it right? How do I know that WCF actually uses this or not?
+3
source share
2 answers

You need to increase the MaxReceivedMessageSize property on the binding with its default value of 65536 on the client and server to accommodate the amount of data that you transfer.

You can use the Message Inspector to check if WCF really uses the ProtoBuf serializer (which is not). Apparently, ProtoBehavior applies only to values ​​with the specified DataContract / ProtoContract attribute. Therefore, in the example below, I created a record type in Vector format, also marked with the F # 3 CLIMutable attribute , to wrap arrays:

 #r "System.ServiceModel" #r "System.Runtime.Serialization" #r "protobuf-net.dll" #time "on" open System.ServiceModel open System.Runtime.Serialization [<DataContract; ProtoBuf.ProtoContract; CLIMutable>] type Vector<'T> = { [<DataMember; ProtoBuf.ProtoMember(1)>] Values : 'T[] } [<ServiceContract>] type IService = [<OperationContract>] [<ProtoBuf.ServiceModel.ProtoBehavior>] abstract Test: Vector<Vector<Vector<float>>> -> string type Service () = interface IService with member o.Test data = sprintf "Hello, %A" data let server = System.Threading.Thread (fun () -> let svh = new ServiceHost (typeof<Service>) let binding = NetNamedPipeBinding() binding.MaxReceivedMessageSize <- binding.MaxReceivedMessageSize * 4L svh.AddServiceEndpoint (typeof<IService>, binding, "net.pipe://localhost/123") |> ignore svh.Open () ) server.IsBackground <- true server.Start() let scf: IService = let binding = NetNamedPipeBinding() binding.MaxReceivedMessageSize <- binding.MaxReceivedMessageSize * 4L ChannelFactory.CreateChannel (binding, EndpointAddress "net.pipe://localhost/123") let rnd = System.Random () let arr = { Values = Array.init 100 (fun i -> { Values = Array.init 10 (fun j -> { Values =Array.init 10 (fun k -> rnd.NextDouble()) } )} )} printfn "%s" (scf.Test arr) 
+4
source

I can only answer "3": use wirehark to check data on the wire or otherwise time / bandwidth measurement. Try using / without protobu-net, and compare. The protobuf message will contain a fragment of binary data instead of XML.

Note. If you use protobuf-net here, enabling MTOM will shave a bit (if it is available for the selected transport).

0
source

All Articles