获得加强的数据大小 [英] Getting serilized data size

查看:48
本文介绍了获得加强的数据大小的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

使用下面的代码,我将通过IP端口发送多个消毒对象。

如果一次只收到一个对象但包装有时,这样可以正常工作

有时候收到的

数据中有多个对象或半个对象。如果我将数据放在接收端的内存流中,那么确定一个结束位置和下一个结束位置的方式是什么?


因为解串器流似乎移动指针我试图在接下来的几个字节看看
以确定流中是否有更多数据。

似乎序列化数据开始于0,1但我无法证实这一点。

是否有规则?


我也注意到收到的字节数总是大于

deserizlized的字节数,任何线索为什么?


代码1

IFormatter f = new BinaryFormatter();

MemoryStream ms = new MemoryStream();

f.Serialize(ms,cmd);

byte [] b = ms.GetBuffer();

this.socket.BeginSend(b,0,b.Length,SocketFlags.None,new

AsyncCallback(Send_Callback),this.socket);


代码2

IFormatter i = new BinaryFormatter();

Memor yStream ms = new MemoryStream(o,0,len);

ms.Position = 0;

while(ms.Position< len)

{

多头头寸= ms.Position;

if(!(ms.ReadByte()== 0&& ms.ReadByte()== 1))

休息;

ms.Position = position;


object obj = i .Deserialize(ms);

.....


问候,

John

Using the below code I am send multiple sterilized object across an IP port.
This works fine if only one object is received at a time but with packing
sometimes there is more then one object or half an object in the received
data. If I place the data in a memory stream on the received side is there
a way to determine where one ends and the next one start?

Since the deserializer stream seems to move the pointer I am trying to look
at the next couple bytes to determine if there is more data in the stream.
It seems that serialized data starts with 0,1 but I can not confirm this.
Is there maybe a rule?

I have also noticed that the number of bytes recieved is always bigger then
the number of bytes deserizlized, any clue why?

CODE 1
IFormatter f = new BinaryFormatter();
MemoryStream ms = new MemoryStream();
f.Serialize(ms, cmd);
byte[] b = ms.GetBuffer();
this.socket.BeginSend(b, 0, b.Length, SocketFlags.None, new
AsyncCallback(Send_Callback), this.socket);

CODE 2
IFormatter i = new BinaryFormatter();
MemoryStream ms = new MemoryStream(o, 0, len);
ms.Position = 0;
while(ms.Position < len)
{
long position = ms.Position;
if(!(ms.ReadByte() == 0 && ms.ReadByte() == 1))
break;
ms.Position = position;

object obj = i.Deserialize(ms);
.....

Regards,
John

推荐答案

John,


你如何获得len的价值?在CODE 2中?您是否尝试过序列化后查看

ms.Length?也许你可以通过电汇以某种方式发送它。


- SM

" John J. Hughes II < no@invalid.com>在留言中写道

news:Ou ************** @ TK2MSFTNGP15.phx.gbl ...
John,

How are you getting the value of "len" in CODE 2? Did you try looking at
ms.Length after serialization? Maybe you could send that in some sort of
delimited fashion over the wire.

- SM
"John J. Hughes II" <no@invalid.com> wrote in message
news:Ou**************@TK2MSFTNGP15.phx.gbl...
使用下面的代码我我通过IP
端口发送多个消毒对象。如果一次只接收一个对象但是有时候收到的数据中有多个对象或半个对象,这样可以正常工作。如果我将数据放在收到的
端的内存流中,有没有办法确定一个结束的位置和下一个的开始?

由于反序列化器流似乎移动指针我我正在尝试查看接下来的几个字节,以确定
流中是否有更多数据。似乎序列化数据从0开始,但我不能确认这一点。可能有规则吗?

我也注意到收到的字节数总是更大
然后去字的字节数,任何线索为什么?

代码1
IFormatter f = new BinaryFormatter();
MemoryStream ms = new MemoryStream();
f.Serialize(ms,cmd);
byte [] b = ms。 GetBuffer();
this.socket.BeginSend(b,0,b.Length,SocketFlags.None,new
AsyncCallback(Send_Callback),this.socket);

代码2
IFormatter i = new BinaryFormatter();
MemoryStream ms = new MemoryStream(o,0,len);
ms.Position = 0;
while(ms.Position< ; len)
{
长位= ms.Position;
if(!(ms.ReadByte()== 0&& ms.ReadByte()== 1))
break;
ms.Position = position;

对象obj = i.Deserialize(ms);
....

问候,
John
Using the below code I am send multiple sterilized object across an IP
port. This works fine if only one object is received at a time but with
packing sometimes there is more then one object or half an object in the
received data. If I place the data in a memory stream on the received
side is there a way to determine where one ends and the next one start?

Since the deserializer stream seems to move the pointer I am trying to
look at the next couple bytes to determine if there is more data in the
stream. It seems that serialized data starts with 0,1 but I can not
confirm this. Is there maybe a rule?

I have also noticed that the number of bytes recieved is always bigger
then the number of bytes deserizlized, any clue why?

CODE 1
IFormatter f = new BinaryFormatter();
MemoryStream ms = new MemoryStream();
f.Serialize(ms, cmd);
byte[] b = ms.GetBuffer();
this.socket.BeginSend(b, 0, b.Length, SocketFlags.None, new
AsyncCallback(Send_Callback), this.socket);

CODE 2
IFormatter i = new BinaryFormatter();
MemoryStream ms = new MemoryStream(o, 0, len);
ms.Position = 0;
while(ms.Position < len)
{
long position = ms.Position;
if(!(ms.ReadByte() == 0 && ms.ReadByte() == 1))
break;
ms.Position = position;

object obj = i.Deserialize(ms);
....

Regards,
John



John J. Hughes II写道:
John J. Hughes II wrote:
使用下面的代码我发送multip通过IP端口消毒对象。
如果一次只收到一个对象但是有包装,这可以正常工作
有时在收到的数据中有一个以上的对象或半个对象。如果我将数据放在接收端的内存流中,是否有一种确定结束位置和下一个结束位置的方法?
Using the below code I am send multiple sterilized object across an IP port.
This works fine if only one object is received at a time but with packing
sometimes there is more then one object or half an object in the received
data. If I place the data in a memory stream on the received side is there
a way to determine where one ends and the next one start?




通过_painstaking_跟踪和小时调试认为一个

网卡驱动程序有问题,我发现:


- SoapSerializer.Deserialize(有时)读取更多数据比

SoapSerializer.Serialize生成(由于缓冲读取)。


- BinarySerializer.Deserialize并不总是读取所有数据

由BinarySerializer.Serialize生成,并且在完成反序列化时将关闭()流




所以基本上,你不能发送多个序列化对象在没有真正幸运的情况下,尤其是在.NET-sp1之后,这是非常幸运的。

SoapSerializer在.NET-sp1之前的大部分时间都曾用过。


我的解决方案是以流式方式发送多个序列化对象,

里面相同的trasport-Stream是实现一个Stream,它会对写入的数据量进行大块长度的en / de-coding。


所以我有一个BlockSubStreamWriter,写入一个16位长度然后

要写入流的数据,并写入一个16位0长度和

刷新标记Close()和一个BlockSubStreamReader读取16位
长度,然后读取相应的数据,如果长度为0则进行EOF,并且

eat如果

BlockSubStreamReader是Close()或Dispose()'ed而没有读取

0-length,则接收剩余的流直到0长度。 br />

所以现在我可以说


new BinarySerializer.Serialize(new BlockSubStreamWriter(stream),graph);

新的BinarySerializer.Deserialize(新的BlockSubStreamReader(流))。


除此之外,我有一个4字节的魔法ID,所以我可以做

序列化/通过简单的界面使用多种协议进行反序列化:


公共接口IObjectChannel:IDisposable

{

///< summary> ;

///向下发送对象

///< / summary>

void SendObject(Object o);

///< summary>

///从频道读取对象

///< / summary>

///< exception cref =" ObjectChannels.Closed"> ObjectChannels.Closed
如果运输已关闭,则会抛出


/ //在收到任何数据之前< / exception>

Object ReceiveObject();

}


我有一个(而不是非常好,如果我应该自己说的话)实现(以及

一些相当漂亮的握手和东西)构成一个透明的方式将b / b
从一个.NET实例运送到另一个.NET实例,包括广泛的

单位和集成测试。


客户现在可以做(/ /来自test /的实际代码)


使用(IObjectChannel c = ksio.ChannelPool.Global.Connect(host,port))

{

c.SendObject(command);

对象回复= c.ReceiveObject();

}


如果现有连接可用,将重用现有连接和GC

空闲时间超过特定时间的连接(默认值:1分钟)。

服务器只需执行(/ test中的实际代码 - 实现echo-service) /)


Socket s = ...;

试试

{

us ing(NetworkStream stream = new NetworkStream(s,true))

while(true)

using(IObjectChannel c =

ObjectChannels.Auto。 Global.Create(stream))

c.SendObject(c.ReceiveObject());

}

catch(ObjectChannels.MagicIdObjectChannel.Closed )

{

//这是关闭的预期方式

}

catch(例外e )

{

Console.WriteLine(" UNEXPECTED END \\\
{0}",e);

}


整个东西(包括在

数据上执行gzip压缩的版本,感谢ICSharpCode.SharpZipLib)大约价值200kb的代码,

..proj-和.sln-files,如果有人

想要查看它,我很乐意发布。


-

Helge



Through _painstaking_ tracing and hours of debugging thinking that a
network card driver was buggy, I have found that:

- The SoapSerializer.Deserialize (sometimes) read more data than
SoapSerializer.Serialize generates (due to buffered reads).

- The BinarySerializer.Deserialize doesn''t always read all the data
generated by BinarySerializer.Serialize, and will Close() the stream
when done deserializing!

So basically, you cannot send multiple serialized objects down the same
stream without being really lucky, especially after .NET-sp1.
SoapSerializer used to work most of the time before .NET-sp1.

My solution for sending multiple serialized objects, in a streaming way,
inside the same trasport-Stream is to implement a Stream that does
chunk-length en/de-coding of the amount of data written.

So I have a BlockSubStreamWriter, that writes a 16-bit length and then
the data to be written to the stream, and writes a 16-bit 0-length and
flushes to mark Close(), and a BlockSubStreamReader that reads 16-bit
length and then corresponding data, making EOF if the length is 0, and
"eating" the rest of stream untill a 0-length is received if the
BlockSubStreamReader is Close() or Dispose()''ed without having read a
0-length.

So now i can say

new BinarySerializer.Serialize(new BlockSubStreamWriter(stream), graph);
new BinarySerializer.Deserialize(new BlockSubStreamReader(stream)).

On top of this i have a 4-byte magic ID, so I can do
serialize/deserialize using multiple protocols from a simple interface:

public interface IObjectChannel: IDisposable
{
/// <summary>
/// Send object down the channel
/// </summary>
void SendObject(Object o);
/// <summary>
/// Read object from channel
/// </summary>
/// <exception cref="ObjectChannels.Closed">ObjectChannels.Closed
is thrown if the transport is closed
/// before any data is received</exception>
Object ReceiveObject();
}

I have a (rather pretty, if I should say it myself) implementation (and
some rather nifty handshaking and stuff) making up a transparent way of
shipping objects from one .NET instance to another, including extensive
unit and integration-tests.

Clients can now do (/actual code from test/)

using ( IObjectChannel c = ksio.ChannelPool.Global.Connect(host,port))
{
c.SendObject(command);
Object reply = c.ReceiveObject();
}

Which will reuse an existing connection if one is available, and GC
connections that are idle for more than a specific time (default: 1minute).

Servers simply do (/actual code from test - implements an "echo-service"/)

Socket s = ...;
try
{
using ( NetworkStream stream = new NetworkStream(s, true) )
while ( true )
using ( IObjectChannel c =
ObjectChannels.Auto.Global.Create(stream) )
c.SendObject(c.ReceiveObject());
}
catch ( ObjectChannels.MagicIdObjectChannel.Closed)
{
// That''s the expected way to close
}
catch ( Exception e )
{
Console.WriteLine("UNEXPECTED END\n{0}", e);
}

The entire stuff (including a version that does gzip compression on the
data, thanks to ICSharpCode.SharpZipLib) is about 200kb worth of code,
..proj- and .sln-files, which I would be happy to publish if someone
wants to check it out.

--
Helge


Sahil Malik


当我收到包裹时Len出现在插座中.. 。下面是调用代码t的代码

你以前见过的帽子。我有另一个系统,我发送

压缩数据,大于缓冲区大小,所以我发送大小为

标头,然后等待所有数据显示。这个系统意图

或多或少只是监控流并根据数据采取行动,所以我试图保持开销下降。猜猜我别无选择,只需要很长时间就可以了。


感谢您的反馈。


///显示数据调用一个委托,该委托将发送到一个事件,即
处理数据。

private void AcceptData(IAsyncResult result)

{

尝试

{

StateObject so =(StateObject)result.AsyncState;

if(so .workSocket == null ||!so.workSocket.Connected)

return;


int bytes = so.workSocket.EndReceive(result);


if(bytes> 0)

{

this.displayData(so.buffer,bytes);

}

其他

{

this.stop = true;

}

recDone.Set();

}

catch(exception ex)

{System.Diagnostics.Debug.WriteLine(ex。信息); }

}

问候,

John
Sahil Malik

Len comes form the socket when I recieved the packet... below is the code
that calls the code that you saw before. I have another system where I send
compressed data that is larger then the buffer size so I send the size as a
header then then wait for all the data to show up. This system was intented
to more or less just monitor the stream and act based on the data so I was
trying to keep the overhead down. Guess I have no choice but to do it the
long way around.

Thanks for the feedback.

/// Display data calls a delegate which inturn is sent to an event which
handles the data.
private void AcceptData(IAsyncResult result)
{
try
{
StateObject so = (StateObject)result.AsyncState;
if(so.workSocket == null || !so.workSocket.Connected)
return;

int bytes = so.workSocket.EndReceive(result);

if(bytes > 0)
{
this.displayData(so.buffer, bytes);
}
else
{
this.stop = true;
}
recDone.Set();
}
catch(Exception ex)
{ System.Diagnostics.Debug.WriteLine(ex.Message); }
}
Regards,
John


这篇关于获得加强的数据大小的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆