Skip to content

Commit

Permalink
几乎所有代码完成剥离Packet,使用IPacket替代
Browse files Browse the repository at this point in the history
  • Loading branch information
nnhy committed Sep 10, 2024
1 parent a7077e4 commit 335140b
Show file tree
Hide file tree
Showing 14 changed files with 531 additions and 236 deletions.
102 changes: 98 additions & 4 deletions NewLife.Core/Data/IPacket.cs
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,11 @@ public static IPacket Append(this IPacket pk, IPacket next)
return pk;
}

/// <summary>附加一个包到当前包链的末尾</summary>
/// <param name="pk"></param>
/// <param name="next"></param>
public static IPacket Append(this IPacket pk, Byte[] next) => Append(pk, new ArrayPacket(next));

/// <summary>转字符串并释放</summary>
/// <param name="pk"></param>
/// <param name="encoding"></param>
Expand Down Expand Up @@ -194,6 +199,48 @@ public static IList<ArraySegment<Byte>> ToSegments(this IPacket pk)

return list;
}

/// <summary>返回字节数组。无差别复制,一定返回新数组</summary>
/// <returns></returns>
public static Byte[] ToArray(this IPacket pk)
{
if (pk.Next == null)
{
if (pk is ArrayPacket ap) return ap.Buffer.ReadBytes(ap.Offset, ap.Length);

return pk.GetSpan().ToArray();
}

// 链式包输出
var ms = Pool.MemoryStream.Get();
pk.CopyTo(ms);

return ms.Return(true);
}

/// <summary>从封包中读取指定数据区,读取全部时直接返回缓冲区,以提升性能</summary>
/// <param name="pk"></param>
/// <param name="offset">相对于数据包的起始位置,实际上是数组的Offset+offset</param>
/// <param name="count">字节个数</param>
/// <returns></returns>
public static Byte[] ReadBytes(this IPacket pk, Int32 offset = 0, Int32 count = -1)
{
// 读取全部
if (offset == 0 && count < 0 && pk is ArrayPacket ap)
{
if (ap.Offset == 0 && (ap.Length < 0 || ap.Offset + ap.Length == ap.Buffer.Length) && ap.Next == null)
return ap.Buffer;
}

if (pk.Next == null)
{
var span = pk.GetSpan();
if (count < 0) count = span.Length - offset;
return span.Slice(offset, count).ToArray();
}

return pk.ToArray().ReadBytes(offset, count);
}
}

/// <summary>所有权内存包。具有所有权管理,不再使用时释放</summary>
Expand Down Expand Up @@ -395,10 +442,10 @@ public struct ArrayPacket : IDisposable, IPacket
/// <summary>数据长度</summary>
public Int32 Length => _length;

/// <summary>获取/设置 指定位置的字节</summary>
/// <param name="index"></param>
/// <returns></returns>
public Byte this[Int32 index] { get => _buffer[_offset + index]; set => _buffer[_offset + index] = value; }
///// <summary>获取/设置 指定位置的字节</summary>
///// <param name="index"></param>
///// <returns></returns>
//public Byte this[Int32 index] { get => _buffer[_offset + index]; set => _buffer[_offset + index] = value; }

/// <summary>是否拥有管理权。Dispose时,若有管理权则还给池里</summary>
public Boolean HasOwner { get; set; }
Expand All @@ -410,6 +457,53 @@ public struct ArrayPacket : IDisposable, IPacket
public Int32 Total => Length + (Next?.Total ?? 0);
#endregion

#region 索引
/// <summary>获取/设置 指定位置的字节</summary>
/// <param name="index"></param>
/// <returns></returns>
public Byte this[Int32 index]
{
get
{
// 超过下标直接报错,谁也不想处理了异常的数据也不知道
if (index < 0) throw new IndexOutOfRangeException($"Index [{index}] is out of bounds");

var p = Offset + index;
if (p >= Offset + _length)
{
if (Next == null) throw new IndexOutOfRangeException($"Index [{index}] is out of bounds [>{Total - 1}]");

return Next[index - _length];
}

return Buffer[p];

// Offset 至 Offset+Count 代表了当前链的可用数据区
// Count 是当前链的实际可用数据长度,(而用 Data.Length 是不准确的,Data的数据不是全部可用),
// 所以 这里通过索引取整个链表的索引数据应该用 Count 作运算.
}
set
{
if (index < 0) throw new IndexOutOfRangeException($"Index [{index}] is out of bounds");

// 设置 对应索引 的数据 应该也是针对整个链表的有效数据区
var p = Offset + index;
if (index >= _length)
{
if (Next == null) throw new IndexOutOfRangeException($"Index [{index}] is out of bounds [>{Total - 1}]");

Next[p - Buffer.Length] = value;
}
else
{
Buffer[p] = value;
}

// 基础类需要严谨给出明确功用,不能模棱两可,因此不能越界
}
}
#endregion

/// <summary>通过指定字节数组来实例化数据包</summary>
/// <param name="buf"></param>
/// <param name="offset"></param>
Expand Down
4 changes: 2 additions & 2 deletions NewLife.Core/Data/IPacketEncoder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -70,8 +70,8 @@ public virtual IPacket Encode(Object value)
try
{
if (type == typeof(IPacket)) return data;
if (type == typeof(Packet)) return data is Packet pk ? pk : data.GetSpan().ToArray();
if (type == typeof(Byte[])) return data.GetSpan().ToArray();
if (type == typeof(Packet)) return data is Packet pk ? pk : data.ReadBytes();
if (type == typeof(Byte[])) return data.ReadBytes();
if (type.As<IAccessor>()) return type.AccessorRead(data);

// 可空类型
Expand Down
4 changes: 2 additions & 2 deletions NewLife.Core/Data/Packet.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ public class Packet : IPacket
/// <summary>长度</summary>
public Int32 Count { get; private set; }

Int32 IPacket.Length => Total;
Int32 IPacket.Length => Count;

/// <summary>下一个链式包</summary>
public Packet? Next { get; set; }
Expand Down Expand Up @@ -290,7 +290,7 @@ public virtual Byte[] ToArray()
{
//if (Offset == 0 && (Count < 0 || Offset + Count == Data.Length) && Next == null) return Data;

if (Next == null) Data.ReadBytes(Offset, Count);
if (Next == null) return Data.ReadBytes(Offset, Count);

// 链式包输出
var ms = Pool.MemoryStream.Get();
Expand Down
7 changes: 1 addition & 6 deletions NewLife.Core/Http/HttpResponse.cs
Original file line number Diff line number Diff line change
Expand Up @@ -108,12 +108,7 @@ public void SetResult(Object result, String? contentType = null)

StatusDescription = ex.Message;
}
else if (result is IPacket pk2)
{
if (contentType.IsNullOrEmpty()) contentType = "application/octet-stream";
Body = pk2;
}
else if (result is Packet pk)
else if (result is IPacket pk)
{
if (contentType.IsNullOrEmpty()) contentType = "application/octet-stream";
Body = pk;
Expand Down
4 changes: 2 additions & 2 deletions NewLife.Core/IO/EasyClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ protected virtual ApiHttpClient GetClient()
/// <param name="data"></param>
/// <returns></returns>
/// <exception cref="ArgumentNullException"></exception>
public virtual async Task<IObjectInfo?> Put(String id, Packet data)
public virtual async Task<IObjectInfo?> Put(String id, IPacket data)
{
if (id.IsNullOrEmpty()) throw new ArgumentNullException(nameof(id));

Expand All @@ -99,7 +99,7 @@ protected virtual ApiHttpClient GetClient()
if (id.IsNullOrEmpty()) throw new ArgumentNullException(nameof(id));

var client = GetClient();
var rs = await client.GetAsync<Packet>(BaseAction + "Get", new { id });
var rs = await client.GetAsync<IPacket>(BaseAction + "Get", new { id });
if (rs == null) return null;

return new ObjectInfo { Name = id, Data = rs };
Expand Down
4 changes: 2 additions & 2 deletions NewLife.Core/IO/IObjectInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ public interface IObjectInfo
Boolean IsDirectory { get; set; }

/// <summary>数据</summary>
Packet? Data { get; set; }
IPacket? Data { get; set; }
}

/// <summary>对象信息。代表文件存储对象,或者磁盘文件,也可以是目录</summary>
Expand All @@ -39,5 +39,5 @@ public class ObjectInfo : IObjectInfo
public Boolean IsDirectory { get; set; }

/// <summary>数据</summary>
public Packet? Data { get; set; }
public IPacket? Data { get; set; }
}
2 changes: 1 addition & 1 deletion NewLife.Core/IO/IObjectStorage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ public interface IObjectStorage
/// <param name="id">对象文件名。可以为空,此时自动生成文件名</param>
/// <param name="data">数据内容</param>
/// <returns>可能是自动生成的新文件名</returns>
Task<IObjectInfo?> Put(String id, Packet data);
Task<IObjectInfo?> Put(String id, IPacket data);

/// <summary>删除文件对象</summary>
/// <param name="id">对象文件名</param>
Expand Down
3 changes: 2 additions & 1 deletion NewLife.Core/Net/ReceivedEventArgs.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ public class ReceivedEventArgs : EventArgs, IData
#region 属性
/// <summary>原始数据包</summary>
/// <remarks>
/// Packet内部的Data可能是网络缓冲区,并非全部数据都属于当前消息,需要ReadBytes得到有效数据。
/// Packet内部直接引用网络缓冲区,以实现零拷贝,并非全部数据都属于当前消息。
/// 需要注意所有权,当前数据事件结束时回收,不应被外部引用。
/// </remarks>
public IPacket? Packet { get; set; }

Expand Down
10 changes: 5 additions & 5 deletions NewLife.Core/Yun/OssClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -200,14 +200,14 @@ private void SetBucket(String? bucketName)
/// <param name="objectName">对象文件名</param>
/// <param name="data">数据内容</param>
/// <returns></returns>
public async Task<IObjectInfo?> Put(String objectName, Packet data)
public async Task<IObjectInfo?> Put(String objectName, IPacket data)
{
SetBucket(BucketName);

var content = data.Next == null ?
new ByteArrayContent(data.Data, data.Offset, data.Count) :
var content = data.Next == null && data is ArrayPacket ap ?
new ByteArrayContent(ap.Buffer, ap.Offset, ap.Length) :
new ByteArrayContent(data.ReadBytes());
var rs = await InvokeAsync<Packet>(HttpMethod.Put, "/" + objectName, content);
var rs = await InvokeAsync<IPacket>(HttpMethod.Put, "/" + objectName, content);

return new ObjectInfo { Name = objectName, Data = rs };
}
Expand All @@ -219,7 +219,7 @@ private void SetBucket(String? bucketName)
{
SetBucket(BucketName);

var rs = await InvokeAsync<Packet>(HttpMethod.Get, "/" + objectName);
var rs = await InvokeAsync<IPacket>(HttpMethod.Get, "/" + objectName);

return new ObjectInfo { Name = objectName, Data = rs };
}
Expand Down
2 changes: 1 addition & 1 deletion Samples/Zero.HttpServer/ClientTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ public static async Task WebSocketTest()

var buf = new Byte[1024];
var rs = await client.ReceiveAsync(buf, default);
XTrace.WriteLine(new Packet(buf, 0, rs.Count).ToStr());
XTrace.WriteLine(new Span<Byte>(buf, 0, rs.Count).ToStr());

// 关闭连接
await client.CloseAsync(WebSocketCloseStatus.NormalClosure, "通信完成", default);
Expand Down
Loading

0 comments on commit 335140b

Please sign in to comment.