使用WCF和F#进行进程间通信

3
我希望使用F#实现两个长时间运行的进程之间的简单一对一通讯,并且它们将定期每5秒交换信息。目前我已经做到了这一点:
#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)

我遇到了许多不同的异常,主要是由于不同的WCF安全限制。

我的问题如下:

  1. 为使它正常工作需要最少需要做什么?
  2. 我编写的代码是否正确,以尽可能快地进行通信?
  3. 我已经尝试包含ProtoBuf序列化程序(请参见代码中的ProtoBehavior),以使序列化更快。我是否实现正确? 我怎样知道WCF是否真正使用它?
2个回答

4

您需要将客户端和服务器上绑定的MaxReceivedMessageSize属性从默认值65536增加以容纳传输的数据量。

您可以使用消息检查器检查WCF是否实际上正在使用ProtoBuf序列化程序(它不是)。ProtoBehavior似乎仅适用于具有指定DataContract / ProtoContract属性的值。因此,在下面的修改示例中,我创建了一个Vector记录类型,也标记为F# 3 CLIMutable属性,以包装数组:

#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)

0

我只能回答“3”:使用Wireshark检查数据线上的数据,或者计时/测量带宽。尝试启用/禁用protobuf-net,并进行比较。Protobuf消息将具有二进制数据块而不是XML。

注意:如果您在此处使用protobuf-net,则启用MTOM将削减更多(如果您选择的传输支持)。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接