c# – 调整缓冲区长度,用于从NetworkStream读取小数据

如何在从TcpClient / NetworkStrem读取小数据时微调bufferSize?

如果bufferSize大到1024,4096读取/ 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);
}

最佳答案

It looks like setting the
ReadTimeout to values like 1000, 2000 has no effect over blocking.

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

Does setting the bufferSize to 1 guarantee there won’t be any blocks?

不,原因不是.如果没有通过连接发送单个字节,则无论bufferize如何,Read调用都将被阻塞.

Will the performance impact be very bad?

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

我不确定你想要分别达到你对阻塞的关注.

当您使用1024字节的缓冲区启动Receive(或Networkstream.Read),并且在套接字上接收10字节时,Read调用将在短暂延迟后返回10字节但在整个缓冲区填满之前不会阻塞.

Is there any other way to make the blocking be short?

你的意思是什么?正如我所说,即使使用大缓冲区,Read也不会在接收少量数据时无休止地阻塞.

(NoDelay = true doesn’t work)

这是一个completely different的故事,但在你的发送者方面设置为真可能很有趣(如果你也控制它).

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

编辑

I mean NetworkStream.BeginRead to return immediately if there is no data.

那么使用stream.DataAvailable呢?没有数据时它应该返回false.

此外,在使用异步模式时,调用将阻塞的预期行为是否有效?否则,您将在繁忙的循环中进行活动轮询.

When the buffer is big it sometimes waits 60 seconds to return (when it is not fully filled or filled to some amount)

嗯,简直不敢相信.您通过频道发送了哪些数据?每分钟1个字节?每秒1000字节?

点赞