NetWork
This commit is contained in:
ALEXTANG
2022-08-29 20:34:39 +08:00
parent ce1eab346b
commit 7158915169
77 changed files with 4539 additions and 1 deletions

View File

@@ -0,0 +1,211 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Runtime.InteropServices;
namespace TEngine.Runtime
{
/// <summary>
/// 游戏框架链表范围。
/// </summary>
/// <typeparam name="T">指定链表范围的元素类型。</typeparam>
[StructLayout(LayoutKind.Auto)]
public struct LinkedListRange<T> : IEnumerable<T>, IEnumerable
{
private readonly LinkedListNode<T> m_First;
private readonly LinkedListNode<T> m_Terminal;
/// <summary>
/// 初始化游戏框架链表范围的新实例。
/// </summary>
/// <param name="first">链表范围的开始结点。</param>
/// <param name="terminal">链表范围的终结标记结点。</param>
public LinkedListRange(LinkedListNode<T> first, LinkedListNode<T> terminal)
{
if (first == null || terminal == null || first == terminal)
{
throw new Exception("Range is invalid.");
}
m_First = first;
m_Terminal = terminal;
}
/// <summary>
/// 获取链表范围是否有效。
/// </summary>
public bool IsValid
{
get
{
return m_First != null && m_Terminal != null && m_First != m_Terminal;
}
}
/// <summary>
/// 获取链表范围的开始结点。
/// </summary>
public LinkedListNode<T> First
{
get
{
return m_First;
}
}
/// <summary>
/// 获取链表范围的终结标记结点。
/// </summary>
public LinkedListNode<T> Terminal
{
get
{
return m_Terminal;
}
}
/// <summary>
/// 获取链表范围的结点数量。
/// </summary>
public int Count
{
get
{
if (!IsValid)
{
return 0;
}
int count = 0;
for (LinkedListNode<T> current = m_First; current != null && current != m_Terminal; current = current.Next)
{
count++;
}
return count;
}
}
/// <summary>
/// 检查是否包含指定值。
/// </summary>
/// <param name="value">要检查的值。</param>
/// <returns>是否包含指定值。</returns>
public bool Contains(T value)
{
for (LinkedListNode<T> current = m_First; current != null && current != m_Terminal; current = current.Next)
{
if (current.Value.Equals(value))
{
return true;
}
}
return false;
}
/// <summary>
/// 返回循环访问集合的枚举数。
/// </summary>
/// <returns>循环访问集合的枚举数。</returns>
public Enumerator GetEnumerator()
{
return new Enumerator(this);
}
/// <summary>
/// 返回循环访问集合的枚举数。
/// </summary>
/// <returns>循环访问集合的枚举数。</returns>
IEnumerator<T> IEnumerable<T>.GetEnumerator()
{
return GetEnumerator();
}
/// <summary>
/// 返回循环访问集合的枚举数。
/// </summary>
/// <returns>循环访问集合的枚举数。</returns>
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
/// <summary>
/// 循环访问集合的枚举数。
/// </summary>
[StructLayout(LayoutKind.Auto)]
public struct Enumerator : IEnumerator<T>, IEnumerator
{
private readonly LinkedListRange<T> _mLinkedListRange;
private LinkedListNode<T> m_Current;
private T m_CurrentValue;
internal Enumerator(LinkedListRange<T> range)
{
if (!range.IsValid)
{
throw new Exception("Range is invalid.");
}
_mLinkedListRange = range;
m_Current = _mLinkedListRange.m_First;
m_CurrentValue = default(T);
}
/// <summary>
/// 获取当前结点。
/// </summary>
public T Current
{
get
{
return m_CurrentValue;
}
}
/// <summary>
/// 获取当前的枚举数。
/// </summary>
object IEnumerator.Current
{
get
{
return m_CurrentValue;
}
}
/// <summary>
/// 清理枚举数。
/// </summary>
public void Dispose()
{
}
/// <summary>
/// 获取下一个结点。
/// </summary>
/// <returns>返回下一个结点。</returns>
public bool MoveNext()
{
if (m_Current == null || m_Current == _mLinkedListRange.m_Terminal)
{
return false;
}
m_CurrentValue = m_Current.Value;
m_Current = m_Current.Next;
return true;
}
/// <summary>
/// 重置枚举数。
/// </summary>
void IEnumerator.Reset()
{
m_Current = _mLinkedListRange.m_First;
m_CurrentValue = default(T);
}
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: ae8aa6552d5da4247996a9f313b9cdc7
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,277 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Runtime.InteropServices;
namespace TEngine.Runtime
{
/// <summary>
/// 游戏框架多值字典类。
/// </summary>
/// <typeparam name="TKey">指定多值字典的主键类型。</typeparam>
/// <typeparam name="TValue">指定多值字典的值类型。</typeparam>
public sealed class MultiDictionary<TKey, TValue> : IEnumerable<KeyValuePair<TKey, LinkedListRange<TValue>>>, IEnumerable
{
private readonly LinkedList<TValue> m_LinkedList;
private readonly Dictionary<TKey, LinkedListRange<TValue>> m_Dictionary;
/// <summary>
/// 初始化游戏框架多值字典类的新实例。
/// </summary>
public MultiDictionary()
{
m_LinkedList = new LinkedList<TValue>();
m_Dictionary = new Dictionary<TKey, LinkedListRange<TValue>>();
}
/// <summary>
/// 获取多值字典中实际包含的主键数量。
/// </summary>
public int Count
{
get
{
return m_Dictionary.Count;
}
}
/// <summary>
/// 获取多值字典中指定主键的范围。
/// </summary>
/// <param name="key">指定的主键。</param>
/// <returns>指定主键的范围。</returns>
public LinkedListRange<TValue> this[TKey key]
{
get
{
LinkedListRange<TValue> range = default(LinkedListRange<TValue>);
m_Dictionary.TryGetValue(key, out range);
return range;
}
}
/// <summary>
/// 清理多值字典。
/// </summary>
public void Clear()
{
m_Dictionary.Clear();
m_LinkedList.Clear();
}
/// <summary>
/// 检查多值字典中是否包含指定主键。
/// </summary>
/// <param name="key">要检查的主键。</param>
/// <returns>多值字典中是否包含指定主键。</returns>
public bool Contains(TKey key)
{
return m_Dictionary.ContainsKey(key);
}
/// <summary>
/// 检查多值字典中是否包含指定值。
/// </summary>
/// <param name="key">要检查的主键。</param>
/// <param name="value">要检查的值。</param>
/// <returns>多值字典中是否包含指定值。</returns>
public bool Contains(TKey key, TValue value)
{
LinkedListRange<TValue> range = default(LinkedListRange<TValue>);
if (m_Dictionary.TryGetValue(key, out range))
{
return range.Contains(value);
}
return false;
}
/// <summary>
/// 尝试获取多值字典中指定主键的范围。
/// </summary>
/// <param name="key">指定的主键。</param>
/// <param name="range">指定主键的范围。</param>
/// <returns>是否获取成功。</returns>
public bool TryGetValue(TKey key, out LinkedListRange<TValue> range)
{
return m_Dictionary.TryGetValue(key, out range);
}
/// <summary>
/// 向指定的主键增加指定的值。
/// </summary>
/// <param name="key">指定的主键。</param>
/// <param name="value">指定的值。</param>
public void Add(TKey key, TValue value)
{
LinkedListRange<TValue> range = default(LinkedListRange<TValue>);
if (m_Dictionary.TryGetValue(key, out range))
{
m_LinkedList.AddBefore(range.Terminal, value);
}
else
{
LinkedListNode<TValue> first = m_LinkedList.AddLast(value);
LinkedListNode<TValue> terminal = m_LinkedList.AddLast(default(TValue));
m_Dictionary.Add(key, new LinkedListRange<TValue>(first, terminal));
}
}
/// <summary>
/// 从指定的主键中移除指定的值。
/// </summary>
/// <param name="key">指定的主键。</param>
/// <param name="value">指定的值。</param>
/// <returns>是否移除成功。</returns>
public bool Remove(TKey key, TValue value)
{
LinkedListRange<TValue> range = default(LinkedListRange<TValue>);
if (m_Dictionary.TryGetValue(key, out range))
{
for (LinkedListNode<TValue> current = range.First; current != null && current != range.Terminal; current = current.Next)
{
if (current.Value.Equals(value))
{
if (current == range.First)
{
LinkedListNode<TValue> next = current.Next;
if (next == range.Terminal)
{
m_LinkedList.Remove(next);
m_Dictionary.Remove(key);
}
else
{
m_Dictionary[key] = new LinkedListRange<TValue>(next, range.Terminal);
}
}
m_LinkedList.Remove(current);
return true;
}
}
}
return false;
}
/// <summary>
/// 从指定的主键中移除所有的值。
/// </summary>
/// <param name="key">指定的主键。</param>
/// <returns>是否移除成功。</returns>
public bool RemoveAll(TKey key)
{
LinkedListRange<TValue> range = default(LinkedListRange<TValue>);
if (m_Dictionary.TryGetValue(key, out range))
{
m_Dictionary.Remove(key);
LinkedListNode<TValue> current = range.First;
while (current != null)
{
LinkedListNode<TValue> next = current != range.Terminal ? current.Next : null;
m_LinkedList.Remove(current);
current = next;
}
return true;
}
return false;
}
/// <summary>
/// 返回循环访问集合的枚举数。
/// </summary>
/// <returns>循环访问集合的枚举数。</returns>
public Enumerator GetEnumerator()
{
return new Enumerator(m_Dictionary);
}
/// <summary>
/// 返回循环访问集合的枚举数。
/// </summary>
/// <returns>循环访问集合的枚举数。</returns>
IEnumerator<KeyValuePair<TKey, LinkedListRange<TValue>>> IEnumerable<KeyValuePair<TKey, LinkedListRange<TValue>>>.GetEnumerator()
{
return GetEnumerator();
}
/// <summary>
/// 返回循环访问集合的枚举数。
/// </summary>
/// <returns>循环访问集合的枚举数。</returns>
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
/// <summary>
/// 循环访问集合的枚举数。
/// </summary>
[StructLayout(LayoutKind.Auto)]
public struct Enumerator : IEnumerator<KeyValuePair<TKey, LinkedListRange<TValue>>>, IEnumerator
{
private Dictionary<TKey, LinkedListRange<TValue>>.Enumerator m_Enumerator;
internal Enumerator(Dictionary<TKey, LinkedListRange<TValue>> dictionary)
{
if (dictionary == null)
{
throw new Exception("Dictionary is invalid.");
}
m_Enumerator = dictionary.GetEnumerator();
}
/// <summary>
/// 获取当前结点。
/// </summary>
public KeyValuePair<TKey, LinkedListRange<TValue>> Current
{
get
{
return m_Enumerator.Current;
}
}
/// <summary>
/// 获取当前的枚举数。
/// </summary>
object IEnumerator.Current
{
get
{
return m_Enumerator.Current;
}
}
/// <summary>
/// 清理枚举数。
/// </summary>
public void Dispose()
{
m_Enumerator.Dispose();
}
/// <summary>
/// 获取下一个结点。
/// </summary>
/// <returns>返回下一个结点。</returns>
public bool MoveNext()
{
return m_Enumerator.MoveNext();
}
/// <summary>
/// 重置枚举数。
/// </summary>
void IEnumerator.Reset()
{
((IEnumerator<KeyValuePair<TKey, LinkedListRange<TValue>>>)m_Enumerator).Reset();
}
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 3eff6e3b9f51d4e48a6e454d268538de
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -690,5 +690,4 @@ namespace TEngine.Runtime
} }
#endregion #endregion
} }
} }

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 69740261aa305b94aa6a2a717d82d8e4
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,23 @@
namespace TEngine.Runtime
{
/// <summary>
/// 网络地址类型。
/// </summary>
public enum AddressFamily : byte
{
/// <summary>
/// 未知。
/// </summary>
Unknown = 0,
/// <summary>
/// IP 版本 4。
/// </summary>
IPv4,
/// <summary>
/// IP 版本 6。
/// </summary>
IPv6
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 6f0c907c7aeb4bd2a19ff78ad8e8b668
timeCreated: 1661772419

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 2c4f37bbaa3a4ae45a5aa851ec78c3d0
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 1b7b82bd3d86d874c978bebc6147b442
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,19 @@
using System;
namespace TEngine.Runtime
{
public abstract class NetBaseEventArgs : EventArgs, IMemory
{
/// <summary>
/// 初始化构造函数
/// </summary>
public NetBaseEventArgs()
{
}
/// <summary>
/// 清理引用。
/// </summary>
public abstract void Clear();
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: dd227169d1cedc64ba3c1454671bca7d
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,61 @@
namespace TEngine.Runtime
{
/// <summary>
/// 网络连接关闭事件。
/// </summary>
public sealed class NetworkClosedEventArgs : GameEventArgs
{
/// <summary>
/// 网络连接关闭事件编号。
/// </summary>
public static readonly int EventId = typeof(NetworkClosedEventArgs).GetHashCode();
/// <summary>
/// 初始化网络连接关闭事件的新实例。
/// </summary>
public NetworkClosedEventArgs()
{
NetworkChannel = null;
}
/// <summary>
/// 获取网络连接关闭事件编号。
/// </summary>
public override int Id
{
get
{
return EventId;
}
}
/// <summary>
/// 获取网络频道。
/// </summary>
public INetworkChannel NetworkChannel
{
get;
private set;
}
/// <summary>
/// 创建网络连接关闭事件。
/// </summary>
/// <param name="networkChannel">网络频道。</param>
/// <returns>创建的网络连接关闭事件。</returns>
public static NetworkClosedEventArgs Create(INetworkChannel networkChannel)
{
NetworkClosedEventArgs networkClosedEventArgs = MemoryPool.Acquire<NetworkClosedEventArgs>();
networkClosedEventArgs.NetworkChannel = networkChannel;
return networkClosedEventArgs;
}
/// <summary>
/// 清理网络连接关闭事件。
/// </summary>
public override void Clear()
{
NetworkChannel = null;
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 6218d5320c6b4a328df908e68d135177
timeCreated: 1661772187

View File

@@ -0,0 +1,74 @@
namespace TEngine.Runtime
{
/// <summary>
/// 网络连接成功事件。
/// </summary>
public sealed class NetworkConnectedEventArgs : GameEventArgs
{
/// <summary>
/// 网络连接成功事件编号。
/// </summary>
public static readonly int EventId = typeof(NetworkConnectedEventArgs).GetHashCode();
/// <summary>
/// 初始化网络连接成功事件的新实例。
/// </summary>
public NetworkConnectedEventArgs()
{
NetworkChannel = null;
UserData = null;
}
/// <summary>
/// 获取网络连接成功事件编号。
/// </summary>
public override int Id
{
get
{
return EventId;
}
}
/// <summary>
/// 获取网络频道。
/// </summary>
public INetworkChannel NetworkChannel
{
get;
private set;
}
/// <summary>
/// 获取用户自定义数据。
/// </summary>
public object UserData
{
get;
private set;
}
/// <summary>
/// 创建网络连接成功事件。
/// </summary>
/// <param name="networkChannel">网络频道。</param>
/// <param name="userData">用户自定义数据。</param>
/// <returns>创建的网络连接成功事件。</returns>
public static NetworkConnectedEventArgs Create(INetworkChannel networkChannel)
{
NetworkConnectedEventArgs networkConnectedEventArgs = MemoryPool.Acquire<NetworkConnectedEventArgs>();
networkConnectedEventArgs.NetworkChannel = networkChannel;
networkConnectedEventArgs.UserData = null;
return networkConnectedEventArgs;
}
/// <summary>
/// 清理网络连接成功事件。
/// </summary>
public override void Clear()
{
NetworkChannel = null;
UserData = null;
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 64fffbe4a72442f0b3bbd81f78509b13
timeCreated: 1661772223

View File

@@ -0,0 +1,74 @@
namespace TEngine.Runtime
{
/// <summary>
/// 用户自定义网络错误事件。
/// </summary>
public sealed class NetworkCustomErrorEventArgs : GameEventArgs
{
/// <summary>
/// 用户自定义网络错误事件编号。
/// </summary>
public static readonly int EventId = typeof(NetworkCustomErrorEventArgs).GetHashCode();
/// <summary>
/// 初始化用户自定义网络错误事件的新实例。
/// </summary>
public NetworkCustomErrorEventArgs()
{
NetworkChannel = null;
CustomErrorData = null;
}
/// <summary>
/// 获取用户自定义网络错误事件编号。
/// </summary>
public override int Id
{
get
{
return EventId;
}
}
/// <summary>
/// 获取网络频道。
/// </summary>
public INetworkChannel NetworkChannel
{
get;
private set;
}
/// <summary>
/// 获取用户自定义错误数据。
/// </summary>
public object CustomErrorData
{
get;
private set;
}
/// <summary>
/// 创建用户自定义网络错误事件。
/// </summary>
/// <param name="networkChannel">网络频道。</param>
/// <param name="customErrorData">用户自定义错误数据。</param>
/// <returns>创建的用户自定义网络错误事件。</returns>
public static NetworkCustomErrorEventArgs Create(INetworkChannel networkChannel, object customErrorData)
{
NetworkCustomErrorEventArgs networkCustomErrorEventArgs = MemoryPool.Acquire<NetworkCustomErrorEventArgs>();
networkCustomErrorEventArgs.NetworkChannel = networkChannel;
networkCustomErrorEventArgs.CustomErrorData = customErrorData;
return networkCustomErrorEventArgs;
}
/// <summary>
/// 清理用户自定义网络错误事件。
/// </summary>
public override void Clear()
{
NetworkChannel = null;
CustomErrorData = null;
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 6947eca0814140a6a7fc564274cdb804
timeCreated: 1661772258

View File

@@ -0,0 +1,102 @@
using System.Net.Sockets;
namespace TEngine.Runtime
{
/// <summary>
/// 网络错误事件。
/// </summary>
public sealed class NetworkErrorEventArgs : GameEventArgs
{
/// <summary>
/// 网络错误事件编号。
/// </summary>
public static readonly int EventId = typeof(NetworkErrorEventArgs).GetHashCode();
/// <summary>
/// 初始化网络错误事件的新实例。
/// </summary>
public NetworkErrorEventArgs()
{
NetworkChannel = null;
ErrorCode = NetworkErrorCode.Unknown;
SocketErrorCode = SocketError.Success;
ErrorMessage = null;
}
/// <summary>
/// 获取网络错误事件编号。
/// </summary>
public override int Id
{
get
{
return EventId;
}
}
/// <summary>
/// 获取网络频道。
/// </summary>
public INetworkChannel NetworkChannel
{
get;
private set;
}
/// <summary>
/// 获取错误码。
/// </summary>
public NetworkErrorCode ErrorCode
{
get;
private set;
}
/// <summary>
/// 获取 Socket 错误码。
/// </summary>
public SocketError SocketErrorCode
{
get;
private set;
}
/// <summary>
/// 获取错误信息。
/// </summary>
public string ErrorMessage
{
get;
private set;
}
/// <summary>
/// 创建网络错误事件。
/// </summary>
/// <param name="networkChannel">网络频道。</param>
/// <param name="errorCode">错误码。</param>
/// <param name="socketErrorCode">Socket 错误码。</param>
/// <param name="errorMessage">错误信息。</param>
/// <returns>创建的网络错误事件。</returns>
public static NetworkErrorEventArgs Create(INetworkChannel networkChannel, NetworkErrorCode errorCode, SocketError socketErrorCode, string errorMessage)
{
NetworkErrorEventArgs networkErrorEventArgs = MemoryPool.Acquire<NetworkErrorEventArgs>();
networkErrorEventArgs.NetworkChannel = networkChannel;
networkErrorEventArgs.ErrorCode = errorCode;
networkErrorEventArgs.SocketErrorCode = socketErrorCode;
networkErrorEventArgs.ErrorMessage = errorMessage;
return networkErrorEventArgs;
}
/// <summary>
/// 清理网络错误事件。
/// </summary>
public override void Clear()
{
NetworkChannel = null;
ErrorCode = NetworkErrorCode.Unknown;
SocketErrorCode = SocketError.Success;
ErrorMessage = null;
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 7f64b74fa985459b88f908ff182e8672
timeCreated: 1661772293

View File

@@ -0,0 +1,74 @@
namespace TEngine.Runtime
{
/// <summary>
/// 网络心跳包丢失事件。
/// </summary>
public sealed class NetworkMissHeartBeatEventArgs : GameEventArgs
{
/// <summary>
/// 网络心跳包丢失事件编号。
/// </summary>
public static readonly int EventId = typeof(NetworkMissHeartBeatEventArgs).GetHashCode();
/// <summary>
/// 初始化网络心跳包丢失事件的新实例。
/// </summary>
public NetworkMissHeartBeatEventArgs()
{
NetworkChannel = null;
MissCount = 0;
}
/// <summary>
/// 获取网络心跳包丢失事件编号。
/// </summary>
public override int Id
{
get
{
return EventId;
}
}
/// <summary>
/// 获取网络频道。
/// </summary>
public INetworkChannel NetworkChannel
{
get;
private set;
}
/// <summary>
/// 获取心跳包已丢失次数。
/// </summary>
public int MissCount
{
get;
private set;
}
/// <summary>
/// 创建网络心跳包丢失事件。
/// </summary>
/// <param name="networkChannel">网络频道。</param>
/// <param name="missCount">心跳包已丢失次数。</param>
/// <returns>创建的网络心跳包丢失事件。</returns>
public static NetworkMissHeartBeatEventArgs Create(INetworkChannel networkChannel, int missCount)
{
NetworkMissHeartBeatEventArgs networkMissHeartBeatEventArgs = MemoryPool.Acquire<NetworkMissHeartBeatEventArgs>();
networkMissHeartBeatEventArgs.NetworkChannel = networkChannel;
networkMissHeartBeatEventArgs.MissCount = missCount;
return networkMissHeartBeatEventArgs;
}
/// <summary>
/// 清理网络心跳包丢失事件。
/// </summary>
public override void Clear()
{
NetworkChannel = null;
MissCount = 0;
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: c2dc35d1fb8047e3b86f4af42124aa06
timeCreated: 1661772338

View File

@@ -0,0 +1,130 @@
using System;
namespace TEngine.Runtime
{
/// <summary>
/// 事件管理器。
/// </summary>
internal sealed class EventManager: IEventManager
{
private readonly EventPool<GameEventArgs> m_EventPool;
/// <summary>
/// 初始化事件管理器的新实例。
/// </summary>
public EventManager()
{
m_EventPool = new EventPool<GameEventArgs>(EventPoolMode.AllowNoHandler | EventPoolMode.AllowMultiHandler);
}
/// <summary>
/// 获取事件处理函数的数量。
/// </summary>
public int EventHandlerCount
{
get
{
return m_EventPool.EventHandlerCount;
}
}
/// <summary>
/// 获取事件数量。
/// </summary>
public int EventCount
{
get
{
return m_EventPool.EventCount;
}
}
/// <summary>
/// 事件管理器轮询。
/// </summary>
/// <param name="elapseSeconds">逻辑流逝时间,以秒为单位。</param>
/// <param name="realElapseSeconds">真实流逝时间,以秒为单位。</param>
internal void Update(float elapseSeconds, float realElapseSeconds)
{
m_EventPool.Update(elapseSeconds, realElapseSeconds);
}
/// <summary>
/// 关闭并清理事件管理器。
/// </summary>
internal void Shutdown()
{
m_EventPool.Shutdown();
}
/// <summary>
/// 获取事件处理函数的数量。
/// </summary>
/// <param name="id">事件类型编号。</param>
/// <returns>事件处理函数的数量。</returns>
public int Count(int id)
{
return m_EventPool.Count(id);
}
/// <summary>
/// 检查是否存在事件处理函数。
/// </summary>
/// <param name="id">事件类型编号。</param>
/// <param name="handler">要检查的事件处理函数。</param>
/// <returns>是否存在事件处理函数。</returns>
public bool Check(int id, EventHandler<GameEventArgs> handler)
{
return m_EventPool.Check(id, handler);
}
/// <summary>
/// 订阅事件处理函数。
/// </summary>
/// <param name="id">事件类型编号。</param>
/// <param name="handler">要订阅的事件处理函数。</param>
public void Subscribe(int id, EventHandler<GameEventArgs> handler)
{
m_EventPool.Subscribe(id, handler);
}
/// <summary>
/// 取消订阅事件处理函数。
/// </summary>
/// <param name="id">事件类型编号。</param>
/// <param name="handler">要取消订阅的事件处理函数。</param>
public void Unsubscribe(int id, EventHandler<GameEventArgs> handler)
{
m_EventPool.Unsubscribe(id, handler);
}
/// <summary>
/// 设置默认事件处理函数。
/// </summary>
/// <param name="handler">要设置的默认事件处理函数。</param>
public void SetDefaultHandler(EventHandler<GameEventArgs> handler)
{
m_EventPool.SetDefaultHandler(handler);
}
/// <summary>
/// 抛出事件,这个操作是线程安全的,即使不在主线程中抛出,也可保证在主线程中回调事件处理函数,但事件会在抛出后的下一帧分发。
/// </summary>
/// <param name="sender">事件源。</param>
/// <param name="e">事件参数。</param>
public void Fire(object sender, GameEventArgs e)
{
m_EventPool.Fire(sender, e);
}
/// <summary>
/// 抛出事件立即模式,这个操作不是线程安全的,事件会立刻分发。
/// </summary>
/// <param name="sender">事件源。</param>
/// <param name="e">事件参数。</param>
public void FireNow(object sender, GameEventArgs e)
{
m_EventPool.FireNow(sender, e);
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 5caf443f519944048edbf1bea889f6d2
timeCreated: 1661775799

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 4b813480944c71f47a87c3facb84bce2
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,31 @@
using System;
namespace TEngine.Runtime
{
/// <summary>
/// 事件基类。
/// </summary>
public abstract class BaseEventArgs : EventArgs, IMemory
{
/// <summary>
/// 构造函数
/// </summary>
public BaseEventArgs()
{
}
/// <summary>
/// 获取类型编号。
/// </summary>
public abstract int Id
{
get;
}
/// <summary>
/// 清理引用。
/// </summary>
public abstract void Clear();
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 996eb2d764ee87b45a2d2aab7b88e148
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,50 @@
namespace TEngine.Runtime
{
internal sealed partial class EventPool<T> where T : BaseEventArgs
{
/// <summary>
/// 事件结点。
/// </summary>
private sealed class Event : IMemory
{
private object m_Sender;
private T m_EventArgs;
public Event()
{
m_Sender = null;
m_EventArgs = null;
}
public object Sender
{
get
{
return m_Sender;
}
}
public T EventArgs
{
get
{
return m_EventArgs;
}
}
public static Event Create(object sender, T e)
{
Event eventNode = MemoryPool.Acquire<Event>();
eventNode.m_Sender = sender;
eventNode.m_EventArgs = e;
return eventNode;
}
public void Clear()
{
m_Sender = null;
m_EventArgs = null;
}
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 342958da5a55f9647a13c573988bdec5
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,278 @@
using System;
using System.Collections.Generic;
namespace TEngine.Runtime
{
/// <summary>
/// 事件池。
/// </summary>
/// <typeparam name="T">事件类型。</typeparam>
internal sealed partial class EventPool<T> where T : BaseEventArgs
{
private readonly MultiDictionary<int, EventHandler<T>> m_EventHandlers;
private readonly Queue<Event> m_Events;
private readonly Dictionary<object, LinkedListNode<EventHandler<T>>> m_CachedNodes;
private readonly Dictionary<object, LinkedListNode<EventHandler<T>>> m_TempNodes;
private readonly EventPoolMode m_EventPoolMode;
private EventHandler<T> m_DefaultHandler;
/// <summary>
/// 初始化事件池的新实例。
/// </summary>
/// <param name="mode">事件池模式。</param>
public EventPool(EventPoolMode mode)
{
m_EventHandlers = new MultiDictionary<int, EventHandler<T>>();
m_Events = new Queue<Event>();
m_CachedNodes = new Dictionary<object, LinkedListNode<EventHandler<T>>>();
m_TempNodes = new Dictionary<object, LinkedListNode<EventHandler<T>>>();
m_EventPoolMode = mode;
m_DefaultHandler = null;
}
/// <summary>
/// 获取事件处理函数的数量。
/// </summary>
public int EventHandlerCount
{
get
{
return m_EventHandlers.Count;
}
}
/// <summary>
/// 获取事件数量。
/// </summary>
public int EventCount
{
get
{
return m_Events.Count;
}
}
/// <summary>
/// 事件池轮询。
/// </summary>
/// <param name="elapseSeconds">逻辑流逝时间,以秒为单位。</param>
/// <param name="realElapseSeconds">真实流逝时间,以秒为单位。</param>
public void Update(float elapseSeconds, float realElapseSeconds)
{
lock (m_Events)
{
while (m_Events.Count > 0)
{
Event eventNode = m_Events.Dequeue();
HandleEvent(eventNode.Sender, eventNode.EventArgs);
MemoryPool.Release(eventNode);
}
}
}
/// <summary>
/// 关闭并清理事件池。
/// </summary>
public void Shutdown()
{
Clear();
m_EventHandlers.Clear();
m_CachedNodes.Clear();
m_TempNodes.Clear();
m_DefaultHandler = null;
}
/// <summary>
/// 清理事件。
/// </summary>
public void Clear()
{
lock (m_Events)
{
m_Events.Clear();
}
}
/// <summary>
/// 获取事件处理函数的数量。
/// </summary>
/// <param name="id">事件类型编号。</param>
/// <returns>事件处理函数的数量。</returns>
public int Count(int id)
{
LinkedListRange<EventHandler<T>> range = default(LinkedListRange<EventHandler<T>>);
if (m_EventHandlers.TryGetValue(id, out range))
{
return range.Count;
}
return 0;
}
/// <summary>
/// 检查是否存在事件处理函数。
/// </summary>
/// <param name="id">事件类型编号。</param>
/// <param name="handler">要检查的事件处理函数。</param>
/// <returns>是否存在事件处理函数。</returns>
public bool Check(int id, EventHandler<T> handler)
{
if (handler == null)
{
throw new Exception("Event handler is invalid.");
}
return m_EventHandlers.Contains(id, handler);
}
/// <summary>
/// 订阅事件处理函数。
/// </summary>
/// <param name="id">事件类型编号。</param>
/// <param name="handler">要订阅的事件处理函数。</param>
public void Subscribe(int id, EventHandler<T> handler)
{
if (handler == null)
{
throw new Exception("Event handler is invalid.");
}
if (!m_EventHandlers.Contains(id))
{
m_EventHandlers.Add(id, handler);
}
else if ((m_EventPoolMode & EventPoolMode.AllowMultiHandler) != EventPoolMode.AllowMultiHandler)
{
throw new Exception(Utility.Text.Format("Event '{0}' not allow multi handler.", id));
}
else if ((m_EventPoolMode & EventPoolMode.AllowDuplicateHandler) != EventPoolMode.AllowDuplicateHandler && Check(id, handler))
{
throw new Exception(Utility.Text.Format("Event '{0}' not allow duplicate handler.", id));
}
else
{
m_EventHandlers.Add(id, handler);
}
}
/// <summary>
/// 取消订阅事件处理函数。
/// </summary>
/// <param name="id">事件类型编号。</param>
/// <param name="handler">要取消订阅的事件处理函数。</param>
public void Unsubscribe(int id, EventHandler<T> handler)
{
if (handler == null)
{
throw new Exception("Event handler is invalid.");
}
if (m_CachedNodes.Count > 0)
{
foreach (KeyValuePair<object, LinkedListNode<EventHandler<T>>> cachedNode in m_CachedNodes)
{
if (cachedNode.Value != null && cachedNode.Value.Value == handler)
{
m_TempNodes.Add(cachedNode.Key, cachedNode.Value.Next);
}
}
if (m_TempNodes.Count > 0)
{
foreach (KeyValuePair<object, LinkedListNode<EventHandler<T>>> cachedNode in m_TempNodes)
{
m_CachedNodes[cachedNode.Key] = cachedNode.Value;
}
m_TempNodes.Clear();
}
}
if (!m_EventHandlers.Remove(id, handler))
{
throw new Exception(Utility.Text.Format("Event '{0}' not exists specified handler.", id));
}
}
/// <summary>
/// 设置默认事件处理函数。
/// </summary>
/// <param name="handler">要设置的默认事件处理函数。</param>
public void SetDefaultHandler(EventHandler<T> handler)
{
m_DefaultHandler = handler;
}
/// <summary>
/// 抛出事件,这个操作是线程安全的,即使不在主线程中抛出,也可保证在主线程中回调事件处理函数,但事件会在抛出后的下一帧分发。
/// </summary>
/// <param name="sender">事件源。</param>
/// <param name="e">事件参数。</param>
public void Fire(object sender, T e)
{
if (e == null)
{
throw new Exception("Event is invalid.");
}
Event eventNode = Event.Create(sender, e);
lock (m_Events)
{
m_Events.Enqueue(eventNode);
}
}
/// <summary>
/// 抛出事件立即模式,这个操作不是线程安全的,事件会立刻分发。
/// </summary>
/// <param name="sender">事件源。</param>
/// <param name="e">事件参数。</param>
public void FireNow(object sender, T e)
{
if (e == null)
{
throw new Exception("Event is invalid.");
}
HandleEvent(sender, e);
}
/// <summary>
/// 处理事件结点。
/// </summary>
/// <param name="sender">事件源。</param>
/// <param name="e">事件参数。</param>
private void HandleEvent(object sender, T e)
{
bool noHandlerException = false;
LinkedListRange<EventHandler<T>> range = default(LinkedListRange<EventHandler<T>>);
if (m_EventHandlers.TryGetValue(e.Id, out range))
{
LinkedListNode<EventHandler<T>> current = range.First;
while (current != null && current != range.Terminal)
{
m_CachedNodes[e] = current.Next != range.Terminal ? current.Next : null;
current.Value(sender, e);
current = m_CachedNodes[e];
}
m_CachedNodes.Remove(e);
}
else if (m_DefaultHandler != null)
{
m_DefaultHandler(sender, e);
}
else if ((m_EventPoolMode & EventPoolMode.AllowNoHandler) == 0)
{
noHandlerException = true;
}
MemoryPool.Release(e);
if (noHandlerException)
{
throw new Exception(Utility.Text.Format("Event '{0}' not allow no handler.", e.Id));
}
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: d5b63a6b52c0c9e42bb270c6756aac26
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,31 @@
using System;
namespace TEngine.Runtime
{
/// <summary>
/// 事件池模式。
/// </summary>
[Flags]
internal enum EventPoolMode : byte
{
/// <summary>
/// 默认事件池模式,即必须存在有且只有一个事件处理函数。
/// </summary>
Default = 0,
/// <summary>
/// 允许不存在事件处理函数。
/// </summary>
AllowNoHandler = 1,
/// <summary>
/// 允许存在多个事件处理函数。
/// </summary>
AllowMultiHandler = 2,
/// <summary>
/// 允许存在重复的事件处理函数。
/// </summary>
AllowDuplicateHandler = 4
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: c15df25d44d958f47a48a7ae0f26018c
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,9 @@
namespace TEngine.Runtime
{
/// <summary>
/// 游戏逻辑事件基类。
/// </summary>
public abstract class GameEventArgs : BaseEventArgs
{
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: af3ac5182b9c4df9b51b8720629f19a8
timeCreated: 1661775780

View File

@@ -0,0 +1,75 @@
using System;
namespace TEngine.Runtime
{
/// <summary>
/// 事件管理器接口。
/// </summary>
public interface IEventManager
{
/// <summary>
/// 获取事件处理函数的数量。
/// </summary>
int EventHandlerCount
{
get;
}
/// <summary>
/// 获取事件数量。
/// </summary>
int EventCount
{
get;
}
/// <summary>
/// 获取事件处理函数的数量。
/// </summary>
/// <param name="id">事件类型编号。</param>
/// <returns>事件处理函数的数量。</returns>
int Count(int id);
/// <summary>
/// 检查是否存在事件处理函数。
/// </summary>
/// <param name="id">事件类型编号。</param>
/// <param name="handler">要检查的事件处理函数。</param>
/// <returns>是否存在事件处理函数。</returns>
bool Check(int id, EventHandler<GameEventArgs> handler);
/// <summary>
/// 订阅事件处理函数。
/// </summary>
/// <param name="id">事件类型编号。</param>
/// <param name="handler">要订阅的事件处理函数。</param>
void Subscribe(int id, EventHandler<GameEventArgs> handler);
/// <summary>
/// 取消订阅事件处理函数。
/// </summary>
/// <param name="id">事件类型编号。</param>
/// <param name="handler">要取消订阅的事件处理函数。</param>
void Unsubscribe(int id, EventHandler<GameEventArgs> handler);
/// <summary>
/// 设置默认事件处理函数。
/// </summary>
/// <param name="handler">要设置的默认事件处理函数。</param>
void SetDefaultHandler(EventHandler<GameEventArgs> handler);
/// <summary>
/// 抛出事件,这个操作是线程安全的,即使不在主线程中抛出,也可保证在主线程中回调事件处理函数,但事件会在抛出后的下一帧分发。
/// </summary>
/// <param name="sender">事件源。</param>
/// <param name="e">事件参数。</param>
void Fire(object sender, GameEventArgs e);
/// <summary>
/// 抛出事件立即模式,这个操作不是线程安全的,事件会立刻分发。
/// </summary>
/// <param name="sender">事件源。</param>
/// <param name="e">事件参数。</param>
void FireNow(object sender, GameEventArgs e);
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 056d52252266e8f419ec195f7908a878
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,111 @@
using System;
namespace TEngine.Runtime
{
public class NetEvent:BehaviourSingleton<NetEvent>
{
private IEventManager m_EventManager = null;
/// <summary>
/// 获取事件处理函数的数量。
/// </summary>
public int EventHandlerCount
{
get
{
return m_EventManager.EventHandlerCount;
}
}
/// <summary>
/// 获取事件数量。
/// </summary>
public int EventCount
{
get
{
return m_EventManager.EventCount;
}
}
public override void Awake()
{
base.Awake();
m_EventManager = new EventManager();
if (m_EventManager == null)
{
Log.Fatal("Event manager is invalid.");
return;
}
}/// <summary>
/// 获取事件处理函数的数量。
/// </summary>
/// <param name="id">事件类型编号。</param>
/// <returns>事件处理函数的数量。</returns>
public int Count(int id)
{
return m_EventManager.Count(id);
}
/// <summary>
/// 检查是否存在事件处理函数。
/// </summary>
/// <param name="id">事件类型编号。</param>
/// <param name="handler">要检查的事件处理函数。</param>
/// <returns>是否存在事件处理函数。</returns>
public bool Check(int id, EventHandler<GameEventArgs> handler)
{
return m_EventManager.Check(id, handler);
}
/// <summary>
/// 订阅事件处理回调函数。
/// </summary>
/// <param name="id">事件类型编号。</param>
/// <param name="handler">要订阅的事件处理回调函数。</param>
public void Subscribe(int id, EventHandler<GameEventArgs> handler)
{
m_EventManager.Subscribe(id, handler);
}
/// <summary>
/// 取消订阅事件处理回调函数。
/// </summary>
/// <param name="id">事件类型编号。</param>
/// <param name="handler">要取消订阅的事件处理回调函数。</param>
public void Unsubscribe(int id, EventHandler<GameEventArgs> handler)
{
m_EventManager.Unsubscribe(id, handler);
}
/// <summary>
/// 设置默认事件处理函数。
/// </summary>
/// <param name="handler">要设置的默认事件处理函数。</param>
public void SetDefaultHandler(EventHandler<GameEventArgs> handler)
{
m_EventManager.SetDefaultHandler(handler);
}
/// <summary>
/// 抛出事件,这个操作是线程安全的,即使不在主线程中抛出,也可保证在主线程中回调事件处理函数,但事件会在抛出后的下一帧分发。
/// </summary>
/// <param name="sender">事件发送者。</param>
/// <param name="e">事件内容。</param>
public void Fire(object sender, GameEventArgs e)
{
m_EventManager.Fire(sender, e);
}
/// <summary>
/// 抛出事件立即模式,这个操作不是线程安全的,事件会立刻分发。
/// </summary>
/// <param name="sender">事件发送者。</param>
/// <param name="e">事件内容。</param>
public void FireNow(object sender, GameEventArgs e)
{
m_EventManager.FireNow(sender, e);
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 4e42aa2c6d194fd59c82dc3c597d9152
timeCreated: 1661775598

View File

@@ -0,0 +1,157 @@
using System;
using System.Net;
using System.Net.Sockets;
namespace TEngine.Runtime
{
/// <summary>
/// 网络频道接口。
/// </summary>
public interface INetworkChannel
{
/// <summary>
/// 获取网络频道名称。
/// </summary>
string Name
{
get;
}
/// <summary>
/// 获取网络频道所使用的 Socket。
/// </summary>
Socket Socket
{
get;
}
/// <summary>
/// 获取是否已连接。
/// </summary>
bool Connected
{
get;
}
/// <summary>
/// 获取网络服务类型。
/// </summary>
ServiceType ServiceType
{
get;
}
/// <summary>
/// 获取网络地址类型。
/// </summary>
AddressFamily AddressFamily
{
get;
}
/// <summary>
/// 获取要发送的消息包数量。
/// </summary>
int SendPacketCount
{
get;
}
/// <summary>
/// 获取累计发送的消息包数量。
/// </summary>
int SentPacketCount
{
get;
}
/// <summary>
/// 获取已接收未处理的消息包数量。
/// </summary>
int ReceivePacketCount
{
get;
}
/// <summary>
/// 获取累计已接收的消息包数量。
/// </summary>
int ReceivedPacketCount
{
get;
}
/// <summary>
/// 获取或设置当收到消息包时是否重置心跳流逝时间。
/// </summary>
bool ResetHeartBeatElapseSecondsWhenReceivePacket
{
get;
set;
}
/// <summary>
/// 获取丢失心跳的次数。
/// </summary>
int MissHeartBeatCount
{
get;
}
/// <summary>
/// 获取或设置心跳间隔时长,以秒为单位。
/// </summary>
float HeartBeatInterval
{
get;
set;
}
/// <summary>
/// 获取心跳等待时长,以秒为单位。
/// </summary>
float HeartBeatElapseSeconds
{
get;
}
/// <summary>
/// 注册网络消息包处理函数。
/// </summary>
/// <param name="handler">要注册的网络消息包处理函数。</param>
void RegisterHandler(IPacketHandler handler);
/// <summary>
/// 设置默认事件处理函数。
/// </summary>
/// <param name="handler">要设置的默认事件处理函数。</param>
void SetDefaultHandler(EventHandler<Packet> handler);
/// <summary>
/// 连接到远程主机。
/// </summary>
/// <param name="ipAddress">远程主机的 IP 地址。</param>
/// <param name="port">远程主机的端口号。</param>
void Connect(IPAddress ipAddress, int port);
/// <summary>
/// 连接到远程主机。
/// </summary>
/// <param name="ipAddress">远程主机的 IP 地址。</param>
/// <param name="port">远程主机的端口号。</param>
/// <param name="userData">用户自定义数据。</param>
void Connect(IPAddress ipAddress, int port, object userData);
/// <summary>
/// 关闭网络频道。
/// </summary>
void Close();
/// <summary>
/// 向远程主机发送消息包。
/// </summary>
/// <typeparam name="T">消息包类型。</typeparam>
/// <param name="packet">要发送的消息包。</param>
void Send<T>(T packet) where T : Packet;
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: c66ee24862094df49e089d63f7481285
timeCreated: 1661771701

View File

@@ -0,0 +1,66 @@
using System.IO;
namespace TEngine.Runtime
{
/// <summary>
/// 网络频道辅助器接口。
/// </summary>
public interface INetworkChannelHelper
{
/// <summary>
/// 获取消息包头长度。
/// </summary>
int PacketHeaderLength
{
get;
}
/// <summary>
/// 初始化网络频道辅助器。
/// </summary>
/// <param name="networkChannel">网络频道。</param>
void Initialize(INetworkChannel networkChannel);
/// <summary>
/// 关闭并清理网络频道辅助器。
/// </summary>
void Shutdown();
/// <summary>
/// 准备进行连接。
/// </summary>
void PrepareForConnecting();
/// <summary>
/// 发送心跳消息包。
/// </summary>
/// <returns>是否发送心跳消息包成功。</returns>
bool SendHeartBeat();
/// <summary>
/// 序列化消息包。
/// </summary>
/// <typeparam name="T">消息包类型。</typeparam>
/// <param name="packet">要序列化的消息包。</param>
/// <param name="destination">要序列化的目标流。</param>
/// <returns>是否序列化成功。</returns>
bool Serialize<T>(T packet, Stream destination) where T : Packet;
/// <summary>
/// 反序列化消息包头。
/// </summary>
/// <param name="source">要反序列化的来源流。</param>
/// <param name="customErrorData">用户自定义错误数据。</param>
/// <returns>反序列化后的消息包头。</returns>
IPacketHeader DeserializePacketHeader(Stream source, out object customErrorData);
/// <summary>
/// 反序列化消息包。
/// </summary>
/// <param name="packetHeader">消息包头。</param>
/// <param name="source">要反序列化的来源流。</param>
/// <param name="customErrorData">用户自定义错误数据。</param>
/// <returns>反序列化后的消息包。</returns>
Packet DeserializePacket(IPacketHeader packetHeader, Stream source, out object customErrorData);
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: aeff0f53fdd54bd489d6a6141e79dca0
timeCreated: 1661771934

View File

@@ -0,0 +1,86 @@
using System;
using System.Collections.Generic;
namespace TEngine.Runtime
{
/// <summary>
/// 网络管理器接口。
/// </summary>
public interface INetworkManager
{
/// <summary>
/// 获取网络频道数量。
/// </summary>
int NetworkChannelCount
{
get;
}
/// <summary>
/// 网络连接成功事件。
/// </summary>
event EventHandler<NetworkConnectedEventArgs> NetworkConnected;
/// <summary>
/// 网络连接关闭事件。
/// </summary>
event EventHandler<NetworkClosedEventArgs> NetworkClosed;
/// <summary>
/// 网络心跳包丢失事件。
/// </summary>
event EventHandler<NetworkMissHeartBeatEventArgs> NetworkMissHeartBeat;
/// <summary>
/// 网络错误事件。
/// </summary>
event EventHandler<NetworkErrorEventArgs> NetworkError;
/// <summary>
/// 用户自定义网络错误事件。
/// </summary>
event EventHandler<NetworkCustomErrorEventArgs> NetworkCustomError;
/// <summary>
/// 检查是否存在网络频道。
/// </summary>
/// <param name="name">网络频道名称。</param>
/// <returns>是否存在网络频道。</returns>
bool HasNetworkChannel(string name);
/// <summary>
/// 获取网络频道。
/// </summary>
/// <param name="name">网络频道名称。</param>
/// <returns>要获取的网络频道。</returns>
INetworkChannel GetNetworkChannel(string name);
/// <summary>
/// 获取所有网络频道。
/// </summary>
/// <returns>所有网络频道。</returns>
INetworkChannel[] GetAllNetworkChannels();
/// <summary>
/// 获取所有网络频道。
/// </summary>
/// <param name="results">所有网络频道。</param>
void GetAllNetworkChannels(List<INetworkChannel> results);
/// <summary>
/// 创建网络频道。
/// </summary>
/// <param name="name">网络频道名称。</param>
/// <param name="serviceType">网络服务类型。</param>
/// <param name="networkChannelHelper">网络频道辅助器。</param>
/// <returns>要创建的网络频道。</returns>
INetworkChannel CreateNetworkChannel(string name, ServiceType serviceType, INetworkChannelHelper networkChannelHelper);
/// <summary>
/// 销毁网络频道。
/// </summary>
/// <param name="name">网络频道名称。</param>
/// <returns>是否销毁网络频道成功。</returns>
bool DestroyNetworkChannel(string name);
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: aa9566de56cd4b579631a1725b89174e
timeCreated: 1661775465

View File

@@ -0,0 +1,23 @@
namespace TEngine.Runtime
{
/// <summary>
/// 网络消息包处理器接口。
/// </summary>
public interface IPacketHandler
{
/// <summary>
/// 获取网络消息包协议编号。
/// </summary>
int Id
{
get;
}
/// <summary>
/// 网络消息包处理函数。
/// </summary>
/// <param name="sender">网络消息包源。</param>
/// <param name="packet">网络消息包内容。</param>
void Handle(object sender, Packet packet);
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 49d9ce041dfb4dc98f954dd85e7b9015
timeCreated: 1661771824

View File

@@ -0,0 +1,16 @@
namespace TEngine.Runtime
{
/// <summary>
/// 网络消息包头接口。
/// </summary>
public interface IPacketHeader
{
/// <summary>
/// 获取网络消息包长度。
/// </summary>
int PacketLength
{
get;
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 1a61d331daf74fe48bffbb083f016cb5
timeCreated: 1661771898

View File

@@ -0,0 +1,139 @@
using System.Collections.Generic;
using UnityEngine;
namespace TEngine.Runtime
{
/// <summary>
/// 网络组件。
/// </summary>
[DisallowMultipleComponent]
[AddComponentMenu("TEngine/Network")]
public class Network : UnitySingleton<Network>
{
private INetworkManager m_NetworkManager = null;
private NetEvent m_NetEvent = NetEvent.Instance;
/// <summary>
/// 获取网络频道数量。
/// </summary>
public int NetworkChannelCount
{
get
{
return m_NetworkManager.NetworkChannelCount;
}
}
public override void Awake()
{
base.Awake();
m_NetworkManager = new NetworkManager();
if (m_NetworkManager == null)
{
Log.Fatal("Network manager is invalid.");
return;
}
m_NetworkManager.NetworkConnected += OnNetworkConnected;
m_NetworkManager.NetworkClosed += OnNetworkClosed;
m_NetworkManager.NetworkMissHeartBeat += OnNetworkMissHeartBeat;
m_NetworkManager.NetworkError += OnNetworkError;
m_NetworkManager.NetworkCustomError += OnNetworkCustomError;
}
protected override void OnLoad()
{
base.OnLoad();
if (m_NetEvent == null)
{
Log.Fatal("Event component is invalid.");
return;
}
}
/// <summary>
/// 检查是否存在网络频道。
/// </summary>
/// <param name="name">网络频道名称。</param>
/// <returns>是否存在网络频道。</returns>
public bool HasNetworkChannel(string name)
{
return m_NetworkManager.HasNetworkChannel(name);
}
/// <summary>
/// 获取网络频道。
/// </summary>
/// <param name="name">网络频道名称。</param>
/// <returns>要获取的网络频道。</returns>
public INetworkChannel GetNetworkChannel(string name)
{
return m_NetworkManager.GetNetworkChannel(name);
}
/// <summary>
/// 获取所有网络频道。
/// </summary>
/// <returns>所有网络频道。</returns>
public INetworkChannel[] GetAllNetworkChannels()
{
return m_NetworkManager.GetAllNetworkChannels();
}
/// <summary>
/// 获取所有网络频道。
/// </summary>
/// <param name="results">所有网络频道。</param>
public void GetAllNetworkChannels(List<INetworkChannel> results)
{
m_NetworkManager.GetAllNetworkChannels(results);
}
/// <summary>
/// 创建网络频道。
/// </summary>
/// <param name="name">网络频道名称。</param>
/// <param name="serviceType">网络服务类型。</param>
/// <param name="networkChannelHelper">网络频道辅助器。</param>
/// <returns>要创建的网络频道。</returns>
public INetworkChannel CreateNetworkChannel(string name, ServiceType serviceType, INetworkChannelHelper networkChannelHelper)
{
return m_NetworkManager.CreateNetworkChannel(name, serviceType, networkChannelHelper);
}
/// <summary>
/// 销毁网络频道。
/// </summary>
/// <param name="name">网络频道名称。</param>
/// <returns>是否销毁网络频道成功。</returns>
public bool DestroyNetworkChannel(string name)
{
return m_NetworkManager.DestroyNetworkChannel(name);
}
private void OnNetworkConnected(object sender, NetworkConnectedEventArgs e)
{
m_NetEvent.Fire(this, e);
}
private void OnNetworkClosed(object sender, NetworkClosedEventArgs e)
{
m_NetEvent.Fire(this, e);
}
private void OnNetworkMissHeartBeat(object sender, NetworkMissHeartBeatEventArgs e)
{
m_NetEvent.Fire(this, e);
}
private void OnNetworkError(object sender, NetworkErrorEventArgs e)
{
m_NetEvent.Fire(this, e);
}
private void OnNetworkCustomError(object sender, NetworkCustomErrorEventArgs e)
{
m_NetEvent.Fire(this, e);
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 1dd2b00e963a5b54db7aae1b87628982
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,53 @@
namespace TEngine.Runtime
{
/// <summary>
/// 网络错误码。
/// </summary>
public enum NetworkErrorCode : byte
{
/// <summary>
/// 未知错误。
/// </summary>
Unknown = 0,
/// <summary>
/// 地址族错误。
/// </summary>
AddressFamilyError,
/// <summary>
/// Socket 错误。
/// </summary>
SocketError,
/// <summary>
/// 连接错误。
/// </summary>
ConnectError,
/// <summary>
/// 发送错误。
/// </summary>
SendError,
/// <summary>
/// 接收错误。
/// </summary>
ReceiveError,
/// <summary>
/// 序列化错误。
/// </summary>
SerializeError,
/// <summary>
/// 反序列化消息包头错误。
/// </summary>
DeserializePacketHeaderError,
/// <summary>
/// 反序列化消息包错误。
/// </summary>
DeserializePacketError
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 86fe9208ee30402ab1fcdc8cdcff1d89
timeCreated: 1661771970

View File

@@ -0,0 +1,35 @@
using System.Net.Sockets;
namespace TEngine.Runtime
{
public sealed partial class NetworkManager
{
private sealed class ConnectState
{
private readonly Socket m_Socket;
private readonly object m_UserData;
public ConnectState(Socket socket, object userData)
{
m_Socket = socket;
m_UserData = userData;
}
public Socket Socket
{
get
{
return m_Socket;
}
}
public object UserData
{
get
{
return m_UserData;
}
}
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 07167c4e7b24c2148acdfe52fbe0c817
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,51 @@
namespace TEngine.Runtime
{
public sealed partial class NetworkManager
{
private sealed class HeartBeatState
{
private float m_HeartBeatElapseSeconds;
private int m_MissHeartBeatCount;
public HeartBeatState()
{
m_HeartBeatElapseSeconds = 0f;
m_MissHeartBeatCount = 0;
}
public float HeartBeatElapseSeconds
{
get
{
return m_HeartBeatElapseSeconds;
}
set
{
m_HeartBeatElapseSeconds = value;
}
}
public int MissHeartBeatCount
{
get
{
return m_MissHeartBeatCount;
}
set
{
m_MissHeartBeatCount = value;
}
}
public void Reset(bool resetHeartBeatElapseSeconds)
{
if (resetHeartBeatElapseSeconds)
{
m_HeartBeatElapseSeconds = 0f;
}
m_MissHeartBeatCount = 0;
}
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: e1beec3505229bd418c252c142a01152
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,629 @@
using System;
using System.Collections.Generic;
using System.Net;
using System.Net.Sockets;
namespace TEngine.Runtime
{
public sealed partial class NetworkManager
{
/// <summary>
/// 网络频道基类。
/// </summary>
private abstract class NetworkChannelBase : INetworkChannel, IDisposable
{
private const float DefaultHeartBeatInterval = 30f;
private readonly string m_Name;
protected readonly Queue<Packet> m_SendPacketPool;
protected readonly EventPool<Packet> m_ReceivePacketPool;
protected readonly INetworkChannelHelper m_NetworkChannelHelper;
protected AddressFamily m_AddressFamily;
protected bool m_ResetHeartBeatElapseSecondsWhenReceivePacket;
protected float m_HeartBeatInterval;
protected Socket m_Socket;
protected readonly SendState m_SendState;
protected readonly ReceiveState m_ReceiveState;
protected readonly HeartBeatState m_HeartBeatState;
protected int m_SentPacketCount;
protected int m_ReceivedPacketCount;
protected bool m_Active;
private bool m_Disposed;
public Action<NetworkChannelBase, object> NetworkChannelConnected;
public Action<NetworkChannelBase> NetworkChannelClosed;
public Action<NetworkChannelBase, int> NetworkChannelMissHeartBeat;
public Action<NetworkChannelBase, NetworkErrorCode, SocketError, string> NetworkChannelError;
public Action<NetworkChannelBase, object> NetworkChannelCustomError;
/// <summary>
/// 初始化网络频道基类的新实例。
/// </summary>
/// <param name="name">网络频道名称。</param>
/// <param name="networkChannelHelper">网络频道辅助器。</param>
public NetworkChannelBase(string name, INetworkChannelHelper networkChannelHelper)
{
m_Name = name ?? string.Empty;
m_SendPacketPool = new Queue<Packet>();
m_ReceivePacketPool = new EventPool<Packet>(EventPoolMode.Default);
m_NetworkChannelHelper = networkChannelHelper;
m_AddressFamily = AddressFamily.Unknown;
m_ResetHeartBeatElapseSecondsWhenReceivePacket = false;
m_HeartBeatInterval = DefaultHeartBeatInterval;
m_Socket = null;
m_SendState = new SendState();
m_ReceiveState = new ReceiveState();
m_HeartBeatState = new HeartBeatState();
m_SentPacketCount = 0;
m_ReceivedPacketCount = 0;
m_Active = false;
m_Disposed = false;
NetworkChannelConnected = null;
NetworkChannelClosed = null;
NetworkChannelMissHeartBeat = null;
NetworkChannelError = null;
NetworkChannelCustomError = null;
networkChannelHelper.Initialize(this);
}
/// <summary>
/// 获取网络频道名称。
/// </summary>
public string Name
{
get
{
return m_Name;
}
}
/// <summary>
/// 获取网络频道所使用的 Socket。
/// </summary>
public Socket Socket
{
get
{
return m_Socket;
}
}
/// <summary>
/// 获取是否已连接。
/// </summary>
public bool Connected
{
get
{
if (m_Socket != null)
{
return m_Socket.Connected;
}
return false;
}
}
/// <summary>
/// 获取网络服务类型。
/// </summary>
public abstract ServiceType ServiceType
{
get;
}
/// <summary>
/// 获取网络地址类型。
/// </summary>
public AddressFamily AddressFamily
{
get
{
return m_AddressFamily;
}
}
/// <summary>
/// 获取要发送的消息包数量。
/// </summary>
public int SendPacketCount
{
get
{
return m_SendPacketPool.Count;
}
}
/// <summary>
/// 获取累计发送的消息包数量。
/// </summary>
public int SentPacketCount
{
get
{
return m_SentPacketCount;
}
}
/// <summary>
/// 获取已接收未处理的消息包数量。
/// </summary>
public int ReceivePacketCount
{
get
{
return m_ReceivePacketPool.EventCount;
}
}
/// <summary>
/// 获取累计已接收的消息包数量。
/// </summary>
public int ReceivedPacketCount
{
get
{
return m_ReceivedPacketCount;
}
}
/// <summary>
/// 获取或设置当收到消息包时是否重置心跳流逝时间。
/// </summary>
public bool ResetHeartBeatElapseSecondsWhenReceivePacket
{
get
{
return m_ResetHeartBeatElapseSecondsWhenReceivePacket;
}
set
{
m_ResetHeartBeatElapseSecondsWhenReceivePacket = value;
}
}
/// <summary>
/// 获取丢失心跳的次数。
/// </summary>
public int MissHeartBeatCount
{
get
{
return m_HeartBeatState.MissHeartBeatCount;
}
}
/// <summary>
/// 获取或设置心跳间隔时长,以秒为单位。
/// </summary>
public float HeartBeatInterval
{
get
{
return m_HeartBeatInterval;
}
set
{
m_HeartBeatInterval = value;
}
}
/// <summary>
/// 获取心跳等待时长,以秒为单位。
/// </summary>
public float HeartBeatElapseSeconds
{
get
{
return m_HeartBeatState.HeartBeatElapseSeconds;
}
}
/// <summary>
/// 网络频道轮询。
/// </summary>
/// <param name="elapseSeconds">逻辑流逝时间,以秒为单位。</param>
/// <param name="realElapseSeconds">真实流逝时间,以秒为单位。</param>
public virtual void Update(float elapseSeconds, float realElapseSeconds)
{
if (m_Socket == null || !m_Active)
{
return;
}
ProcessSend();
ProcessReceive();
if (m_Socket == null || !m_Active)
{
return;
}
m_ReceivePacketPool.Update(elapseSeconds, realElapseSeconds);
if (m_HeartBeatInterval > 0f)
{
bool sendHeartBeat = false;
int missHeartBeatCount = 0;
lock (m_HeartBeatState)
{
if (m_Socket == null || !m_Active)
{
return;
}
m_HeartBeatState.HeartBeatElapseSeconds += realElapseSeconds;
if (m_HeartBeatState.HeartBeatElapseSeconds >= m_HeartBeatInterval)
{
sendHeartBeat = true;
missHeartBeatCount = m_HeartBeatState.MissHeartBeatCount;
m_HeartBeatState.HeartBeatElapseSeconds = 0f;
m_HeartBeatState.MissHeartBeatCount++;
}
}
if (sendHeartBeat && m_NetworkChannelHelper.SendHeartBeat())
{
if (missHeartBeatCount > 0 && NetworkChannelMissHeartBeat != null)
{
NetworkChannelMissHeartBeat(this, missHeartBeatCount);
}
}
}
}
/// <summary>
/// 关闭网络频道。
/// </summary>
public virtual void Shutdown()
{
Close();
m_ReceivePacketPool.Shutdown();
m_NetworkChannelHelper.Shutdown();
}
/// <summary>
/// 注册网络消息包处理函数。
/// </summary>
/// <param name="handler">要注册的网络消息包处理函数。</param>
public void RegisterHandler(IPacketHandler handler)
{
if (handler == null)
{
throw new Exception("Packet handler is invalid.");
}
m_ReceivePacketPool.Subscribe(handler.Id, handler.Handle);
}
/// <summary>
/// 设置默认事件处理函数。
/// </summary>
/// <param name="handler">要设置的默认事件处理函数。</param>
public void SetDefaultHandler(EventHandler<Packet> handler)
{
m_ReceivePacketPool.SetDefaultHandler(handler);
}
/// <summary>
/// 连接到远程主机。
/// </summary>
/// <param name="ipAddress">远程主机的 IP 地址。</param>
/// <param name="port">远程主机的端口号。</param>
public void Connect(IPAddress ipAddress, int port)
{
Connect(ipAddress, port, null);
}
/// <summary>
/// 连接到远程主机。
/// </summary>
/// <param name="ipAddress">远程主机的 IP 地址。</param>
/// <param name="port">远程主机的端口号。</param>
/// <param name="userData">用户自定义数据。</param>
public virtual void Connect(IPAddress ipAddress, int port, object userData)
{
if (m_Socket != null)
{
Close();
m_Socket = null;
}
switch (ipAddress.AddressFamily)
{
case System.Net.Sockets.AddressFamily.InterNetwork:
m_AddressFamily = AddressFamily.IPv4;
break;
case System.Net.Sockets.AddressFamily.InterNetworkV6:
m_AddressFamily = AddressFamily.IPv6;
break;
default:
string errorMessage = Utility.Text.Format("Not supported address family '{0}'.", ipAddress.AddressFamily);
if (NetworkChannelError != null)
{
NetworkChannelError(this, NetworkErrorCode.AddressFamilyError, SocketError.Success, errorMessage);
return;
}
throw new Exception(errorMessage);
}
m_SendState.Reset();
m_ReceiveState.PrepareForPacketHeader(m_NetworkChannelHelper.PacketHeaderLength);
}
/// <summary>
/// 关闭连接并释放所有相关资源。
/// </summary>
public void Close()
{
lock (this)
{
if (m_Socket == null)
{
return;
}
m_Active = false;
try
{
m_Socket.Shutdown(SocketShutdown.Both);
}
catch
{
}
finally
{
m_Socket.Close();
m_Socket = null;
if (NetworkChannelClosed != null)
{
NetworkChannelClosed(this);
}
}
m_SentPacketCount = 0;
m_ReceivedPacketCount = 0;
lock (m_SendPacketPool)
{
m_SendPacketPool.Clear();
}
m_ReceivePacketPool.Clear();
lock (m_HeartBeatState)
{
m_HeartBeatState.Reset(true);
}
}
}
/// <summary>
/// 向远程主机发送消息包。
/// </summary>
/// <typeparam name="T">消息包类型。</typeparam>
/// <param name="packet">要发送的消息包。</param>
public void Send<T>(T packet) where T : Packet
{
if (m_Socket == null)
{
string errorMessage = "You must connect first.";
if (NetworkChannelError != null)
{
NetworkChannelError(this, NetworkErrorCode.SendError, SocketError.Success, errorMessage);
return;
}
throw new Exception(errorMessage);
}
if (!m_Active)
{
string errorMessage = "Socket is not active.";
if (NetworkChannelError != null)
{
NetworkChannelError(this, NetworkErrorCode.SendError, SocketError.Success, errorMessage);
return;
}
throw new Exception(errorMessage);
}
if (packet == null)
{
string errorMessage = "Packet is invalid.";
if (NetworkChannelError != null)
{
NetworkChannelError(this, NetworkErrorCode.SendError, SocketError.Success, errorMessage);
return;
}
throw new Exception(errorMessage);
}
lock (m_SendPacketPool)
{
m_SendPacketPool.Enqueue(packet);
}
}
/// <summary>
/// 释放资源。
/// </summary>
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
/// <summary>
/// 释放资源。
/// </summary>
/// <param name="disposing">释放资源标记。</param>
private void Dispose(bool disposing)
{
if (m_Disposed)
{
return;
}
if (disposing)
{
Close();
m_SendState.Dispose();
m_ReceiveState.Dispose();
}
m_Disposed = true;
}
protected virtual bool ProcessSend()
{
if (m_SendState.Stream.Length > 0 || m_SendPacketPool.Count <= 0)
{
return false;
}
while (m_SendPacketPool.Count > 0)
{
Packet packet = null;
lock (m_SendPacketPool)
{
packet = m_SendPacketPool.Dequeue();
}
bool serializeResult = false;
try
{
serializeResult = m_NetworkChannelHelper.Serialize(packet, m_SendState.Stream);
}
catch (Exception exception)
{
m_Active = false;
if (NetworkChannelError != null)
{
SocketException socketException = exception as SocketException;
NetworkChannelError(this, NetworkErrorCode.SerializeError, socketException != null ? socketException.SocketErrorCode : SocketError.Success, exception.ToString());
return false;
}
throw;
}
if (!serializeResult)
{
string errorMessage = "Serialized packet failure.";
if (NetworkChannelError != null)
{
NetworkChannelError(this, NetworkErrorCode.SerializeError, SocketError.Success, errorMessage);
return false;
}
throw new Exception(errorMessage);
}
}
m_SendState.Stream.Position = 0L;
return true;
}
protected virtual void ProcessReceive()
{
}
protected virtual bool ProcessPacketHeader()
{
try
{
object customErrorData = null;
IPacketHeader packetHeader = m_NetworkChannelHelper.DeserializePacketHeader(m_ReceiveState.Stream, out customErrorData);
if (customErrorData != null && NetworkChannelCustomError != null)
{
NetworkChannelCustomError(this, customErrorData);
}
if (packetHeader == null)
{
string errorMessage = "Packet header is invalid.";
if (NetworkChannelError != null)
{
NetworkChannelError(this, NetworkErrorCode.DeserializePacketHeaderError, SocketError.Success, errorMessage);
return false;
}
throw new Exception(errorMessage);
}
m_ReceiveState.PrepareForPacket(packetHeader);
if (packetHeader.PacketLength <= 0)
{
bool processSuccess = ProcessPacket();
m_ReceivedPacketCount++;
return processSuccess;
}
}
catch (Exception exception)
{
m_Active = false;
if (NetworkChannelError != null)
{
SocketException socketException = exception as SocketException;
NetworkChannelError(this, NetworkErrorCode.DeserializePacketHeaderError, socketException != null ? socketException.SocketErrorCode : SocketError.Success, exception.ToString());
return false;
}
throw;
}
return true;
}
protected virtual bool ProcessPacket()
{
lock (m_HeartBeatState)
{
m_HeartBeatState.Reset(m_ResetHeartBeatElapseSecondsWhenReceivePacket);
}
try
{
object customErrorData = null;
Packet packet = m_NetworkChannelHelper.DeserializePacket(m_ReceiveState.PacketHeader, m_ReceiveState.Stream, out customErrorData);
if (customErrorData != null && NetworkChannelCustomError != null)
{
NetworkChannelCustomError(this, customErrorData);
}
if (packet != null)
{
m_ReceivePacketPool.Fire(this, packet);
}
m_ReceiveState.PrepareForPacketHeader(m_NetworkChannelHelper.PacketHeaderLength);
}
catch (Exception exception)
{
m_Active = false;
if (NetworkChannelError != null)
{
SocketException socketException = exception as SocketException;
NetworkChannelError(this, NetworkErrorCode.DeserializePacketError, socketException != null ? socketException.SocketErrorCode : SocketError.Success, exception.ToString());
return false;
}
throw;
}
return true;
}
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: d124c3d2afc7006459e261c8d510711c
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,91 @@
using System;
using System.IO;
namespace TEngine.Runtime
{
public sealed partial class NetworkManager
{
private sealed class ReceiveState : IDisposable
{
private const int DefaultBufferLength = 1024 * 64;
private MemoryStream m_Stream;
private IPacketHeader m_PacketHeader;
private bool m_Disposed;
public ReceiveState()
{
m_Stream = new MemoryStream(DefaultBufferLength);
m_PacketHeader = null;
m_Disposed = false;
}
public MemoryStream Stream
{
get
{
return m_Stream;
}
}
public IPacketHeader PacketHeader
{
get
{
return m_PacketHeader;
}
}
public void PrepareForPacketHeader(int packetHeaderLength)
{
Reset(packetHeaderLength, null);
}
public void PrepareForPacket(IPacketHeader packetHeader)
{
if (packetHeader == null)
{
throw new Exception("Packet header is invalid.");
}
Reset(packetHeader.PacketLength, packetHeader);
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
private void Dispose(bool disposing)
{
if (m_Disposed)
{
return;
}
if (disposing)
{
if (m_Stream != null)
{
m_Stream.Dispose();
m_Stream = null;
}
}
m_Disposed = true;
}
private void Reset(int targetLength, IPacketHeader packetHeader)
{
if (targetLength < 0)
{
throw new Exception("Target length is invalid.");
}
m_Stream.Position = 0L;
m_Stream.SetLength(targetLength);
m_PacketHeader = packetHeader;
}
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 4a8a0b968c7b38442ae9bbf523e6f234
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,60 @@
using System;
using System.IO;
namespace TEngine.Runtime
{
public sealed partial class NetworkManager
{
private sealed class SendState : IDisposable
{
private const int DefaultBufferLength = 1024 * 64;
private MemoryStream m_Stream;
private bool m_Disposed;
public SendState()
{
m_Stream = new MemoryStream(DefaultBufferLength);
m_Disposed = false;
}
public MemoryStream Stream
{
get
{
return m_Stream;
}
}
public void Reset()
{
m_Stream.Position = 0L;
m_Stream.SetLength(0L);
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
private void Dispose(bool disposing)
{
if (m_Disposed)
{
return;
}
if (disposing)
{
if (m_Stream != null)
{
m_Stream.Dispose();
m_Stream = null;
}
}
m_Disposed = true;
}
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 01a1e8d0d67bac34a9d5ea40a96bb0eb
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,350 @@
using System;
using System.Collections.Generic;
using System.Net.Sockets;
namespace TEngine.Runtime
{
/// <summary>
/// 网络管理器。
/// </summary>
public sealed partial class NetworkManager : INetworkManager
{
private readonly Dictionary<string, NetworkChannelBase> m_NetworkChannels;
private EventHandler<NetworkConnectedEventArgs> m_NetworkConnectedEventHandler;
private EventHandler<NetworkClosedEventArgs> m_NetworkClosedEventHandler;
private EventHandler<NetworkMissHeartBeatEventArgs> m_NetworkMissHeartBeatEventHandler;
private EventHandler<NetworkErrorEventArgs> m_NetworkErrorEventHandler;
private EventHandler<NetworkCustomErrorEventArgs> m_NetworkCustomErrorEventHandler;
/// <summary>
/// 初始化网络管理器的新实例。
/// </summary>
public NetworkManager()
{
m_NetworkChannels = new Dictionary<string, NetworkChannelBase>(StringComparer.Ordinal);
m_NetworkConnectedEventHandler = null;
m_NetworkClosedEventHandler = null;
m_NetworkMissHeartBeatEventHandler = null;
m_NetworkErrorEventHandler = null;
m_NetworkCustomErrorEventHandler = null;
}
/// <summary>
/// 获取网络频道数量。
/// </summary>
public int NetworkChannelCount
{
get
{
return m_NetworkChannels.Count;
}
}
/// <summary>
/// 网络连接成功事件。
/// </summary>
public event EventHandler<NetworkConnectedEventArgs> NetworkConnected
{
add
{
m_NetworkConnectedEventHandler += value;
}
remove
{
m_NetworkConnectedEventHandler -= value;
}
}
/// <summary>
/// 网络连接关闭事件。
/// </summary>
public event EventHandler<NetworkClosedEventArgs> NetworkClosed
{
add
{
m_NetworkClosedEventHandler += value;
}
remove
{
m_NetworkClosedEventHandler -= value;
}
}
/// <summary>
/// 网络心跳包丢失事件。
/// </summary>
public event EventHandler<NetworkMissHeartBeatEventArgs> NetworkMissHeartBeat
{
add
{
m_NetworkMissHeartBeatEventHandler += value;
}
remove
{
m_NetworkMissHeartBeatEventHandler -= value;
}
}
/// <summary>
/// 网络错误事件。
/// </summary>
public event EventHandler<NetworkErrorEventArgs> NetworkError
{
add
{
m_NetworkErrorEventHandler += value;
}
remove
{
m_NetworkErrorEventHandler -= value;
}
}
/// <summary>
/// 用户自定义网络错误事件。
/// </summary>
public event EventHandler<NetworkCustomErrorEventArgs> NetworkCustomError
{
add
{
m_NetworkCustomErrorEventHandler += value;
}
remove
{
m_NetworkCustomErrorEventHandler -= value;
}
}
/// <summary>
/// 网络管理器轮询。
/// </summary>
/// <param name="elapseSeconds">逻辑流逝时间,以秒为单位。</param>
/// <param name="realElapseSeconds">真实流逝时间,以秒为单位。</param>
public void Update(float elapseSeconds, float realElapseSeconds)
{
foreach (KeyValuePair<string, NetworkChannelBase> networkChannel in m_NetworkChannels)
{
networkChannel.Value.Update(elapseSeconds, realElapseSeconds);
}
}
/// <summary>
/// 关闭并清理网络管理器。
/// </summary>
public void Shutdown()
{
foreach (KeyValuePair<string, NetworkChannelBase> networkChannel in m_NetworkChannels)
{
NetworkChannelBase networkChannelBase = networkChannel.Value;
networkChannelBase.NetworkChannelConnected -= OnNetworkChannelConnected;
networkChannelBase.NetworkChannelClosed -= OnNetworkChannelClosed;
networkChannelBase.NetworkChannelMissHeartBeat -= OnNetworkChannelMissHeartBeat;
networkChannelBase.NetworkChannelError -= OnNetworkChannelError;
networkChannelBase.NetworkChannelCustomError -= OnNetworkChannelCustomError;
networkChannelBase.Shutdown();
}
m_NetworkChannels.Clear();
}
/// <summary>
/// 检查是否存在网络频道。
/// </summary>
/// <param name="name">网络频道名称。</param>
/// <returns>是否存在网络频道。</returns>
public bool HasNetworkChannel(string name)
{
return m_NetworkChannels.ContainsKey(name ?? string.Empty);
}
/// <summary>
/// 获取网络频道。
/// </summary>
/// <param name="name">网络频道名称。</param>
/// <returns>要获取的网络频道。</returns>
public INetworkChannel GetNetworkChannel(string name)
{
NetworkChannelBase networkChannel = null;
if (m_NetworkChannels.TryGetValue(name ?? string.Empty, out networkChannel))
{
return networkChannel;
}
return null;
}
/// <summary>
/// 获取所有网络频道。
/// </summary>
/// <returns>所有网络频道。</returns>
public INetworkChannel[] GetAllNetworkChannels()
{
int index = 0;
INetworkChannel[] results = new INetworkChannel[m_NetworkChannels.Count];
foreach (KeyValuePair<string, NetworkChannelBase> networkChannel in m_NetworkChannels)
{
results[index++] = networkChannel.Value;
}
return results;
}
/// <summary>
/// 获取所有网络频道。
/// </summary>
/// <param name="results">所有网络频道。</param>
public void GetAllNetworkChannels(List<INetworkChannel> results)
{
if (results == null)
{
throw new Exception("Results is invalid.");
}
results.Clear();
foreach (KeyValuePair<string, NetworkChannelBase> networkChannel in m_NetworkChannels)
{
results.Add(networkChannel.Value);
}
}
/// <summary>
/// 创建网络频道。
/// </summary>
/// <param name="name">网络频道名称。</param>
/// <param name="serviceType">网络服务类型。</param>
/// <param name="networkChannelHelper">网络频道辅助器。</param>
/// <returns>要创建的网络频道。</returns>
public INetworkChannel CreateNetworkChannel(string name, ServiceType serviceType, INetworkChannelHelper networkChannelHelper)
{
if (networkChannelHelper == null)
{
throw new Exception("Network channel helper is invalid.");
}
if (networkChannelHelper.PacketHeaderLength < 0)
{
throw new Exception("Packet header length is invalid.");
}
if (HasNetworkChannel(name))
{
throw new Exception(Utility.Text.Format("Already exist network channel '{0}'.", name ?? string.Empty));
}
NetworkChannelBase networkChannel = null;
switch (serviceType)
{
case ServiceType.Tcp:
networkChannel = new TcpNetworkChannel(name, networkChannelHelper);
break;
case ServiceType.TcpWithSyncReceive:
networkChannel = new TcpWithSyncReceiveNetworkChannel(name, networkChannelHelper);
break;
case ServiceType.Udp:
networkChannel = new UdpNetworkChannel(name, networkChannelHelper);
break;
default:
throw new Exception(Utility.Text.Format("Not supported service type '{0}'.", serviceType));
}
networkChannel.NetworkChannelConnected += OnNetworkChannelConnected;
networkChannel.NetworkChannelClosed += OnNetworkChannelClosed;
networkChannel.NetworkChannelMissHeartBeat += OnNetworkChannelMissHeartBeat;
networkChannel.NetworkChannelError += OnNetworkChannelError;
networkChannel.NetworkChannelCustomError += OnNetworkChannelCustomError;
m_NetworkChannels.Add(name, networkChannel);
return networkChannel;
}
/// <summary>
/// 销毁网络频道。
/// </summary>
/// <param name="name">网络频道名称。</param>
/// <returns>是否销毁网络频道成功。</returns>
public bool DestroyNetworkChannel(string name)
{
NetworkChannelBase networkChannel = null;
if (m_NetworkChannels.TryGetValue(name ?? string.Empty, out networkChannel))
{
networkChannel.NetworkChannelConnected -= OnNetworkChannelConnected;
networkChannel.NetworkChannelClosed -= OnNetworkChannelClosed;
networkChannel.NetworkChannelMissHeartBeat -= OnNetworkChannelMissHeartBeat;
networkChannel.NetworkChannelError -= OnNetworkChannelError;
networkChannel.NetworkChannelCustomError -= OnNetworkChannelCustomError;
networkChannel.Shutdown();
return m_NetworkChannels.Remove(name);
}
return false;
}
private void OnNetworkChannelConnected(NetworkChannelBase networkChannel, object userData)
{
if (m_NetworkConnectedEventHandler != null)
{
lock (m_NetworkConnectedEventHandler)
{
NetworkConnectedEventArgs networkConnectedEventArgs = NetworkConnectedEventArgs.Create(networkChannel);
m_NetworkConnectedEventHandler(this, networkConnectedEventArgs);
MemoryPool.Release(networkConnectedEventArgs);
}
}
}
private void OnNetworkChannelClosed(NetworkChannelBase networkChannel)
{
if (m_NetworkClosedEventHandler != null)
{
lock (m_NetworkClosedEventHandler)
{
NetworkClosedEventArgs networkClosedEventArgs = NetworkClosedEventArgs.Create(networkChannel);
m_NetworkClosedEventHandler(this, networkClosedEventArgs);
MemoryPool.Release(networkClosedEventArgs);
}
}
}
private void OnNetworkChannelMissHeartBeat(NetworkChannelBase networkChannel, int missHeartBeatCount)
{
if (m_NetworkMissHeartBeatEventHandler != null)
{
lock (m_NetworkMissHeartBeatEventHandler)
{
NetworkMissHeartBeatEventArgs networkMissHeartBeatEventArgs = NetworkMissHeartBeatEventArgs.Create(networkChannel, missHeartBeatCount);
m_NetworkMissHeartBeatEventHandler(this, networkMissHeartBeatEventArgs);
MemoryPool.Release(networkMissHeartBeatEventArgs);
}
}
}
private void OnNetworkChannelError(NetworkChannelBase networkChannel, NetworkErrorCode errorCode, SocketError socketErrorCode, string errorMessage)
{
if (m_NetworkErrorEventHandler != null)
{
lock (m_NetworkErrorEventHandler)
{
NetworkErrorEventArgs networkErrorEventArgs = NetworkErrorEventArgs.Create(networkChannel, errorCode, socketErrorCode, errorMessage);
m_NetworkErrorEventHandler(this, networkErrorEventArgs);
MemoryPool.Release(networkErrorEventArgs);
}
}
}
private void OnNetworkChannelCustomError(NetworkChannelBase networkChannel, object customErrorData)
{
if (m_NetworkCustomErrorEventHandler != null)
{
lock (m_NetworkCustomErrorEventHandler)
{
NetworkCustomErrorEventArgs networkCustomErrorEventArgs = NetworkCustomErrorEventArgs.Create(networkChannel, customErrorData);
m_NetworkCustomErrorEventHandler(this, networkCustomErrorEventArgs);
MemoryPool.Release(networkCustomErrorEventArgs);
}
}
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 4ea28106108b496bb4b66fd8aa528797
timeCreated: 1661772444

View File

@@ -0,0 +1,10 @@
namespace TEngine.Runtime
{
/// <summary>
/// 网络消息包基类。
/// </summary>
public abstract class Packet : BaseEventArgs
{
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 4d54f03c4aed4afbab3b4fc45def97c5
timeCreated: 1661771739

View File

@@ -0,0 +1,28 @@
namespace TEngine.Runtime
{
/// <summary>
/// 网络服务类型。
/// </summary>
public enum ServiceType : byte
{
/// <summary>
/// TCP 网络服务。
/// </summary>
Tcp = 0,
/// <summary>
/// 使用同步接收的 TCP 网络服务。
/// </summary>
TcpWithSyncReceive,
/// <summary>
/// Udp 网络服务。
/// </summary>
Udp,
/// <summary>
/// Kcp 网络服务。
/// </summary>
Kcp,
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 11929818b1dbde74ba521dc2c5d03f49
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: bcf0e9cef581b5441ad604bfc2f771c4
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,283 @@
using System;
using System.Net;
using System.Net.Sockets;
namespace TEngine.Runtime
{
public sealed partial class NetworkManager
{
/// <summary>
/// TCP 网络频道。
/// </summary>
private sealed class TcpNetworkChannel : NetworkChannelBase
{
private readonly AsyncCallback m_ConnectCallback;
private readonly AsyncCallback m_SendCallback;
private readonly AsyncCallback m_ReceiveCallback;
/// <summary>
/// 初始化网络频道的新实例。
/// </summary>
/// <param name="name">网络频道名称。</param>
/// <param name="networkChannelHelper">网络频道辅助器。</param>
public TcpNetworkChannel(string name, INetworkChannelHelper networkChannelHelper)
: base(name, networkChannelHelper)
{
m_ConnectCallback = ConnectCallback;
m_SendCallback = SendCallback;
m_ReceiveCallback = ReceiveCallback;
}
/// <summary>
/// 获取网络服务类型。
/// </summary>
public override ServiceType ServiceType
{
get
{
return ServiceType.Tcp;
}
}
/// <summary>
/// 连接到远程主机。
/// </summary>
/// <param name="ipAddress">远程主机的 IP 地址。</param>
/// <param name="port">远程主机的端口号。</param>
/// <param name="userData">用户自定义数据。</param>
public override void Connect(IPAddress ipAddress, int port, object userData)
{
base.Connect(ipAddress, port, userData);
m_Socket = new Socket(ipAddress.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
if (m_Socket == null)
{
string errorMessage = "Initialize network channel failure.";
if (NetworkChannelError != null)
{
NetworkChannelError(this, NetworkErrorCode.SocketError, SocketError.Success, errorMessage);
return;
}
throw new Exception(errorMessage);
}
m_NetworkChannelHelper.PrepareForConnecting();
ConnectAsync(ipAddress, port, userData);
}
protected override bool ProcessSend()
{
if (base.ProcessSend())
{
SendAsync();
return true;
}
return false;
}
private void ConnectAsync(IPAddress ipAddress, int port, object userData)
{
try
{
m_Socket.BeginConnect(ipAddress, port, m_ConnectCallback, new ConnectState(m_Socket, userData));
}
catch (Exception exception)
{
if (NetworkChannelError != null)
{
SocketException socketException = exception as SocketException;
NetworkChannelError(this, NetworkErrorCode.ConnectError, socketException != null ? socketException.SocketErrorCode : SocketError.Success, exception.ToString());
return;
}
throw;
}
}
private void ConnectCallback(IAsyncResult ar)
{
ConnectState socketUserData = (ConnectState)ar.AsyncState;
try
{
socketUserData.Socket.EndConnect(ar);
}
catch (ObjectDisposedException)
{
return;
}
catch (Exception exception)
{
m_Active = false;
if (NetworkChannelError != null)
{
SocketException socketException = exception as SocketException;
NetworkChannelError(this, NetworkErrorCode.ConnectError, socketException != null ? socketException.SocketErrorCode : SocketError.Success, exception.ToString());
return;
}
throw;
}
m_SentPacketCount = 0;
m_ReceivedPacketCount = 0;
lock (m_SendPacketPool)
{
m_SendPacketPool.Clear();
}
m_ReceivePacketPool.Clear();
lock (m_HeartBeatState)
{
m_HeartBeatState.Reset(true);
}
if (NetworkChannelConnected != null)
{
NetworkChannelConnected(this, socketUserData.UserData);
}
m_Active = true;
ReceiveAsync();
}
private void SendAsync()
{
try
{
m_Socket.BeginSend(m_SendState.Stream.GetBuffer(), (int)m_SendState.Stream.Position, (int)(m_SendState.Stream.Length - m_SendState.Stream.Position), SocketFlags.None, m_SendCallback, m_Socket);
}
catch (Exception exception)
{
m_Active = false;
if (NetworkChannelError != null)
{
SocketException socketException = exception as SocketException;
NetworkChannelError(this, NetworkErrorCode.SendError, socketException != null ? socketException.SocketErrorCode : SocketError.Success, exception.ToString());
return;
}
throw;
}
}
private void SendCallback(IAsyncResult ar)
{
Socket socket = (Socket)ar.AsyncState;
if (!socket.Connected)
{
return;
}
int bytesSent = 0;
try
{
bytesSent = socket.EndSend(ar);
}
catch (Exception exception)
{
m_Active = false;
if (NetworkChannelError != null)
{
SocketException socketException = exception as SocketException;
NetworkChannelError(this, NetworkErrorCode.SendError, socketException != null ? socketException.SocketErrorCode : SocketError.Success, exception.ToString());
return;
}
throw;
}
m_SendState.Stream.Position += bytesSent;
if (m_SendState.Stream.Position < m_SendState.Stream.Length)
{
SendAsync();
return;
}
m_SentPacketCount++;
m_SendState.Reset();
}
private void ReceiveAsync()
{
try
{
m_Socket.BeginReceive(m_ReceiveState.Stream.GetBuffer(), (int)m_ReceiveState.Stream.Position, (int)(m_ReceiveState.Stream.Length - m_ReceiveState.Stream.Position), SocketFlags.None, m_ReceiveCallback, m_Socket);
}
catch (Exception exception)
{
m_Active = false;
if (NetworkChannelError != null)
{
SocketException socketException = exception as SocketException;
NetworkChannelError(this, NetworkErrorCode.ReceiveError, socketException != null ? socketException.SocketErrorCode : SocketError.Success, exception.ToString());
return;
}
throw;
}
}
private void ReceiveCallback(IAsyncResult ar)
{
Socket socket = (Socket)ar.AsyncState;
if (!socket.Connected)
{
return;
}
int bytesReceived = 0;
try
{
bytesReceived = socket.EndReceive(ar);
}
catch (Exception exception)
{
m_Active = false;
if (NetworkChannelError != null)
{
SocketException socketException = exception as SocketException;
NetworkChannelError(this, NetworkErrorCode.ReceiveError, socketException != null ? socketException.SocketErrorCode : SocketError.Success, exception.ToString());
return;
}
throw;
}
if (bytesReceived <= 0)
{
Close();
return;
}
m_ReceiveState.Stream.Position += bytesReceived;
if (m_ReceiveState.Stream.Position < m_ReceiveState.Stream.Length)
{
ReceiveAsync();
return;
}
m_ReceiveState.Stream.Position = 0L;
bool processSuccess = false;
if (m_ReceiveState.PacketHeader != null)
{
processSuccess = ProcessPacket();
m_ReceivedPacketCount++;
}
else
{
processSuccess = ProcessPacketHeader();
}
if (processSuccess)
{
ReceiveAsync();
return;
}
}
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 2df585ebfe0562642b66664dbf0feaaf
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,259 @@
using System;
using System.Net;
using System.Net.Sockets;
namespace TEngine.Runtime
{
public sealed partial class NetworkManager
{
/// <summary>
/// 使用同步接收的 TCP 网络频道。
/// </summary>
private sealed class TcpWithSyncReceiveNetworkChannel : NetworkChannelBase
{
private readonly AsyncCallback m_ConnectCallback;
private readonly AsyncCallback m_SendCallback;
/// <summary>
/// 初始化网络频道的新实例。
/// </summary>
/// <param name="name">网络频道名称。</param>
/// <param name="networkChannelHelper">网络频道辅助器。</param>
public TcpWithSyncReceiveNetworkChannel(string name, INetworkChannelHelper networkChannelHelper)
: base(name, networkChannelHelper)
{
m_ConnectCallback = ConnectCallback;
m_SendCallback = SendCallback;
}
/// <summary>
/// 获取网络服务类型。
/// </summary>
public override ServiceType ServiceType
{
get
{
return ServiceType.TcpWithSyncReceive;
}
}
/// <summary>
/// 连接到远程主机。
/// </summary>
/// <param name="ipAddress">远程主机的 IP 地址。</param>
/// <param name="port">远程主机的端口号。</param>
/// <param name="userData">用户自定义数据。</param>
public override void Connect(IPAddress ipAddress, int port, object userData)
{
base.Connect(ipAddress, port, userData);
m_Socket = new Socket(ipAddress.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
if (m_Socket == null)
{
string errorMessage = "Initialize network channel failure.";
if (NetworkChannelError != null)
{
NetworkChannelError(this, NetworkErrorCode.SocketError, SocketError.Success, errorMessage);
return;
}
throw new Exception(errorMessage);
}
m_NetworkChannelHelper.PrepareForConnecting();
ConnectAsync(ipAddress, port, userData);
}
protected override bool ProcessSend()
{
if (base.ProcessSend())
{
SendAsync();
return true;
}
return false;
}
protected override void ProcessReceive()
{
base.ProcessReceive();
while (m_Socket.Available > 0)
{
if (!ReceiveSync())
{
break;
}
}
}
private void ConnectAsync(IPAddress ipAddress, int port, object userData)
{
try
{
m_Socket.BeginConnect(ipAddress, port, m_ConnectCallback, new ConnectState(m_Socket, userData));
}
catch (Exception exception)
{
if (NetworkChannelError != null)
{
SocketException socketException = exception as SocketException;
NetworkChannelError(this, NetworkErrorCode.ConnectError, socketException != null ? socketException.SocketErrorCode : SocketError.Success, exception.ToString());
return;
}
throw;
}
}
private void ConnectCallback(IAsyncResult ar)
{
ConnectState socketUserData = (ConnectState)ar.AsyncState;
try
{
socketUserData.Socket.EndConnect(ar);
}
catch (ObjectDisposedException)
{
return;
}
catch (Exception exception)
{
m_Active = false;
if (NetworkChannelError != null)
{
SocketException socketException = exception as SocketException;
NetworkChannelError(this, NetworkErrorCode.ConnectError, socketException != null ? socketException.SocketErrorCode : SocketError.Success, exception.ToString());
return;
}
throw;
}
m_SentPacketCount = 0;
m_ReceivedPacketCount = 0;
lock (m_SendPacketPool)
{
m_SendPacketPool.Clear();
}
m_ReceivePacketPool.Clear();
lock (m_HeartBeatState)
{
m_HeartBeatState.Reset(true);
}
if (NetworkChannelConnected != null)
{
NetworkChannelConnected(this, socketUserData.UserData);
}
m_Active = true;
}
private void SendAsync()
{
try
{
m_Socket.BeginSend(m_SendState.Stream.GetBuffer(), (int)m_SendState.Stream.Position, (int)(m_SendState.Stream.Length - m_SendState.Stream.Position), SocketFlags.None, m_SendCallback, m_Socket);
}
catch (Exception exception)
{
m_Active = false;
if (NetworkChannelError != null)
{
SocketException socketException = exception as SocketException;
NetworkChannelError(this, NetworkErrorCode.SendError, socketException != null ? socketException.SocketErrorCode : SocketError.Success, exception.ToString());
return;
}
throw;
}
}
private void SendCallback(IAsyncResult ar)
{
Socket socket = (Socket)ar.AsyncState;
if (!socket.Connected)
{
return;
}
int bytesSent = 0;
try
{
bytesSent = socket.EndSend(ar);
}
catch (Exception exception)
{
m_Active = false;
if (NetworkChannelError != null)
{
SocketException socketException = exception as SocketException;
NetworkChannelError(this, NetworkErrorCode.SendError, socketException != null ? socketException.SocketErrorCode : SocketError.Success, exception.ToString());
return;
}
throw;
}
m_SendState.Stream.Position += bytesSent;
if (m_SendState.Stream.Position < m_SendState.Stream.Length)
{
SendAsync();
return;
}
m_SentPacketCount++;
m_SendState.Reset();
}
private bool ReceiveSync()
{
try
{
int bytesReceived = m_Socket.Receive(m_ReceiveState.Stream.GetBuffer(), (int)m_ReceiveState.Stream.Position, (int)(m_ReceiveState.Stream.Length - m_ReceiveState.Stream.Position), SocketFlags.None);
if (bytesReceived <= 0)
{
Close();
return false;
}
m_ReceiveState.Stream.Position += bytesReceived;
if (m_ReceiveState.Stream.Position < m_ReceiveState.Stream.Length)
{
return false;
}
m_ReceiveState.Stream.Position = 0L;
bool processSuccess = false;
if (m_ReceiveState.PacketHeader != null)
{
processSuccess = ProcessPacket();
m_ReceivedPacketCount++;
}
else
{
processSuccess = ProcessPacketHeader();
}
return processSuccess;
}
catch (Exception exception)
{
m_Active = false;
if (NetworkChannelError != null)
{
SocketException socketException = exception as SocketException;
NetworkChannelError(this, NetworkErrorCode.ReceiveError, socketException != null ? socketException.SocketErrorCode : SocketError.Success, exception.ToString());
return false;
}
throw;
}
}
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 19723c1417631894d90eef482924d87d
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 181b125a26149ad4bbc6f270738f37ce
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,276 @@
using System;
using System.Net;
using System.Net.Sockets;
namespace TEngine.Runtime
{
public sealed partial class NetworkManager
{
private sealed class UdpNetworkChannel : NetworkChannelBase
{
/// <summary>
/// 获取网络服务类型。
/// </summary>
public override ServiceType ServiceType => ServiceType.Udp;
private readonly AsyncCallback m_ConnectCallback;
private readonly AsyncCallback m_SendCallback;
private readonly AsyncCallback m_ReceiveCallback;
/// <summary>
/// 初始化网络频道的新实例。
/// </summary>
/// <param name="name">网络频道名称。</param>
/// <param name="networkChannelHelper">网络频道辅助器。</param>
public UdpNetworkChannel(string name, INetworkChannelHelper networkChannelHelper)
: base(name, networkChannelHelper)
{
m_ConnectCallback = ConnectCallback;
m_SendCallback = SendCallback;
m_ReceiveCallback = ReceiveCallback;
}
/// <summary>
/// 连接到远程主机。
/// </summary>
/// <param name="ipAddress">远程主机的 IP 地址。</param>
/// <param name="port">远程主机的端口号。</param>
/// <param name="userData">用户自定义数据。</param>
public override void Connect(IPAddress ipAddress, int port, object userData)
{
base.Connect(ipAddress, port, userData);
m_Socket = new Socket(ipAddress.AddressFamily, SocketType.Stream, ProtocolType.Udp);
if (m_Socket == null)
{
string errorMessage = "Initialize network channel failure.";
if (NetworkChannelError != null)
{
NetworkChannelError(this, NetworkErrorCode.SocketError, SocketError.Success, errorMessage);
return;
}
throw new Exception(errorMessage);
}
m_NetworkChannelHelper.PrepareForConnecting();
ConnectAsync(ipAddress, port, userData);
}
protected override bool ProcessSend()
{
if (base.ProcessSend())
{
SendAsync();
return true;
}
return false;
}
private void ConnectAsync(IPAddress ipAddress, int port, object userData)
{
try
{
m_Socket.BeginConnect(ipAddress, port, m_ConnectCallback, new ConnectState(m_Socket, userData));
}
catch (Exception exception)
{
if (NetworkChannelError != null)
{
SocketException socketException = exception as SocketException;
NetworkChannelError(this, NetworkErrorCode.ConnectError, socketException != null ? socketException.SocketErrorCode : SocketError.Success, exception.ToString());
return;
}
throw;
}
}
private void ConnectCallback(IAsyncResult ar)
{
ConnectState socketUserData = (ConnectState)ar.AsyncState;
try
{
socketUserData.Socket.EndConnect(ar);
}
catch (ObjectDisposedException)
{
return;
}
catch (Exception exception)
{
m_Active = false;
if (NetworkChannelError != null)
{
SocketException socketException = exception as SocketException;
NetworkChannelError(this, NetworkErrorCode.ConnectError, socketException != null ? socketException.SocketErrorCode : SocketError.Success, exception.ToString());
return;
}
throw;
}
m_SentPacketCount = 0;
m_ReceivedPacketCount = 0;
lock (m_SendPacketPool)
{
m_SendPacketPool.Clear();
}
m_ReceivePacketPool.Clear();
lock (m_HeartBeatState)
{
m_HeartBeatState.Reset(true);
}
if (NetworkChannelConnected != null)
{
NetworkChannelConnected(this, socketUserData.UserData);
}
m_Active = true;
ReceiveAsync();
}
private void SendAsync()
{
try
{
m_Socket.BeginSend(m_SendState.Stream.GetBuffer(), (int)m_SendState.Stream.Position, (int)(m_SendState.Stream.Length - m_SendState.Stream.Position), SocketFlags.None, m_SendCallback, m_Socket);
}
catch (Exception exception)
{
m_Active = false;
if (NetworkChannelError != null)
{
SocketException socketException = exception as SocketException;
NetworkChannelError(this, NetworkErrorCode.SendError, socketException != null ? socketException.SocketErrorCode : SocketError.Success, exception.ToString());
return;
}
throw;
}
}
private void SendCallback(IAsyncResult ar)
{
Socket socket = (Socket)ar.AsyncState;
if (!socket.Connected)
{
return;
}
int bytesSent = 0;
try
{
bytesSent = socket.EndSend(ar);
}
catch (Exception exception)
{
m_Active = false;
if (NetworkChannelError != null)
{
SocketException socketException = exception as SocketException;
NetworkChannelError(this, NetworkErrorCode.SendError, socketException != null ? socketException.SocketErrorCode : SocketError.Success, exception.ToString());
return;
}
throw;
}
m_SendState.Stream.Position += bytesSent;
if (m_SendState.Stream.Position < m_SendState.Stream.Length)
{
SendAsync();
return;
}
m_SentPacketCount++;
m_SendState.Reset();
}
private void ReceiveAsync()
{
try
{
m_Socket.BeginReceive(m_ReceiveState.Stream.GetBuffer(), (int)m_ReceiveState.Stream.Position, (int)(m_ReceiveState.Stream.Length - m_ReceiveState.Stream.Position), SocketFlags.None, m_ReceiveCallback, m_Socket);
}
catch (Exception exception)
{
m_Active = false;
if (NetworkChannelError != null)
{
SocketException socketException = exception as SocketException;
NetworkChannelError(this, NetworkErrorCode.ReceiveError, socketException != null ? socketException.SocketErrorCode : SocketError.Success, exception.ToString());
return;
}
throw;
}
}
private void ReceiveCallback(IAsyncResult ar)
{
Socket socket = (Socket)ar.AsyncState;
if (!socket.Connected)
{
return;
}
int bytesReceived = 0;
try
{
bytesReceived = socket.EndReceive(ar);
}
catch (Exception exception)
{
m_Active = false;
if (NetworkChannelError != null)
{
SocketException socketException = exception as SocketException;
NetworkChannelError(this, NetworkErrorCode.ReceiveError, socketException != null ? socketException.SocketErrorCode : SocketError.Success, exception.ToString());
return;
}
throw;
}
if (bytesReceived <= 0)
{
Close();
return;
}
m_ReceiveState.Stream.Position += bytesReceived;
if (m_ReceiveState.Stream.Position < m_ReceiveState.Stream.Length)
{
ReceiveAsync();
return;
}
m_ReceiveState.Stream.Position = 0L;
bool processSuccess = false;
if (m_ReceiveState.PacketHeader != null)
{
processSuccess = ProcessPacket();
m_ReceivedPacketCount++;
}
else
{
processSuccess = ProcessPacketHeader();
}
if (processSuccess)
{
ReceiveAsync();
return;
}
}
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 17b9e06584f10da45a8a3ca27fd5e654
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant: