简体   繁体   English

如何使用C#使用Protobuf进行非阻塞套接字读取?

[英]How to do non blocking socket reads with Protobuf using C#?

Lets say I want to do non blocking reads from a network socket. 假设我想从网络套接字执行非阻塞读取。 I can async await for the socket to read x bytes and all is fine. 我可以异步等待套接字读取x字节,一切都很好。

But how do I combine this with deserialization via protobuf? 但是如何通过protobuf将其与反序列化相结合?

Reading objects from a stream must be blocking? 从流中读取对象必须阻塞? that is, if the stream contains too little data for the parser, then there has to be some blocking going on behind the scenes so that the reader can fetch all the bytes it needs. 也就是说,如果流包含的解析器数据太少,那么必须在后台进行一些阻塞,以便读者可以获取所需的所有字节。

I guess I can use lengthprefix delimiters and read the first bytes and then figure out how many bytes I have to fetch minimum before I parse, is this the right way to go about it? 我想我可以使用lengthprefix分隔符并读取第一个字节,然后计算出在解析之前我必须获取最少的字节数,这是正确的方法吗? eg if my buffer is 500 bytes, then await those 500 bytes, and parse the lengthprefix and if the length is more than 500 then wait again, untill all of it is read. 例如,如果我的缓冲区是500字节,则等待那500个字节,并解析长度前缀,如果长度超过500,则再次等待,直到读取所有内容。

What is the idiomatic way to combine non blocking IO and protobuf parsing? 结合非阻塞IO和protobuf解析的惯用方法是什么?

(I'm using Jon Skeet's implementation right now http://code.google.com/p/protobuf-csharp-port/ ) (我现在正在使用Jon Skeet的实现http://code.google.com/p/protobuf-csharp-port/

As a general rule, serializers don't often contain a DeserializeAsync method, because that is really really hard to do (at least, efficiently). 作为一般规则,序列化程序通常不包含DeserializeAsync方法,因为这真的很难(至少,有效)。 If the data is of moderate size, then I would advise to buffer the required amount of data using asynchronous code - and then deserialize when all of the required data is available. 如果数据大小适中,那么我建议使用异步代码缓冲所需的数据量 - 然后在所有必需数据可用时进行反序列化。 If the data is very large and you don't want to have to buffer everything in memory, then consider using a regular synchronous deserialize on a worker thread. 如果数据非常大并且您不希望缓冲内存中的所有内容,那么请考虑在工作线程上使用常规同步反序列化。

(note that note of this is implementation specific, but if the serializer you are using does support an async deserialize: then sure, use that) (请注意,这是特定于实现的,但如果您使用的序列化程序确实支持异步反序列化:那么确定,使用它)

Use the BeginReceive/EndRecieve() methods to receive your data into a byte buffer (typically 1024 or 2048 bytes). 使用BeginReceive/EndRecieve()方法将数据接收到字节缓冲区(通常为1024或2048字节)。 In the AsyncCallback , after ensuring that you didn't read -1/0 bytes (end of stream/disconnect/io error), attempt to deserialize the packet with ProtocolBuf. AsyncCallback ,确保您没有读取-1/0字节(流结束/ disconnect / io错误)后,尝试使用ProtocolBuf反序列化数据包。

Your receive callback will be asynchronous, and it makes sense to parse the packet in the same thread as the reading, IMHO. 您的接收回调将是异步的,并且在与读取相同的线程中解析数据包是有意义的,恕我直言。 It's the handling that will likely cause the biggest performance hit. 这种处理可能会带来最大的性能损失。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM