NetworkStream.BeginRead。流媒体图像/视频。处理不能在一次读取中获取整个图像。 [英] NetworkStream.BeginRead. Streaming images/video. Dealing with not getting entire image in one read.

查看:83
本文介绍了NetworkStream.BeginRead。流媒体图像/视频。处理不能在一次读取中获取整个图像。的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我知道,不要重新发明轮子,使用现有的库。由于各种原因,我需要在没有第三方库的情况下执行此操作,我需要自己设计这个。 

I know, don't reinvent the wheel, use an existing library. I'm in a situation where I need to do this without a 3rd party library due to various reasons and I need to engineer this up myself. 

我正在创建一个视频客户端工作服务器解决方案。 服务器允许客户端连接,并且会一次向客户端发送一个图像,这似乎运行得很好。 

I'm creating a video client server solution for work.  The server allows for a client connection and will send one image at a time to a client this seems to operate just fine. 

我的假设是,对于来自服务器的每次写入,我将在客户端上进行1对1读取,然后我将字节转换为图像并将其显示在表单控件中。 

My assumption was that for every Write from the server, I would have a 1 to 1 read on the client which I would then turn the bytes into an image and display them in a form control. 

但是,情况并非如此。 调用NetworkStream.BeginRead(...)时问题出在客户端,因为我不能保证在一次读取时收到完整的图像字节。这真的使事情变得复杂,因为在BeginRead
中指定的回调在不同的线程上运行。  
$


有没有办法调用BeginRead并获得在应用程序循环返回并再次调用BeginRead之前,一次性从服务器获取整个映像?因为最终第二个BeginRead将包含来自上一个图像的字节以及从服务器发送的下一个图像
。 

However, that's not the case.  The problem is on the client side when calling NetworkStream.BeginRead(...) because I'm not guaranteed to receive the full image bytes in one read. Which really complicates things because the callback specified in BeginRead operates on a different thread.  

Is there a way to call BeginRead and and get the entire image from the server in one shot before the application loops back around and calls BeginRead again? Because ultimately the second BeginRead would contain bytes from the previous image AND the next image being sent from the server. 

或者......这只是性质的野兽和我必须不断地,从回调中,用字节数据填充一些缓冲区,然后有一些其他进程知道如何从该缓冲区中取出每个图像,一直处理线程并锁定
数据... ...


这里的任何指导都很棒! 

OR... Is this just the nature of the beast and I have to constantly, from the callback, fill some buffer with the byte data, then have some other process that knows how to pluck each image out of that buffer, all the while dealing with threads and locking the data...

Any guidance here would be awesome! 

谢谢。

Rick

推荐答案

不,BeginRead永远不能保证在单次读取中返回所有数据。涉及的因素太多,甚至可能是远程可能的。但是,这个问题有几种不同的解决方案。

No, BeginRead is never guaranteed to return all the data in a single read. There are too many factors involved such that this would even be remotely possible. There are several different solutions to this problem however.

最简单的解决方案是将NetworkStream包装在BinaryReader中。然后使用
ReadBytes
阅读您需要的确切数据量。该方法将循环,直到读取指定的字节数。不幸的是,这需要改变你的架构,因为:a)你需要提前知道图像的大小b)它是
sync。

The simplest solution is to wrap NetworkStream in a BinaryReader. Then use ReadBytes to read the exact amount of data you need. That method will loop until the specified # of bytes are read. Unfortunately this would require a change in your architecture because: a) you need to know the size of the image in advance and b) it is sync.

对于A这是编写TCP协议的人遇到的常见问题。解决方案几乎总是确保您在客户端和服务器之间传递消息(而不仅仅是数据)。该消息具有明确定义的标头,该标头指定(在其他
项内)预期的有效负载大小。然后,客户端/服务器可以读取固定大小的标头,确定它是什么消息以及有多大。然后使用ReadBytes读取剩余的数据。在读取所有数据(忽略流式消息)之后,可以处理
。如果所有数据都没有到达那么就会出现网络问题而且应该忽略该消息。

For A this is a common problem that people writing TCP protocols run into. The solution is almost always to ensure that you're passing messages (not just data) between the client and server. The message has a well-defined header that specifies (amongst other things) the size of the payload to expect. The client/server can then read the fixed-size header, determine what message it is and how big. Then use ReadBytes to read the remaining data in. After all the data is read (ignoring streaming messages) then it can be processed. If all the data doesn't arrive then there was a network issue and the message should be ignored.

对于B,您可以调用异步(而不是BeginRead)并完成相同的操作。这会破坏你的代码,但比使用旧的BeginRead更好。

For B you can make the call async (instead of BeginRead) and accomplish the same thing. This will ripple up your code but is preferable to using the older BeginRead stuff.

对于多线程的事情,通常每个客户端都有一个专用的线程(如果你不喜欢)没有太多)或者每个客户端请求都由工作线程处理。在他们的情况下,线程将有自己的缓冲区写入
所以不应该有任何线程问题。处理完请求后,不再需要缓冲区。如果还有另一个线程试图处理来自多个客户端的各种请求,那么每个请求线程在检索到
后,所有数据都应该将其添加到处理线程侦听的共享工作队列中。 ReaderWriterLock是为这种架构而设计的,它允许处理线程在没有任何操作时休眠。并且可以有任何#bob
线程将(已完成)消息添加到队列中以供处理器运行。

As for the multi thread thing it is generally common to have each client either have a dedicated thread (if you don't have too many) or have each client request be handled by a worker thread. In their case the thread will have its own buffer to write to so there shouldn't be any threading issues. Once the request has been handled the buffer is no longer needed. If you have yet another thread that is trying to process the various requests from multiple clients then each request thread, after it has retrieved all the data should add it to a shared worker queue that the processing thread listens on. A ReaderWriterLock is designed for this kind of architecture and allows the processing thread to sleep when there is nothing to do. And there can be any # of worker threads adding (completed) messages to the queue for the processor to run against.


这篇关于NetworkStream.BeginRead。流媒体图像/视频。处理不能在一次读取中获取整个图像。的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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