[fix] 修正Redis响应数据超过8192时,读取出现死循环的问题。close: https://github.com/NewLifeX/NewLife.Redis/issues/149

This commit is contained in:
大石头 2025-02-08 23:24:52 +08:00
parent bafbdbe32f
commit e4705f8685
3 changed files with 27 additions and 6 deletions

View File

@ -72,8 +72,9 @@ public ref struct BufferedReader
var remain = FreeCapacity;
if (remain < size)
{
// 申请指定大小的数据包缓冲区,实际大小可能更大
var idx = 0;
var pk = new OwnerPacket(_bufferSize);
var pk = new OwnerPacket(size <= _bufferSize ? _bufferSize : size);
if (_data != null && remain > 0)
{
if (!_data.TryGetArray(out var arr)) throw new NotSupportedException();
@ -90,8 +91,10 @@ public ref struct BufferedReader
//var n = _stream.ReadExactly(pk.Buffer, pk.Offset + idx, pk.Length - idx);
while (idx < size)
{
var n = _stream.Read(pk.Buffer, pk.Offset + idx, pk.Length - idx);
if (n < 0) break;
// 实际缓冲区大小可能大于申请大小,充分利用缓冲区,避免多次读取
var len = pk.Buffer.Length - pk.Offset;
var n = _stream.Read(pk.Buffer, pk.Offset + idx, len - idx);
if (n <= 0) break;
idx += n;
}

View File

@ -577,11 +577,11 @@ public class RedisClient : DisposeBase
return null;
}
if (len <= 0) return null;
len += 2;
// 读取数据包,并跳过换行符
var pk = reader.ReadPacket(len - 2);
reader.Advance(2);
var pk = reader.ReadPacket(len);
if (reader.FreeCapacity >= 2) reader.Advance(2);
return pk;
}

View File

@ -294,6 +294,24 @@ public class RedisTest
Assert.Equal(pk.ToHex(), pk2.ToHex());
}
/// <summary>超大数据包</summary>
/// <remarks>https://github.com/NewLifeX/NewLife.Redis/issues/149</remarks>
[TestOrder(31)]
[Fact(DisplayName = "超大数据包")]
public void TestBigPacket()
{
var ic = _redis;
var key = "buf";
var buf = Rand.NextBytes(8192 + 1);
var pk = new ArrayPacket(buf);
ic.Set(key, pk);
var pk2 = ic.Get<IPacket>(key);
Assert.Equal(pk.ToHex(), pk2.ToHex());
}
[TestOrder(40)]
[Fact(DisplayName = "管道")]
public void TestPipeline()