C# “运行时”;EndOfStreamException“;通过ZeroMQ进行MS Bond序列化时出错

C# “运行时”;EndOfStreamException“;通过ZeroMQ进行MS Bond序列化时出错,c#,f#,zeromq,bond,C#,F#,Zeromq,Bond,首先,值得一提的是,在单个F#解决方案中,消息的序列化和反序列化工作正常。但是,我在通过ZeroMQ正确处理消息的发送和/或接收时遇到问题 以下程序的订阅服务器端出现运行时错误。bond文件是用bond编译器定义和编译的。然后从C#创建一个dll,从F#调用。然后我有两个F#程序。一个是通过tcp套接字发布序列化数据的,另一个是订阅者。当sub上接收到消息时,尝试解组原始数据的行就是导致运行时错误的行。有人知道这是为什么吗 [编辑]根据Fyodor的评论,我在发布服务器端进行了更改,从而更改了订

首先,值得一提的是,在单个F#解决方案中,消息的序列化和反序列化工作正常。但是,我在通过ZeroMQ正确处理消息的发送和/或接收时遇到问题

以下程序的订阅服务器端出现运行时错误。bond文件是用bond编译器定义和编译的。然后从C#创建一个dll,从F#调用。然后我有两个F#程序。一个是通过tcp套接字发布序列化数据的,另一个是订阅者。当sub上接收到消息时,尝试解组原始数据的行就是导致运行时错误的行。有人知道这是为什么吗

[编辑]根据Fyodor的评论,我在发布服务器端进行了更改,从而更改了订阅服务器端的错误。因此,错误可能与我如何打包和解包信息有关

这是.bond文件

namespace Examples

struct Record
{
    0: map<string, double> payload;
}
名称空间示例
结构记录
{
0:地图有效载荷;
}
以下是出版商:

// publisher

open System
open Bond
open Bond.Protocols
open Bond.IO.Safe
open ZeroMQ

let ctx = new ZContext()
let publisher = new ZSocket(ctx, ZSocketType.PUB)
publisher.Bind("tcp://*:5556")

let src = new Examples.Record()
src.payload.Add("a", 1.)
src.payload.Add("b", 2.)

let output = new OutputBuffer()
let writer = new CompactBinaryWriter<OutputBuffer>(output)

while true do
    Marshal.To(writer, src)
    //let input = new InputBuffer(output.Data)
    //let byteArr = input.ReadBytes(int(input.Length - 1L))
    let updateFrame = new ZFrame(System.Text.Encoding.ASCII.GetString output.Data.Array)
    publisher.Send(updateFrame)
//发布者
开放系统
未平仓债券
开放式债券。协议
打开保险箱
打开ZeroMQ
设ctx=new ZContext()
让publisher=newzSocket(ctx,ZSocketType.PUB)
publisher.Bind(“tcp://*:5556”)
设src=newexamples.Record()
src.payload.Add(“a”,1.)
src.payload.Add(“b”,2.)
let output=new OutputBuffer()
let writer=新的CompactBinaryWriter(输出)
尽管如此
封送员(编写员,src)
//让输入=新的InputBuffer(output.Data)
//let byteArr=input.ReadBytes(int(input.Length-1L))
让updateFrame=new ZFrame(System.Text.Encoding.ASCII.GetString output.Data.Array)
publisher.Send(updatename)
这是订户:

// subscriber

open Bond
open Bond.Protocols
open Bond.IO.Safe
open System
open System.Text
open ZeroMQ

let ctx = new ZContext()
let subscriber = new ZSocket(ctx, ZSocketType.SUB)
subscriber.Connect("tcp://127.0.0.1:5556")
subscriber.SubscribeAll()

let output = new OutputBuffer()    
while true do    
    let received = subscriber.ReceiveFrame()
    let byteArr = Encoding.ASCII.GetBytes (received.ReadString())
    let arrSeg = ArraySegment<byte>(byteArr)
    let input = new InputBuffer(arrSeg)
    let dst = Unmarshal<Examples.Record>.From(input)
    for KeyValue(k, v) in dst.payload do
        printfn "%A %A" k v
//订户
未平仓债券
开放式债券。协议
打开保险箱
开放系统
开放系统.Text
打开ZeroMQ
设ctx=new ZContext()
let subscriber=new ZSocket(ctx,ZSocketType.SUB)
订阅服务器。连接(“tcp://127.0.0.1:5556")
subscriber.subscribbeall()
let output=new OutputBuffer()
尽管如此
let received=subscriber.ReceiveFrame()
let byteArr=Encoding.ASCII.GetBytes(received.ReadString())
设arrSeg=ArraySegment(byteArr)
让输入=新输入缓冲区(arrSeg)
让dst=Unmarshal.From(输入)
对于dst中的键值(k,v)。有效负载do
printfn“%A%A”k v

在接收端,当您尝试将封送的Bond Compact二进制文件解码为ASCII字符串时,会丢失一些有效负载。将结构(如
记录
封送到压缩二进制文件时,有效负载的前四个字节是
0x43 0x42 0x10 0x00
)。当从ZFrame读取字符串时,无论帧大小如何,遇到的错误都会发出字符串结束的信号。因此,读取端只看到
0x43 0x42 0x10
,而不是整个有效负载(我测试时为29字节)

由于Compact Binary是一种二进制协议,因此您需要使用
ZFrame
构造函数在发布服务器端获取缓冲区:

let updateFrame = new ZFrame(output.Data.Array, output.Data.Offset, output.Data.Count)
在订户端,您只需读取缓冲区:

let byteArr = received.Read()
此外,在发布服务器端,您不断地将数据累积到同一个OutputBuffer中。您需要将
输出重置。在整理下一条记录以重新使用缓冲区而不是增加缓冲区之前,请将
定位为0:

while true do  
    Marshal.To(writer, src)
    let updateFrame = new ZFrame(output.Data.Array, output.Data.Offset, output.Data.Count)output.Data.Array)
    publisher.Send(updateFrame)
    output.Position <- 0

在接收端,当您尝试将封送的Bond Compact二进制文件解码为ASCII字符串时,会丢失一些有效负载。将结构(如
记录
封送到压缩二进制文件时,有效负载的前四个字节是
0x43 0x42 0x10 0x00
)。当从ZFrame读取字符串时,无论帧大小如何,遇到的错误都会发出字符串结束的信号。因此,读取端只看到
0x43 0x42 0x10
,而不是整个有效负载(我测试时为29字节)

由于Compact Binary是一种二进制协议,因此您需要使用
ZFrame
构造函数在发布服务器端获取缓冲区:

let updateFrame = new ZFrame(output.Data.Array, output.Data.Offset, output.Data.Count)
在订户端,您只需读取缓冲区:

let byteArr = received.Read()
此外,在发布服务器端,您不断地将数据累积到同一个OutputBuffer中。您需要将
输出重置。在整理下一条记录以重新使用缓冲区而不是增加缓冲区之前,请将
定位为0:

while true do  
    Marshal.To(writer, src)
    let updateFrame = new ZFrame(output.Data.Array, output.Data.Offset, output.Data.Count)output.Data.Array)
    publisher.Send(updateFrame)
    output.Position <- 0

我看到您正在使用
byteArr.ToString()
创建一个
ZFrame
。这和你想象的不一样。请尝试打印出
byteArr.ToString()
的结果,以查看实际发送的内容。我看到您正在使用
byteArr.ToString()
创建一个
ZFrame
。这和你想象的不一样。尝试打印出
byteArr.ToString()的结果以查看实际发送的内容。