繁体   English   中英

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

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

从TcpClient / NetworkStrem读取小数据时,如何微调bufferSize? 如果bufferSize大,如1024、4096,则Read / BeginRead块。 如果将bufferSize设置为16,则32不会阻塞。

  • 将bufferSize设置为1是否可以确保没有任何块? 性能影响会很差吗?
  • 看起来将ReadTimeout设置为1000、2000之类的值不会对阻塞产生影响。 还有其他方法可以缩短封锁时间吗? (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); } 

看起来将ReadTimeout设置为1000、2000之类的值不会对阻塞产生影响。

Msdn说,使用异步BeginRead方法时,ReadTimeout无效。

将bufferSize设置为1是否可以确保没有任何块?

不,原因不对。 如果没有通过连接发送单个字节,则无论缓冲区大小如何,Read调用都会阻塞。

性能影响会很差吗?

我猜您在这里谈论的是1字节缓冲区。 这取决于您收到的数据的数量和频率以及在EndRead执行的代码。 在处理具有高带宽的流时,影响可能很大。 您必须尝试在接收数据时观察CPU。

我不太确定您要分别实现什么,而您对阻塞的关注是什么。

当您启动一个具有例如1024个字节的缓冲区的Receive(或Networkstream.Read),并且在套接字上收到10个字节时,Read调用将在短暂的延迟后返回该10个字节,但是直到整个缓冲区被填满后才会阻塞。

还有其他方法可以缩短封锁时间吗?

简而言之你什么意思。 如我所说,即使有很大的缓冲区,当接收少量数据时,读取也不会无限阻塞。

(NoDelay = true不起作用)

那是一个完全不同的故事,但是在发件人一侧将它设置为true可能会很有趣(如果您也可以控制的话)。

设置为false(默认值)时,它将把发送的较小数据块合并为较大的数据块,以减少一个tcp数据包(40字节标头)的开销。

编辑

我的意思是NetworkStream.BeginRead如果没有数据,则立即返回。

关于使用stream.DataAvailable呢? 没有数据时应返回false。

另外,在使用异步模式时,不是在某些事情要做之前调用将被阻塞的预期行为吗? 否则,您将在繁忙的循环中获得主动轮询。

当缓冲区很大时,有时会等待60秒返回(当缓冲区未完全填充或填充到一定量时)

嗯,真不敢相信。 您通过通道发送什么样的数据? 每分钟1个字节? 每秒1000个字节?

暂无
暂无

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

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