简体   繁体   English

调整缓冲区长度以从NetworkStream读取小数据

[英]Tuning buffer length for reading small data from NetworkStream

How to fine tune the bufferSize while reading small data from the TcpClient/NetworkStrem? 从TcpClient / NetworkStrem读取小数据时,如何微调bufferSize? If the bufferSize is big like 1024, 4096 the Read/BeginRead blocks. 如果bufferSize大,如1024、4096,则Read / BeginRead块。 If I set the bufferSize to 16, 32 it works without blocking. 如果将bufferSize设置为16,则32不会阻塞。

  • Does setting the bufferSize to 1 guarantee there won't be any blocks? 将bufferSize设置为1是否可以确保没有任何块? Will the performance impact be very bad? 性能影响会很差吗?
  • It looks like setting the ReadTimeout to values like 1000, 2000 has no effect over blocking. 看起来将ReadTimeout设置为1000、2000之类的值不会对阻塞产生影响。 Is there any other way to make the blocking be short? 还有其他方法可以缩短封锁时间吗? (NoDelay = true doesn't work) (NoDelay = true不起作用)

     public static IObservable<byte[]> AsyncReadChunk(this Stream stream, int bufferSize) { var buffer = new byte[bufferSize]; return Observable.FromAsyncPattern<byte[], int, int, int>(stream.BeginRead, stream.EndRead)(buffer, 0, bufferSize) .Select(cbRead => { var dataChunk = new byte[cbRead]; Buffer.BlockCopy(buffer, 0, dataChunk, 0, cbRead); return dataChunk; }); } public static IObservable<byte[]> AsyncRead(this NetworkStream stream, int bufferSize) { return Observable.Defer(() => stream.DataAvailable ? AsyncReadChunk(stream, bufferSize) : Observable.Return(new byte[0])) .Repeat() .TakeWhile((dataChunk, index) => dataChunk.Length > 0); } 

It looks like setting the ReadTimeout to values like 1000, 2000 has no effect over blocking. 看起来将ReadTimeout设置为1000、2000之类的值不会对阻塞产生影响。

Msdn says, that ReadTimeout has no effect when using the async BeginRead method. Msdn说,使用异步BeginRead方法时,ReadTimeout无效。

Does setting the bufferSize to 1 guarantee there won't be any blocks? 将bufferSize设置为1是否可以确保没有任何块?

No, of cause not. 不,原因不对。 When not a single byte is sent over the connection, the Read call will block regardless of the buffersize. 如果没有通过连接发送单个字节,则无论缓冲区大小如何,Read调用都会阻塞。

Will the performance impact be very bad? 性能影响会很差吗?

I guess you are talking about the 1 byte buffer here. 我猜您在这里谈论的是1字节缓冲区。 It depends on the amount and frequency of data you receive and what code you execute on EndRead . 这取决于您收到的数据的数量和频率以及在EndRead执行的代码。 When processing a stream with a high bandwidth, the impact can be big. 在处理具有高带宽的流时,影响可能很大。 You have to try and watch your cpu while receiving data. 您必须尝试在接收数据时观察CPU。

I'm not really sure what you want to achieve respectively what your concern about blocking is. 我不太确定您要分别实现什么,而您对阻塞的关注是什么。

When you start a Receive (or Networkstream.Read) with a buffer of say 1024 bytes, and you receive 10 Bytes on the socket, the Read call will return that 10 Bytes after a short delay but will not block until the whole buffer is filled. 当您启动一个具有例如1024个字节的缓冲区的Receive(或Networkstream.Read),并且在套接字上收到10个字节时,Read调用将在短暂的延迟后返回该10个字节,但是直到整个缓冲区被填满后才会阻塞。

Is there any other way to make the blocking be short? 还有其他方法可以缩短封锁时间吗?

What do you mean with short . 简而言之你什么意思。 As i say, even with a big buffer, the Read won't block endlessly when receiving small amounts of data. 如我所说,即使有很大的缓冲区,当接收少量数据时,读取也不会无限阻塞。

(NoDelay = true doesn't work) (NoDelay = true不起作用)

That a completely different story but is might be interesting to set it to true on your senders side (if you are in control of that, too). 那是一个完全不同的故事,但是在发件人一侧将它设置为true可能会很有趣(如果您也可以控制的话)。

When set to false (the default), it will combine small datachunks being sent into bigger ones to reduce the overhead of one tcp packet (40 Bytes header). 设置为false(默认值)时,它将把发送的较小数据块合并为较大的数据块,以减少一个tcp数据包(40字节标头)的开销。

EDIT 编辑

I mean NetworkStream.BeginRead to return immediately if there is no data. 我的意思是NetworkStream.BeginRead如果没有数据,则立即返回。

What about using stream.DataAvailable ? 关于使用stream.DataAvailable呢? It should return false when there is no data. 没有数据时应返回false。

In addition, when using the async pattern, isn't it expected behaviour that the calls will block until there is something to do? 另外,在使用异步模式时,不是在某些事情要做之前调用将被阻塞的预期行为吗? Otherwise you will get active polling in a busy loop. 否则,您将在繁忙的循环中获得主动轮询。

When the buffer is big it sometimes waits 60 seconds to return (when it is not fully filled or filled to some amount) 当缓冲区很大时,有时会等待60秒返回(当缓冲区未完全填充或填充到一定量时)

Hm, can't believe that. 嗯,真不敢相信。 What kind of data are you sending over the channel? 您通过通道发送什么样的数据? 1 byte every minute? 每分钟1个字节? 1000 bytes per second? 每秒1000个字节?

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

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