黄宗银 1 year ago
parent
commit
68dfee147e

+ 24 - 8
Debug/net8.0/Apq.Web5.deps.json

@@ -72,6 +72,14 @@
           }
         }
       },
+      "Fleck/1.2.0": {
+        "runtime": {
+          "lib/netcoreapp2.0/Fleck.dll": {
+            "assemblyVersion": "1.2.0.0",
+            "fileVersion": "1.2.0.0"
+          }
+        }
+      },
       "Google.Protobuf/3.25.1": {
         "runtime": {
           "lib/net5.0/Google.Protobuf.dll": {
@@ -120,14 +128,14 @@
           }
         }
       },
-      "log4net/2.0.15": {
+      "log4net/2.0.16": {
         "dependencies": {
           "System.Configuration.ConfigurationManager": "6.0.1"
         },
         "runtime": {
           "lib/netstandard2.0/log4net.dll": {
-            "assemblyVersion": "2.0.15.0",
-            "fileVersion": "2.0.15.0"
+            "assemblyVersion": "2.0.16.0",
+            "fileVersion": "2.0.16.0"
           }
         }
       },
@@ -873,6 +881,7 @@
         "dependencies": {
           "AntiXSS.NetStandard": "0.1.125",
           "ConsoleTables": "2.6.1",
+          "Fleck": "1.2.0",
           "GuerrillaNtp": "3.1.0",
           "Microsoft.Extensions.Configuration.EnvironmentVariables": "8.0.0",
           "Microsoft.Extensions.Configuration.Ini": "8.0.0",
@@ -889,7 +898,7 @@
           "System.Linq.Dynamic.Core": "1.3.10",
           "System.Reactive": "6.0.0",
           "UTF.Unknown": "2.5.1",
-          "log4net": "2.0.15"
+          "log4net": "2.0.16"
         },
         "runtime": {
           "Apq.dll": {}
@@ -938,6 +947,13 @@
       "path": "entityframework/6.4.4",
       "hashPath": "entityframework.6.4.4.nupkg.sha512"
     },
+    "Fleck/1.2.0": {
+      "type": "package",
+      "serviceable": true,
+      "sha512": "sha512-bPLXn6QbLAFoviur6XbrKB0Zn6x04E8VibHXyHZeJsoC7bkUl5DVtzM5cZgDuqHkIrBqAXJyTNJwSNIc6wBJ2Q==",
+      "path": "fleck/1.2.0",
+      "hashPath": "fleck.1.2.0.nupkg.sha512"
+    },
     "Google.Protobuf/3.25.1": {
       "type": "package",
       "serviceable": true,
@@ -973,12 +989,12 @@
       "path": "k4os.hash.xxhash/1.0.8",
       "hashPath": "k4os.hash.xxhash.1.0.8.nupkg.sha512"
     },
-    "log4net/2.0.15": {
+    "log4net/2.0.16": {
       "type": "package",
       "serviceable": true,
-      "sha512": "sha512-GahnO9ZgFka+xYcFwAfIFjW+k86P2nxFoaEpH6t3v4hiGj7tv2ksVZphxCVIHmJxoySS0HeU3dgCW+bSCcfD0A==",
-      "path": "log4net/2.0.15",
-      "hashPath": "log4net.2.0.15.nupkg.sha512"
+      "sha512": "sha512-6MoFh1BB83ZPiUHXlIJQZsoXSMlwnrNHmiPTGCobA6Ik3fmeNVLgEwF0MjxZtec2PfB0WdL81XCAtxjrummCCg==",
+      "path": "log4net/2.0.16",
+      "hashPath": "log4net.2.0.16.nupkg.sha512"
     },
     "Microsoft.CSharp/4.7.0": {
       "type": "package",

BIN
Debug/net8.0/Apq.Web5.dll


BIN
Debug/net8.0/Apq.Web5.pdb


+ 24 - 8
Debug/net8.0/Apq.deps.json

@@ -10,6 +10,7 @@
         "dependencies": {
           "AntiXSS.NetStandard": "0.1.125",
           "ConsoleTables": "2.6.1",
+          "Fleck": "1.2.0",
           "GuerrillaNtp": "3.1.0",
           "Microsoft.Extensions.Configuration.EnvironmentVariables": "8.0.0",
           "Microsoft.Extensions.Configuration.Ini": "8.0.0",
@@ -26,7 +27,7 @@
           "System.Linq.Dynamic.Core": "1.3.10",
           "System.Reactive": "6.0.0",
           "UTF.Unknown": "2.5.1",
-          "log4net": "2.0.15"
+          "log4net": "2.0.16"
         },
         "runtime": {
           "Apq.dll": {}
@@ -89,6 +90,14 @@
           }
         }
       },
+      "Fleck/1.2.0": {
+        "runtime": {
+          "lib/netcoreapp2.0/Fleck.dll": {
+            "assemblyVersion": "1.2.0.0",
+            "fileVersion": "1.2.0.0"
+          }
+        }
+      },
       "Google.Protobuf/3.25.1": {
         "runtime": {
           "lib/net5.0/Google.Protobuf.dll": {
@@ -137,14 +146,14 @@
           }
         }
       },
-      "log4net/2.0.15": {
+      "log4net/2.0.16": {
         "dependencies": {
           "System.Configuration.ConfigurationManager": "6.0.0"
         },
         "runtime": {
           "lib/netstandard2.0/log4net.dll": {
-            "assemblyVersion": "2.0.15.0",
-            "fileVersion": "2.0.15.0"
+            "assemblyVersion": "2.0.16.0",
+            "fileVersion": "2.0.16.0"
           }
         }
       },
@@ -997,6 +1006,13 @@
       "path": "entityframework/6.4.4",
       "hashPath": "entityframework.6.4.4.nupkg.sha512"
     },
+    "Fleck/1.2.0": {
+      "type": "package",
+      "serviceable": true,
+      "sha512": "sha512-bPLXn6QbLAFoviur6XbrKB0Zn6x04E8VibHXyHZeJsoC7bkUl5DVtzM5cZgDuqHkIrBqAXJyTNJwSNIc6wBJ2Q==",
+      "path": "fleck/1.2.0",
+      "hashPath": "fleck.1.2.0.nupkg.sha512"
+    },
     "Google.Protobuf/3.25.1": {
       "type": "package",
       "serviceable": true,
@@ -1032,12 +1048,12 @@
       "path": "k4os.hash.xxhash/1.0.8",
       "hashPath": "k4os.hash.xxhash.1.0.8.nupkg.sha512"
     },
-    "log4net/2.0.15": {
+    "log4net/2.0.16": {
       "type": "package",
       "serviceable": true,
-      "sha512": "sha512-GahnO9ZgFka+xYcFwAfIFjW+k86P2nxFoaEpH6t3v4hiGj7tv2ksVZphxCVIHmJxoySS0HeU3dgCW+bSCcfD0A==",
-      "path": "log4net/2.0.15",
-      "hashPath": "log4net.2.0.15.nupkg.sha512"
+      "sha512": "sha512-6MoFh1BB83ZPiUHXlIJQZsoXSMlwnrNHmiPTGCobA6Ik3fmeNVLgEwF0MjxZtec2PfB0WdL81XCAtxjrummCCg==",
+      "path": "log4net/2.0.16",
+      "hashPath": "log4net.2.0.16.nupkg.sha512"
     },
     "Microsoft.CSharp/4.7.0": {
       "type": "package",

BIN
Debug/net8.0/Apq.dll


BIN
Debug/net8.0/Apq.pdb


+ 558 - 5
Debug/net8.0/Apq.xml

@@ -3311,6 +3311,11 @@
             全局对象
             </summary>
         </member>
+        <member name="P:Apq.GlobalObject.TheAssembly">
+            <summary>
+            该程序集
+            </summary>
+        </member>
         <member name="P:Apq.GlobalObject.TheProcess">
             <summary>
             当前进程
@@ -3321,11 +3326,6 @@
             当前程序的入口目录。入口程序集(dll或exe)所在目录(以"\"结尾的绝对路径)
             </summary>
         </member>
-        <member name="P:Apq.GlobalObject.TheAssembly">
-            <summary>
-            该程序集
-            </summary>
-        </member>
         <member name="P:Apq.GlobalObject.DllFolder">
             <summary>
             本程序集(dll或exe)所在目录(以"\"结尾的绝对路径)
@@ -3341,6 +3341,11 @@
             Config目录(以"\"结尾)
             </summary>
         </member>
+        <member name="P:Apq.GlobalObject.LogFolder">
+            <summary>
+            日志目录(以"\"结尾)
+            </summary>
+        </member>
         <member name="P:Apq.GlobalObject.NamedInstances">
             <summary>
             命名实例集合
@@ -3476,6 +3481,66 @@
             </summary>
             <remarks>该方法不会产生异常</remarks>
         </member>
+        <member name="T:Apq.Net.FleckWebSocketServer">
+            <summary>
+            代表一个已连接到客户端的长连接(服务端)
+            </summary>
+            <remarks>WebSocket</remarks>
+        </member>
+        <member name="M:Apq.Net.FleckWebSocketServer.#ctor(Fleck.IWebSocketConnection)">
+            <summary>
+            代表一个已连接到客户端的长连接(服务端)
+            </summary>
+            <remarks>WebSocket</remarks>
+        </member>
+        <member name="P:Apq.Net.FleckWebSocketServer.WebSocket">
+            <summary>
+            WebSocket
+            </summary>
+        </member>
+        <member name="M:Apq.Net.FleckWebSocketServer.BindClient">
+            <summary>
+            设置Client相关事件的处理
+            </summary>
+        </member>
+        <member name="M:Apq.Net.FleckWebSocketServer.UnBindClient">
+            <summary>
+            取消Client相关事件的处理
+            </summary>
+        </member>
+        <member name="P:Apq.Net.FleckWebSocketServer.Connected">
+            <summary>
+            是否已连接
+            </summary>
+        </member>
+        <member name="P:Apq.Net.FleckWebSocketServer.ShouldClose">
+            <summary>
+            连接是否应该关闭(已空闲过久)
+            </summary>
+        </member>
+        <member name="M:Apq.Net.FleckWebSocketServer.DoTask_Close(System.String,System.Boolean)">
+            <summary>
+            关闭长连接(实现)
+            </summary>
+            <returns>是否关闭成功</returns>
+        </member>
+        <member name="M:Apq.Net.FleckWebSocketServer.DoSend(System.Collections.Generic.IList{System.Byte},System.Threading.CancellationToken)">
+            <summary>
+            发送数据到客户端(实现)
+            </summary>
+            <returns>是否发送成功</returns>
+        </member>
+        <member name="M:Apq.Net.FleckWebSocketServer.DoSend(System.String,System.Threading.CancellationToken)">
+            <summary>
+            发送消息到客户端(实现)
+            </summary>
+            <returns>是否发送成功</returns>
+        </member>
+        <member name="M:Apq.Net.FleckWebSocketServer.DoTask_HeartBeat(System.Threading.CancellationToken)">
+            <summary>
+            任务实现:心跳检测
+            </summary>
+        </member>
         <member name="T:Apq.Net.HttpClientHelper">
             <summary>
             使用HttpClient进行Http访问
@@ -3542,6 +3607,453 @@
             <param name="Min">最小值(含)</param>
             <param name="Max">最大值(含)</param>
         </member>
+        <!-- Badly formed XML comment ignored for member "T:Apq.Net.PersistentClient" -->
+        <!-- Badly formed XML comment ignored for member "M:Apq.Net.PersistentClient.#ctor(System.Object)" -->
+        <member name="P:Apq.Net.PersistentClient.Server">
+            <summary>
+            域名/IP/Url
+            </summary>
+        </member>
+        <member name="P:Apq.Net.PersistentClient.Port">
+            <summary>
+            端口
+            </summary>
+        </member>
+        <member name="P:Apq.Net.PersistentClient.SessionID">
+            <summary>
+            由服务端分配的会话ID(客户端标识)
+            </summary>
+        </member>
+        <member name="P:Apq.Net.PersistentClient.Client">
+            <summary>
+            客户端
+            </summary>
+        </member>
+        <member name="P:Apq.Net.PersistentClient.SrLock">
+            <summary>
+            数据收发锁,防止并发(即不能同时进行多个连接、发送或接收)
+            </summary>
+        </member>
+        <member name="P:Apq.Net.PersistentClient.CTS_Connect">
+            <summary>
+            任务的取消令牌:连接、接收、心跳、[发送]
+            </summary>
+        </member>
+        <member name="P:Apq.Net.PersistentClient.CTS_PreConnect">
+            <summary>
+            任务的取消令牌:上一次连接
+            </summary>
+        </member>
+        <member name="P:Apq.Net.PersistentClient.Provider_NewClient">
+            <summary>
+            提供:创建新连接实例的方法。重连时使用
+            </summary>
+        </member>
+        <member name="M:Apq.Net.PersistentClient.Init">
+            <summary>
+            对此实例进行初始化(绑定事件、启动任务等)
+            </summary>
+        </member>
+        <member name="M:Apq.Net.PersistentClient.Dispose(System.Boolean)">
+            <param name="disposing">指定释放类型{true:托管对象,false:未托管对象}</param>
+        </member>
+        <member name="M:Apq.Net.PersistentClient.BindClient">
+            <summary>
+            设置Client相关事件的处理
+            </summary>
+        </member>
+        <member name="M:Apq.Net.PersistentClient.UnBindClient">
+            <summary>
+            取消Client相关事件的处理
+            </summary>
+        </member>
+        <member name="P:Apq.Net.PersistentClient.Connected">
+            <summary>
+            是否已连接
+            </summary>
+        </member>
+        <member name="P:Apq.Net.PersistentClient.TryTimes">
+            <summary>
+            已尝试连接的次数
+            </summary>
+        </member>
+        <!-- Badly formed XML comment ignored for member "P:Apq.Net.PersistentClient.MaxTryTimes" -->
+        <member name="P:Apq.Net.PersistentClient.IsConnecting">
+            <summary>
+            是否正在连接(用于防止重复发起连接)
+            </summary>
+        </member>
+        <member name="P:Apq.Net.PersistentClient.LastConnectTime">
+            <summary>
+            最后发起连接的时间
+            </summary>
+        </member>
+        <member name="P:Apq.Net.PersistentClient.HadConnected">
+            <summary>
+            是否曾连接成功过
+            </summary>
+        </member>
+        <member name="M:Apq.Net.PersistentClient.Connect(System.Threading.CancellationToken)">
+            <summary>
+            连接到服务器(最多自动重连MaxTryTimes次)
+            </summary>
+            <returns>是否成功</returns>
+        </member>
+        <member name="M:Apq.Net.PersistentClient.TryConnect(System.Int32,System.Threading.CancellationToken)">
+            <summary>
+            连接到服务器(最多重连指定次数)
+            </summary>
+            <returns>是否成功</returns>
+        </member>
+        <member name="M:Apq.Net.PersistentClient.TryConnectOnce(System.Threading.CancellationToken)">
+            <summary>
+            尝试连接到服务器(一次)
+            </summary>
+            <returns>是否成功</returns>
+        </member>
+        <member name="M:Apq.Net.PersistentClient.DoTask_Connect(System.Threading.CancellationToken)">
+            <summary>
+            执行一次连接
+            </summary>
+            <returns>是否连接成功</returns>
+        </member>
+        <member name="E:Apq.Net.PersistentClient.AfterConnectTimeout">
+            <summary>
+            连接超时事件
+            </summary>
+        </member>
+        <member name="E:Apq.Net.PersistentClient.AfterConnectError">
+            <summary>
+            连接过程中发生异常时
+            </summary>
+        </member>
+        <member name="E:Apq.Net.PersistentClient.AfterConnected">
+            <summary>
+            连接成功事件
+            </summary>
+        </member>
+        <member name="M:Apq.Net.PersistentClient.OnAfterConnected">
+            <summary>
+            连接成功后的处理
+            </summary>
+        </member>
+        <member name="P:Apq.Net.PersistentClient.ShouldClose">
+            <summary>
+            连接是否应该关闭(已空闲过久)
+            </summary>
+        </member>
+        <member name="P:Apq.Net.PersistentClient.CloseReason">
+            <summary>
+            关闭原因(只接受第一次非空赋值)
+            </summary>
+        </member>
+        <member name="P:Apq.Net.PersistentClient.IsCloseByServer">
+            <summary>
+            是否是被服务端断开导致关闭的
+            </summary>
+        </member>
+        <member name="E:Apq.Net.PersistentClient.BeforeClose">
+            <summary>
+            连接关闭前
+            </summary>
+        </member>
+        <member name="E:Apq.Net.PersistentClient.AfterClose">
+            <summary>
+            连接关闭后
+            </summary>
+        </member>
+        <member name="M:Apq.Net.PersistentClient.Close(System.String,System.Boolean)">
+            <summary>
+            在新任务中关闭长连接
+            </summary>
+        </member>
+        <member name="M:Apq.Net.PersistentClient.DoTask_Close(System.String,System.Boolean)">
+            <summary>
+            任务实现:关闭长连接
+            </summary>
+            <returns>是否关闭成功</returns>
+            <remarks>基类实现了停止连接任务</remarks>
+        </member>
+        <member name="M:Apq.Net.PersistentClient.Send(System.Collections.Generic.IList{System.Byte},System.Threading.CancellationToken)">
+            <summary>
+            发送数据到服务端
+            </summary>
+            <returns>是否发送成功</returns>
+        </member>
+        <member name="M:Apq.Net.PersistentClient.DoSend(System.Collections.Generic.IList{System.Byte},System.Threading.CancellationToken)">
+            <summary>
+            发送数据到服务端(实现)
+            </summary>
+            <returns>是否发送成功</returns>
+        </member>
+        <member name="M:Apq.Net.PersistentClient.Send(System.String,System.Threading.CancellationToken)">
+            <summary>
+            发送消息到服务端
+            </summary>
+            <returns>是否发送成功</returns>
+        </member>
+        <member name="M:Apq.Net.PersistentClient.DoSend(System.String,System.Threading.CancellationToken)">
+            <summary>
+            发送消息到服务端(实现)
+            </summary>
+            <returns>是否发送成功</returns>
+        </member>
+        <member name="E:Apq.Net.PersistentClient.BeforeSend">
+            <summary>
+            发送前
+            </summary>
+        </member>
+        <member name="E:Apq.Net.PersistentClient.AfterSend">
+            <summary>
+            发送后
+            </summary>
+        </member>
+        <member name="E:Apq.Net.PersistentClient.BeforeSendMsg">
+            <summary>
+            发送前(文本)
+            </summary>
+        </member>
+        <member name="E:Apq.Net.PersistentClient.AfterSendMsg">
+            <summary>
+            发送后(文本)
+            </summary>
+        </member>
+        <member name="M:Apq.Net.PersistentClient.StartReceive(System.Threading.CancellationToken)">
+            <summary>
+            启动接收任务
+            </summary>
+        </member>
+        <member name="M:Apq.Net.PersistentClient.DoTask_Receive(System.Threading.CancellationToken)">
+            <summary>
+            任务实现:接收
+            </summary>
+        </member>
+        <member name="E:Apq.Net.PersistentClient.AfterReceiveMsg">
+            <summary>
+            接收到服务端发送的消息后
+            </summary>
+        </member>
+        <member name="E:Apq.Net.PersistentClient.AfterReceiveData">
+            <summary>
+            接收到服务端发送的数据后
+            </summary>
+        </member>
+        <member name="P:Apq.Net.PersistentClient.LastActiveTime">
+            <summary>
+            最后心跳时间
+            </summary>
+        </member>
+        <member name="P:Apq.Net.PersistentClient.Provider_HeartBeatMsg">
+            <summary>
+            提供心跳消息(返回不为空就发)
+            </summary>
+        </member>
+        <member name="P:Apq.Net.PersistentClient.Provider_HeartBeatData">
+            <summary>
+            提供心跳数据(返回不为空就发)
+            </summary>
+        </member>
+        <!-- Badly formed XML comment ignored for member "P:Apq.Net.PersistentClient.MaxTryTimesWhenInterrupted" -->
+        <member name="P:Apq.Net.PersistentClient.CTS_ReconnectWhenInterrupted">
+            <summary>
+            任务的取消令牌:断线重连
+            </summary>
+        </member>
+        <member name="M:Apq.Net.PersistentClient.StartHeartBeat(System.Threading.CancellationToken)">
+            <summary>
+            启动心跳任务
+            </summary>
+        </member>
+        <member name="M:Apq.Net.PersistentClient.DoTask_HeartBeat(System.Threading.CancellationToken)">
+            <summary>
+            任务实现:心跳检测
+            </summary>
+        </member>
+        <member name="E:Apq.Net.PersistentClient.AfterHeartBeatTimeout">
+            <summary>
+            心跳超时后
+            </summary>
+            <returns>是否取消心跳任务</returns>
+        </member>
+        <member name="M:Apq.Net.PersistentClient.OnAfterHeartBeatTimeout">
+            <summary>
+            心跳超时后的处理
+            </summary>
+            <returns>是否取消心跳任务</returns>
+        </member>
+        <member name="T:Apq.Net.PersistentServer">
+            <summary>
+            代表一个已连接到客户端的长连接(服务端)
+            </summary>
+            <param name="client">IWebSocketConnection或Socket</param>
+        </member>
+        <member name="M:Apq.Net.PersistentServer.#ctor(System.Object)">
+            <summary>
+            代表一个已连接到客户端的长连接(服务端)
+            </summary>
+            <param name="client">IWebSocketConnection或Socket</param>
+        </member>
+        <member name="P:Apq.Net.PersistentServer.SessionID">
+            <summary>
+            自动分配客户端标识(会话ID)
+            </summary>
+        </member>
+        <member name="P:Apq.Net.PersistentServer.Client">
+            <summary>
+            已接受的客户端(已连接)
+            </summary>
+        </member>
+        <member name="P:Apq.Net.PersistentServer.CTS_Work">
+            <summary>
+            任务的取消令牌:与连接关联的所有任务
+            </summary>
+        </member>
+        <member name="M:Apq.Net.PersistentServer.Init">
+            <summary>
+            对实例进行初始化
+            </summary>
+        </member>
+        <member name="M:Apq.Net.PersistentServer.Dispose(System.Boolean)">
+            <param name="disposing">指定释放类型{true:托管对象,false:未托管对象}</param>
+        </member>
+        <member name="M:Apq.Net.PersistentServer.BindClient">
+            <summary>
+            设置Client相关事件的处理
+            </summary>
+        </member>
+        <member name="M:Apq.Net.PersistentServer.UnBindClient">
+            <summary>
+            取消Client相关事件的处理
+            </summary>
+        </member>
+        <member name="P:Apq.Net.PersistentServer.ShouldAbandon">
+            <summary>
+            此连接是否应抛弃(不能再用了)
+            </summary>
+        </member>
+        <member name="P:Apq.Net.PersistentServer.Connected">
+            <summary>
+            是否已连接
+            </summary>
+        </member>
+        <member name="P:Apq.Net.PersistentServer.ShouldClose">
+            <summary>
+            连接是否应该关闭(已空闲过久)
+            </summary>
+        </member>
+        <member name="P:Apq.Net.PersistentServer.CloseReason">
+            <summary>
+            关闭原因(只接受第一次非空赋值)
+            </summary>
+        </member>
+        <member name="P:Apq.Net.PersistentServer.IsCloseByClient">
+            <summary>
+            是否是被客户端断开导致关闭的
+            </summary>
+        </member>
+        <member name="E:Apq.Net.PersistentServer.BeforeClose">
+            <summary>
+            连接关闭前
+            </summary>
+        </member>
+        <member name="E:Apq.Net.PersistentServer.AfterClose">
+            <summary>
+            连接关闭后
+            </summary>
+        </member>
+        <member name="M:Apq.Net.PersistentServer.Close(System.String,System.Boolean)">
+            <summary>
+            新任务中关闭长连接
+            </summary>
+        </member>
+        <member name="M:Apq.Net.PersistentServer.DoTask_Close(System.String,System.Boolean)">
+            <summary>
+            任务实现:关闭长连接
+            </summary>
+            <returns>是否关闭成功</returns>
+        </member>
+        <member name="M:Apq.Net.PersistentServer.Send(System.Collections.Generic.IList{System.Byte},System.Threading.CancellationToken)">
+            <summary>
+            发送数据到客户端
+            </summary>
+            <returns>是否发送成功</returns>
+        </member>
+        <member name="M:Apq.Net.PersistentServer.DoSend(System.Collections.Generic.IList{System.Byte},System.Threading.CancellationToken)">
+            <summary>
+            发送数据到客户端(实现)
+            </summary>
+            <returns>是否发送成功</returns>
+        </member>
+        <member name="M:Apq.Net.PersistentServer.Send(System.String,System.Threading.CancellationToken)">
+            <summary>
+            发送消息到客户端
+            </summary>
+            <returns>是否发送成功</returns>
+        </member>
+        <member name="M:Apq.Net.PersistentServer.DoSend(System.String,System.Threading.CancellationToken)">
+            <summary>
+            发送消息到客户端(实现)
+            </summary>
+            <returns>是否发送成功</returns>
+        </member>
+        <member name="E:Apq.Net.PersistentServer.BeforeSend">
+            <summary>
+            发送前
+            </summary>
+        </member>
+        <member name="E:Apq.Net.PersistentServer.AfterSend">
+            <summary>
+            发送后
+            </summary>
+        </member>
+        <member name="E:Apq.Net.PersistentServer.BeforeSendMsg">
+            <summary>
+            发送前(文本)
+            </summary>
+        </member>
+        <member name="E:Apq.Net.PersistentServer.AfterSendMsg">
+            <summary>
+            发送后(文本)
+            </summary>
+        </member>
+        <member name="E:Apq.Net.PersistentServer.AfterReceiveMsg">
+            <summary>
+            接收到客户端发送的消息后
+            </summary>
+        </member>
+        <member name="E:Apq.Net.PersistentServer.AfterReceiveData">
+            <summary>
+            接收到客户端发送的数据后
+            </summary>
+        </member>
+        <member name="P:Apq.Net.PersistentServer.LastActiveTime">
+            <summary>
+            最后心跳时间(由客户端发起)
+            </summary>
+        </member>
+        <member name="M:Apq.Net.PersistentServer.StartHeartBeat(System.Threading.CancellationToken)">
+            <summary>
+            启动心跳任务
+            </summary>
+        </member>
+        <member name="E:Apq.Net.PersistentServer.AfterHeartBeatTimeout">
+            <summary>
+            心跳超时后
+            </summary>
+            <returns>是否取消心跳任务</returns>
+        </member>
+        <member name="M:Apq.Net.PersistentServer.OnAfterHeartBeatTimeout">
+            <summary>
+            心跳超时后的处理
+            </summary>
+            <returns>是否取消心跳任务</returns>
+        </member>
+        <member name="M:Apq.Net.PersistentServer.DoTask_HeartBeat(System.Int32,System.Threading.CancellationToken)">
+            <summary>
+            任务实现:心跳检测
+            </summary>
+            <param name="interval">间隔(毫秒)</param>
+        </member>
         <member name="T:Apq.Net.PortEndPoint">
             <summary>
             端口端点
@@ -3591,6 +4103,47 @@
             参考来自 stackoverflow
             </summary>
         </member>
+        <!-- Badly formed XML comment ignored for member "T:Apq.Net.TcClient" -->
+        <!-- Badly formed XML comment ignored for member "M:Apq.Net.TcClient.#ctor(System.Net.Sockets.TcpClient)" -->
+        <member name="P:Apq.Net.TcClient.TcpClient">
+            <summary>
+            TcpClient
+            </summary>
+        </member>
+        <member name="P:Apq.Net.TcClient.Connected">
+            <summary>
+            是否已连接
+            </summary>
+        </member>
+        <member name="M:Apq.Net.TcClient.DoTask_Connect(System.Threading.CancellationToken)">
+            <summary>
+            执行一次连接
+            </summary>
+            <returns>是否连接成功</returns>
+        </member>
+        <member name="M:Apq.Net.TcClient.DoTask_Close(System.String,System.Boolean)">
+            <summary>
+            任务实现:关闭长连接
+            </summary>
+            <returns>是否关闭成功</returns>
+        </member>
+        <member name="M:Apq.Net.TcClient.DoSend(System.Collections.Generic.IList{System.Byte},System.Threading.CancellationToken)">
+            <summary>
+            发送数据到服务端(实现)
+            </summary>
+            <returns>是否发送成功</returns>
+        </member>
+        <member name="M:Apq.Net.TcClient.DoSend(System.String,System.Threading.CancellationToken)">
+            <summary>
+            发送消息到服务端
+            </summary>
+            <returns>是否发送成功</returns>
+        </member>
+        <member name="M:Apq.Net.TcClient.DoTask_Receive(System.Threading.CancellationToken)">
+            <summary>
+            任务实现:接收
+            </summary>
+        </member>
         <member name="M:Apq.Net.UrlHelper.GetUrlWithoutParams(System.String,System.Collections.Generic.IEnumerable{System.String})">
             <summary>
             获取不含参数的url

+ 24 - 8
Release/net8.0/Apq.Web5.deps.json

@@ -72,6 +72,14 @@
           }
         }
       },
+      "Fleck/1.2.0": {
+        "runtime": {
+          "lib/netcoreapp2.0/Fleck.dll": {
+            "assemblyVersion": "1.2.0.0",
+            "fileVersion": "1.2.0.0"
+          }
+        }
+      },
       "Google.Protobuf/3.25.1": {
         "runtime": {
           "lib/net5.0/Google.Protobuf.dll": {
@@ -120,14 +128,14 @@
           }
         }
       },
-      "log4net/2.0.15": {
+      "log4net/2.0.16": {
         "dependencies": {
           "System.Configuration.ConfigurationManager": "6.0.1"
         },
         "runtime": {
           "lib/netstandard2.0/log4net.dll": {
-            "assemblyVersion": "2.0.15.0",
-            "fileVersion": "2.0.15.0"
+            "assemblyVersion": "2.0.16.0",
+            "fileVersion": "2.0.16.0"
           }
         }
       },
@@ -873,6 +881,7 @@
         "dependencies": {
           "AntiXSS.NetStandard": "0.1.125",
           "ConsoleTables": "2.6.1",
+          "Fleck": "1.2.0",
           "GuerrillaNtp": "3.1.0",
           "Microsoft.Extensions.Configuration.EnvironmentVariables": "8.0.0",
           "Microsoft.Extensions.Configuration.Ini": "8.0.0",
@@ -889,7 +898,7 @@
           "System.Linq.Dynamic.Core": "1.3.10",
           "System.Reactive": "6.0.0",
           "UTF.Unknown": "2.5.1",
-          "log4net": "2.0.15"
+          "log4net": "2.0.16"
         },
         "runtime": {
           "Apq.dll": {}
@@ -938,6 +947,13 @@
       "path": "entityframework/6.4.4",
       "hashPath": "entityframework.6.4.4.nupkg.sha512"
     },
+    "Fleck/1.2.0": {
+      "type": "package",
+      "serviceable": true,
+      "sha512": "sha512-bPLXn6QbLAFoviur6XbrKB0Zn6x04E8VibHXyHZeJsoC7bkUl5DVtzM5cZgDuqHkIrBqAXJyTNJwSNIc6wBJ2Q==",
+      "path": "fleck/1.2.0",
+      "hashPath": "fleck.1.2.0.nupkg.sha512"
+    },
     "Google.Protobuf/3.25.1": {
       "type": "package",
       "serviceable": true,
@@ -973,12 +989,12 @@
       "path": "k4os.hash.xxhash/1.0.8",
       "hashPath": "k4os.hash.xxhash.1.0.8.nupkg.sha512"
     },
-    "log4net/2.0.15": {
+    "log4net/2.0.16": {
       "type": "package",
       "serviceable": true,
-      "sha512": "sha512-GahnO9ZgFka+xYcFwAfIFjW+k86P2nxFoaEpH6t3v4hiGj7tv2ksVZphxCVIHmJxoySS0HeU3dgCW+bSCcfD0A==",
-      "path": "log4net/2.0.15",
-      "hashPath": "log4net.2.0.15.nupkg.sha512"
+      "sha512": "sha512-6MoFh1BB83ZPiUHXlIJQZsoXSMlwnrNHmiPTGCobA6Ik3fmeNVLgEwF0MjxZtec2PfB0WdL81XCAtxjrummCCg==",
+      "path": "log4net/2.0.16",
+      "hashPath": "log4net.2.0.16.nupkg.sha512"
     },
     "Microsoft.CSharp/4.7.0": {
       "type": "package",

BIN
Release/net8.0/Apq.Web5.dll


BIN
Release/net8.0/Apq.Web5.pdb


+ 24 - 8
Release/net8.0/Apq.deps.json

@@ -10,6 +10,7 @@
         "dependencies": {
           "AntiXSS.NetStandard": "0.1.125",
           "ConsoleTables": "2.6.1",
+          "Fleck": "1.2.0",
           "GuerrillaNtp": "3.1.0",
           "Microsoft.Extensions.Configuration.EnvironmentVariables": "8.0.0",
           "Microsoft.Extensions.Configuration.Ini": "8.0.0",
@@ -26,7 +27,7 @@
           "System.Linq.Dynamic.Core": "1.3.10",
           "System.Reactive": "6.0.0",
           "UTF.Unknown": "2.5.1",
-          "log4net": "2.0.15"
+          "log4net": "2.0.16"
         },
         "runtime": {
           "Apq.dll": {}
@@ -89,6 +90,14 @@
           }
         }
       },
+      "Fleck/1.2.0": {
+        "runtime": {
+          "lib/netcoreapp2.0/Fleck.dll": {
+            "assemblyVersion": "1.2.0.0",
+            "fileVersion": "1.2.0.0"
+          }
+        }
+      },
       "Google.Protobuf/3.25.1": {
         "runtime": {
           "lib/net5.0/Google.Protobuf.dll": {
@@ -137,14 +146,14 @@
           }
         }
       },
-      "log4net/2.0.15": {
+      "log4net/2.0.16": {
         "dependencies": {
           "System.Configuration.ConfigurationManager": "6.0.0"
         },
         "runtime": {
           "lib/netstandard2.0/log4net.dll": {
-            "assemblyVersion": "2.0.15.0",
-            "fileVersion": "2.0.15.0"
+            "assemblyVersion": "2.0.16.0",
+            "fileVersion": "2.0.16.0"
           }
         }
       },
@@ -997,6 +1006,13 @@
       "path": "entityframework/6.4.4",
       "hashPath": "entityframework.6.4.4.nupkg.sha512"
     },
+    "Fleck/1.2.0": {
+      "type": "package",
+      "serviceable": true,
+      "sha512": "sha512-bPLXn6QbLAFoviur6XbrKB0Zn6x04E8VibHXyHZeJsoC7bkUl5DVtzM5cZgDuqHkIrBqAXJyTNJwSNIc6wBJ2Q==",
+      "path": "fleck/1.2.0",
+      "hashPath": "fleck.1.2.0.nupkg.sha512"
+    },
     "Google.Protobuf/3.25.1": {
       "type": "package",
       "serviceable": true,
@@ -1032,12 +1048,12 @@
       "path": "k4os.hash.xxhash/1.0.8",
       "hashPath": "k4os.hash.xxhash.1.0.8.nupkg.sha512"
     },
-    "log4net/2.0.15": {
+    "log4net/2.0.16": {
       "type": "package",
       "serviceable": true,
-      "sha512": "sha512-GahnO9ZgFka+xYcFwAfIFjW+k86P2nxFoaEpH6t3v4hiGj7tv2ksVZphxCVIHmJxoySS0HeU3dgCW+bSCcfD0A==",
-      "path": "log4net/2.0.15",
-      "hashPath": "log4net.2.0.15.nupkg.sha512"
+      "sha512": "sha512-6MoFh1BB83ZPiUHXlIJQZsoXSMlwnrNHmiPTGCobA6Ik3fmeNVLgEwF0MjxZtec2PfB0WdL81XCAtxjrummCCg==",
+      "path": "log4net/2.0.16",
+      "hashPath": "log4net.2.0.16.nupkg.sha512"
     },
     "Microsoft.CSharp/4.7.0": {
       "type": "package",

BIN
Release/net8.0/Apq.dll


BIN
Release/net8.0/Apq.pdb


+ 558 - 5
Release/net8.0/Apq.xml

@@ -3311,6 +3311,11 @@
             全局对象
             </summary>
         </member>
+        <member name="P:Apq.GlobalObject.TheAssembly">
+            <summary>
+            该程序集
+            </summary>
+        </member>
         <member name="P:Apq.GlobalObject.TheProcess">
             <summary>
             当前进程
@@ -3321,11 +3326,6 @@
             当前程序的入口目录。入口程序集(dll或exe)所在目录(以"\"结尾的绝对路径)
             </summary>
         </member>
-        <member name="P:Apq.GlobalObject.TheAssembly">
-            <summary>
-            该程序集
-            </summary>
-        </member>
         <member name="P:Apq.GlobalObject.DllFolder">
             <summary>
             本程序集(dll或exe)所在目录(以"\"结尾的绝对路径)
@@ -3341,6 +3341,11 @@
             Config目录(以"\"结尾)
             </summary>
         </member>
+        <member name="P:Apq.GlobalObject.LogFolder">
+            <summary>
+            日志目录(以"\"结尾)
+            </summary>
+        </member>
         <member name="P:Apq.GlobalObject.NamedInstances">
             <summary>
             命名实例集合
@@ -3476,6 +3481,66 @@
             </summary>
             <remarks>该方法不会产生异常</remarks>
         </member>
+        <member name="T:Apq.Net.FleckWebSocketServer">
+            <summary>
+            代表一个已连接到客户端的长连接(服务端)
+            </summary>
+            <remarks>WebSocket</remarks>
+        </member>
+        <member name="M:Apq.Net.FleckWebSocketServer.#ctor(Fleck.IWebSocketConnection)">
+            <summary>
+            代表一个已连接到客户端的长连接(服务端)
+            </summary>
+            <remarks>WebSocket</remarks>
+        </member>
+        <member name="P:Apq.Net.FleckWebSocketServer.WebSocket">
+            <summary>
+            WebSocket
+            </summary>
+        </member>
+        <member name="M:Apq.Net.FleckWebSocketServer.BindClient">
+            <summary>
+            设置Client相关事件的处理
+            </summary>
+        </member>
+        <member name="M:Apq.Net.FleckWebSocketServer.UnBindClient">
+            <summary>
+            取消Client相关事件的处理
+            </summary>
+        </member>
+        <member name="P:Apq.Net.FleckWebSocketServer.Connected">
+            <summary>
+            是否已连接
+            </summary>
+        </member>
+        <member name="P:Apq.Net.FleckWebSocketServer.ShouldClose">
+            <summary>
+            连接是否应该关闭(已空闲过久)
+            </summary>
+        </member>
+        <member name="M:Apq.Net.FleckWebSocketServer.DoTask_Close(System.String,System.Boolean)">
+            <summary>
+            关闭长连接(实现)
+            </summary>
+            <returns>是否关闭成功</returns>
+        </member>
+        <member name="M:Apq.Net.FleckWebSocketServer.DoSend(System.Collections.Generic.IList{System.Byte},System.Threading.CancellationToken)">
+            <summary>
+            发送数据到客户端(实现)
+            </summary>
+            <returns>是否发送成功</returns>
+        </member>
+        <member name="M:Apq.Net.FleckWebSocketServer.DoSend(System.String,System.Threading.CancellationToken)">
+            <summary>
+            发送消息到客户端(实现)
+            </summary>
+            <returns>是否发送成功</returns>
+        </member>
+        <member name="M:Apq.Net.FleckWebSocketServer.DoTask_HeartBeat(System.Threading.CancellationToken)">
+            <summary>
+            任务实现:心跳检测
+            </summary>
+        </member>
         <member name="T:Apq.Net.HttpClientHelper">
             <summary>
             使用HttpClient进行Http访问
@@ -3542,6 +3607,453 @@
             <param name="Min">最小值(含)</param>
             <param name="Max">最大值(含)</param>
         </member>
+        <!-- Badly formed XML comment ignored for member "T:Apq.Net.PersistentClient" -->
+        <!-- Badly formed XML comment ignored for member "M:Apq.Net.PersistentClient.#ctor(System.Object)" -->
+        <member name="P:Apq.Net.PersistentClient.Server">
+            <summary>
+            域名/IP/Url
+            </summary>
+        </member>
+        <member name="P:Apq.Net.PersistentClient.Port">
+            <summary>
+            端口
+            </summary>
+        </member>
+        <member name="P:Apq.Net.PersistentClient.SessionID">
+            <summary>
+            由服务端分配的会话ID(客户端标识)
+            </summary>
+        </member>
+        <member name="P:Apq.Net.PersistentClient.Client">
+            <summary>
+            客户端
+            </summary>
+        </member>
+        <member name="P:Apq.Net.PersistentClient.SrLock">
+            <summary>
+            数据收发锁,防止并发(即不能同时进行多个连接、发送或接收)
+            </summary>
+        </member>
+        <member name="P:Apq.Net.PersistentClient.CTS_Connect">
+            <summary>
+            任务的取消令牌:连接、接收、心跳、[发送]
+            </summary>
+        </member>
+        <member name="P:Apq.Net.PersistentClient.CTS_PreConnect">
+            <summary>
+            任务的取消令牌:上一次连接
+            </summary>
+        </member>
+        <member name="P:Apq.Net.PersistentClient.Provider_NewClient">
+            <summary>
+            提供:创建新连接实例的方法。重连时使用
+            </summary>
+        </member>
+        <member name="M:Apq.Net.PersistentClient.Init">
+            <summary>
+            对此实例进行初始化(绑定事件、启动任务等)
+            </summary>
+        </member>
+        <member name="M:Apq.Net.PersistentClient.Dispose(System.Boolean)">
+            <param name="disposing">指定释放类型{true:托管对象,false:未托管对象}</param>
+        </member>
+        <member name="M:Apq.Net.PersistentClient.BindClient">
+            <summary>
+            设置Client相关事件的处理
+            </summary>
+        </member>
+        <member name="M:Apq.Net.PersistentClient.UnBindClient">
+            <summary>
+            取消Client相关事件的处理
+            </summary>
+        </member>
+        <member name="P:Apq.Net.PersistentClient.Connected">
+            <summary>
+            是否已连接
+            </summary>
+        </member>
+        <member name="P:Apq.Net.PersistentClient.TryTimes">
+            <summary>
+            已尝试连接的次数
+            </summary>
+        </member>
+        <!-- Badly formed XML comment ignored for member "P:Apq.Net.PersistentClient.MaxTryTimes" -->
+        <member name="P:Apq.Net.PersistentClient.IsConnecting">
+            <summary>
+            是否正在连接(用于防止重复发起连接)
+            </summary>
+        </member>
+        <member name="P:Apq.Net.PersistentClient.LastConnectTime">
+            <summary>
+            最后发起连接的时间
+            </summary>
+        </member>
+        <member name="P:Apq.Net.PersistentClient.HadConnected">
+            <summary>
+            是否曾连接成功过
+            </summary>
+        </member>
+        <member name="M:Apq.Net.PersistentClient.Connect(System.Threading.CancellationToken)">
+            <summary>
+            连接到服务器(最多自动重连MaxTryTimes次)
+            </summary>
+            <returns>是否成功</returns>
+        </member>
+        <member name="M:Apq.Net.PersistentClient.TryConnect(System.Int32,System.Threading.CancellationToken)">
+            <summary>
+            连接到服务器(最多重连指定次数)
+            </summary>
+            <returns>是否成功</returns>
+        </member>
+        <member name="M:Apq.Net.PersistentClient.TryConnectOnce(System.Threading.CancellationToken)">
+            <summary>
+            尝试连接到服务器(一次)
+            </summary>
+            <returns>是否成功</returns>
+        </member>
+        <member name="M:Apq.Net.PersistentClient.DoTask_Connect(System.Threading.CancellationToken)">
+            <summary>
+            执行一次连接
+            </summary>
+            <returns>是否连接成功</returns>
+        </member>
+        <member name="E:Apq.Net.PersistentClient.AfterConnectTimeout">
+            <summary>
+            连接超时事件
+            </summary>
+        </member>
+        <member name="E:Apq.Net.PersistentClient.AfterConnectError">
+            <summary>
+            连接过程中发生异常时
+            </summary>
+        </member>
+        <member name="E:Apq.Net.PersistentClient.AfterConnected">
+            <summary>
+            连接成功事件
+            </summary>
+        </member>
+        <member name="M:Apq.Net.PersistentClient.OnAfterConnected">
+            <summary>
+            连接成功后的处理
+            </summary>
+        </member>
+        <member name="P:Apq.Net.PersistentClient.ShouldClose">
+            <summary>
+            连接是否应该关闭(已空闲过久)
+            </summary>
+        </member>
+        <member name="P:Apq.Net.PersistentClient.CloseReason">
+            <summary>
+            关闭原因(只接受第一次非空赋值)
+            </summary>
+        </member>
+        <member name="P:Apq.Net.PersistentClient.IsCloseByServer">
+            <summary>
+            是否是被服务端断开导致关闭的
+            </summary>
+        </member>
+        <member name="E:Apq.Net.PersistentClient.BeforeClose">
+            <summary>
+            连接关闭前
+            </summary>
+        </member>
+        <member name="E:Apq.Net.PersistentClient.AfterClose">
+            <summary>
+            连接关闭后
+            </summary>
+        </member>
+        <member name="M:Apq.Net.PersistentClient.Close(System.String,System.Boolean)">
+            <summary>
+            在新任务中关闭长连接
+            </summary>
+        </member>
+        <member name="M:Apq.Net.PersistentClient.DoTask_Close(System.String,System.Boolean)">
+            <summary>
+            任务实现:关闭长连接
+            </summary>
+            <returns>是否关闭成功</returns>
+            <remarks>基类实现了停止连接任务</remarks>
+        </member>
+        <member name="M:Apq.Net.PersistentClient.Send(System.Collections.Generic.IList{System.Byte},System.Threading.CancellationToken)">
+            <summary>
+            发送数据到服务端
+            </summary>
+            <returns>是否发送成功</returns>
+        </member>
+        <member name="M:Apq.Net.PersistentClient.DoSend(System.Collections.Generic.IList{System.Byte},System.Threading.CancellationToken)">
+            <summary>
+            发送数据到服务端(实现)
+            </summary>
+            <returns>是否发送成功</returns>
+        </member>
+        <member name="M:Apq.Net.PersistentClient.Send(System.String,System.Threading.CancellationToken)">
+            <summary>
+            发送消息到服务端
+            </summary>
+            <returns>是否发送成功</returns>
+        </member>
+        <member name="M:Apq.Net.PersistentClient.DoSend(System.String,System.Threading.CancellationToken)">
+            <summary>
+            发送消息到服务端(实现)
+            </summary>
+            <returns>是否发送成功</returns>
+        </member>
+        <member name="E:Apq.Net.PersistentClient.BeforeSend">
+            <summary>
+            发送前
+            </summary>
+        </member>
+        <member name="E:Apq.Net.PersistentClient.AfterSend">
+            <summary>
+            发送后
+            </summary>
+        </member>
+        <member name="E:Apq.Net.PersistentClient.BeforeSendMsg">
+            <summary>
+            发送前(文本)
+            </summary>
+        </member>
+        <member name="E:Apq.Net.PersistentClient.AfterSendMsg">
+            <summary>
+            发送后(文本)
+            </summary>
+        </member>
+        <member name="M:Apq.Net.PersistentClient.StartReceive(System.Threading.CancellationToken)">
+            <summary>
+            启动接收任务
+            </summary>
+        </member>
+        <member name="M:Apq.Net.PersistentClient.DoTask_Receive(System.Threading.CancellationToken)">
+            <summary>
+            任务实现:接收
+            </summary>
+        </member>
+        <member name="E:Apq.Net.PersistentClient.AfterReceiveMsg">
+            <summary>
+            接收到服务端发送的消息后
+            </summary>
+        </member>
+        <member name="E:Apq.Net.PersistentClient.AfterReceiveData">
+            <summary>
+            接收到服务端发送的数据后
+            </summary>
+        </member>
+        <member name="P:Apq.Net.PersistentClient.LastActiveTime">
+            <summary>
+            最后心跳时间
+            </summary>
+        </member>
+        <member name="P:Apq.Net.PersistentClient.Provider_HeartBeatMsg">
+            <summary>
+            提供心跳消息(返回不为空就发)
+            </summary>
+        </member>
+        <member name="P:Apq.Net.PersistentClient.Provider_HeartBeatData">
+            <summary>
+            提供心跳数据(返回不为空就发)
+            </summary>
+        </member>
+        <!-- Badly formed XML comment ignored for member "P:Apq.Net.PersistentClient.MaxTryTimesWhenInterrupted" -->
+        <member name="P:Apq.Net.PersistentClient.CTS_ReconnectWhenInterrupted">
+            <summary>
+            任务的取消令牌:断线重连
+            </summary>
+        </member>
+        <member name="M:Apq.Net.PersistentClient.StartHeartBeat(System.Threading.CancellationToken)">
+            <summary>
+            启动心跳任务
+            </summary>
+        </member>
+        <member name="M:Apq.Net.PersistentClient.DoTask_HeartBeat(System.Threading.CancellationToken)">
+            <summary>
+            任务实现:心跳检测
+            </summary>
+        </member>
+        <member name="E:Apq.Net.PersistentClient.AfterHeartBeatTimeout">
+            <summary>
+            心跳超时后
+            </summary>
+            <returns>是否取消心跳任务</returns>
+        </member>
+        <member name="M:Apq.Net.PersistentClient.OnAfterHeartBeatTimeout">
+            <summary>
+            心跳超时后的处理
+            </summary>
+            <returns>是否取消心跳任务</returns>
+        </member>
+        <member name="T:Apq.Net.PersistentServer">
+            <summary>
+            代表一个已连接到客户端的长连接(服务端)
+            </summary>
+            <param name="client">IWebSocketConnection或Socket</param>
+        </member>
+        <member name="M:Apq.Net.PersistentServer.#ctor(System.Object)">
+            <summary>
+            代表一个已连接到客户端的长连接(服务端)
+            </summary>
+            <param name="client">IWebSocketConnection或Socket</param>
+        </member>
+        <member name="P:Apq.Net.PersistentServer.SessionID">
+            <summary>
+            自动分配客户端标识(会话ID)
+            </summary>
+        </member>
+        <member name="P:Apq.Net.PersistentServer.Client">
+            <summary>
+            已接受的客户端(已连接)
+            </summary>
+        </member>
+        <member name="P:Apq.Net.PersistentServer.CTS_Work">
+            <summary>
+            任务的取消令牌:与连接关联的所有任务
+            </summary>
+        </member>
+        <member name="M:Apq.Net.PersistentServer.Init">
+            <summary>
+            对实例进行初始化
+            </summary>
+        </member>
+        <member name="M:Apq.Net.PersistentServer.Dispose(System.Boolean)">
+            <param name="disposing">指定释放类型{true:托管对象,false:未托管对象}</param>
+        </member>
+        <member name="M:Apq.Net.PersistentServer.BindClient">
+            <summary>
+            设置Client相关事件的处理
+            </summary>
+        </member>
+        <member name="M:Apq.Net.PersistentServer.UnBindClient">
+            <summary>
+            取消Client相关事件的处理
+            </summary>
+        </member>
+        <member name="P:Apq.Net.PersistentServer.ShouldAbandon">
+            <summary>
+            此连接是否应抛弃(不能再用了)
+            </summary>
+        </member>
+        <member name="P:Apq.Net.PersistentServer.Connected">
+            <summary>
+            是否已连接
+            </summary>
+        </member>
+        <member name="P:Apq.Net.PersistentServer.ShouldClose">
+            <summary>
+            连接是否应该关闭(已空闲过久)
+            </summary>
+        </member>
+        <member name="P:Apq.Net.PersistentServer.CloseReason">
+            <summary>
+            关闭原因(只接受第一次非空赋值)
+            </summary>
+        </member>
+        <member name="P:Apq.Net.PersistentServer.IsCloseByClient">
+            <summary>
+            是否是被客户端断开导致关闭的
+            </summary>
+        </member>
+        <member name="E:Apq.Net.PersistentServer.BeforeClose">
+            <summary>
+            连接关闭前
+            </summary>
+        </member>
+        <member name="E:Apq.Net.PersistentServer.AfterClose">
+            <summary>
+            连接关闭后
+            </summary>
+        </member>
+        <member name="M:Apq.Net.PersistentServer.Close(System.String,System.Boolean)">
+            <summary>
+            新任务中关闭长连接
+            </summary>
+        </member>
+        <member name="M:Apq.Net.PersistentServer.DoTask_Close(System.String,System.Boolean)">
+            <summary>
+            任务实现:关闭长连接
+            </summary>
+            <returns>是否关闭成功</returns>
+        </member>
+        <member name="M:Apq.Net.PersistentServer.Send(System.Collections.Generic.IList{System.Byte},System.Threading.CancellationToken)">
+            <summary>
+            发送数据到客户端
+            </summary>
+            <returns>是否发送成功</returns>
+        </member>
+        <member name="M:Apq.Net.PersistentServer.DoSend(System.Collections.Generic.IList{System.Byte},System.Threading.CancellationToken)">
+            <summary>
+            发送数据到客户端(实现)
+            </summary>
+            <returns>是否发送成功</returns>
+        </member>
+        <member name="M:Apq.Net.PersistentServer.Send(System.String,System.Threading.CancellationToken)">
+            <summary>
+            发送消息到客户端
+            </summary>
+            <returns>是否发送成功</returns>
+        </member>
+        <member name="M:Apq.Net.PersistentServer.DoSend(System.String,System.Threading.CancellationToken)">
+            <summary>
+            发送消息到客户端(实现)
+            </summary>
+            <returns>是否发送成功</returns>
+        </member>
+        <member name="E:Apq.Net.PersistentServer.BeforeSend">
+            <summary>
+            发送前
+            </summary>
+        </member>
+        <member name="E:Apq.Net.PersistentServer.AfterSend">
+            <summary>
+            发送后
+            </summary>
+        </member>
+        <member name="E:Apq.Net.PersistentServer.BeforeSendMsg">
+            <summary>
+            发送前(文本)
+            </summary>
+        </member>
+        <member name="E:Apq.Net.PersistentServer.AfterSendMsg">
+            <summary>
+            发送后(文本)
+            </summary>
+        </member>
+        <member name="E:Apq.Net.PersistentServer.AfterReceiveMsg">
+            <summary>
+            接收到客户端发送的消息后
+            </summary>
+        </member>
+        <member name="E:Apq.Net.PersistentServer.AfterReceiveData">
+            <summary>
+            接收到客户端发送的数据后
+            </summary>
+        </member>
+        <member name="P:Apq.Net.PersistentServer.LastActiveTime">
+            <summary>
+            最后心跳时间(由客户端发起)
+            </summary>
+        </member>
+        <member name="M:Apq.Net.PersistentServer.StartHeartBeat(System.Threading.CancellationToken)">
+            <summary>
+            启动心跳任务
+            </summary>
+        </member>
+        <member name="E:Apq.Net.PersistentServer.AfterHeartBeatTimeout">
+            <summary>
+            心跳超时后
+            </summary>
+            <returns>是否取消心跳任务</returns>
+        </member>
+        <member name="M:Apq.Net.PersistentServer.OnAfterHeartBeatTimeout">
+            <summary>
+            心跳超时后的处理
+            </summary>
+            <returns>是否取消心跳任务</returns>
+        </member>
+        <member name="M:Apq.Net.PersistentServer.DoTask_HeartBeat(System.Int32,System.Threading.CancellationToken)">
+            <summary>
+            任务实现:心跳检测
+            </summary>
+            <param name="interval">间隔(毫秒)</param>
+        </member>
         <member name="T:Apq.Net.PortEndPoint">
             <summary>
             端口端点
@@ -3591,6 +4103,47 @@
             参考来自 stackoverflow
             </summary>
         </member>
+        <!-- Badly formed XML comment ignored for member "T:Apq.Net.TcClient" -->
+        <!-- Badly formed XML comment ignored for member "M:Apq.Net.TcClient.#ctor(System.Net.Sockets.TcpClient)" -->
+        <member name="P:Apq.Net.TcClient.TcpClient">
+            <summary>
+            TcpClient
+            </summary>
+        </member>
+        <member name="P:Apq.Net.TcClient.Connected">
+            <summary>
+            是否已连接
+            </summary>
+        </member>
+        <member name="M:Apq.Net.TcClient.DoTask_Connect(System.Threading.CancellationToken)">
+            <summary>
+            执行一次连接
+            </summary>
+            <returns>是否连接成功</returns>
+        </member>
+        <member name="M:Apq.Net.TcClient.DoTask_Close(System.String,System.Boolean)">
+            <summary>
+            任务实现:关闭长连接
+            </summary>
+            <returns>是否关闭成功</returns>
+        </member>
+        <member name="M:Apq.Net.TcClient.DoSend(System.Collections.Generic.IList{System.Byte},System.Threading.CancellationToken)">
+            <summary>
+            发送数据到服务端(实现)
+            </summary>
+            <returns>是否发送成功</returns>
+        </member>
+        <member name="M:Apq.Net.TcClient.DoSend(System.String,System.Threading.CancellationToken)">
+            <summary>
+            发送消息到服务端
+            </summary>
+            <returns>是否发送成功</returns>
+        </member>
+        <member name="M:Apq.Net.TcClient.DoTask_Receive(System.Threading.CancellationToken)">
+            <summary>
+            任务实现:接收
+            </summary>
+        </member>
         <member name="M:Apq.Net.UrlHelper.GetUrlWithoutParams(System.String,System.Collections.Generic.IEnumerable{System.String})">
             <summary>
             获取不含参数的url

BIN
Wfj/Charge32/Apq.Web5.dll


BIN
Wfj/Charge32/Apq.Web5.pdb


BIN
Wfj/Charge32/Apq.dll


BIN
Wfj/Charge32/Apq.pdb


+ 84 - 28
Wfj/Charge32/Apq.xml

@@ -3609,6 +3609,16 @@
         </member>
         <!-- Badly formed XML comment ignored for member "T:Apq.Net.PersistentClient" -->
         <!-- Badly formed XML comment ignored for member "M:Apq.Net.PersistentClient.#ctor(System.Object)" -->
+        <member name="P:Apq.Net.PersistentClient.Server">
+            <summary>
+            域名/IP/Url
+            </summary>
+        </member>
+        <member name="P:Apq.Net.PersistentClient.Port">
+            <summary>
+            端口
+            </summary>
+        </member>
         <member name="P:Apq.Net.PersistentClient.SessionID">
             <summary>
             由服务端分配的会话ID(客户端标识)
@@ -3619,14 +3629,14 @@
             客户端
             </summary>
         </member>
-        <member name="P:Apq.Net.PersistentClient.CTS_Work">
+        <member name="P:Apq.Net.PersistentClient.SrLock">
             <summary>
-            任务的取消令牌:与连接关联的任务(接收、[发送]、心跳)
+            数据收发锁,防止并发(即不能同时进行多个连接、发送或接收)
             </summary>
         </member>
         <member name="P:Apq.Net.PersistentClient.CTS_Connect">
             <summary>
-            任务的取消令牌:连接
+            任务的取消令牌:连接、接收、心跳、[发送]
             </summary>
         </member>
         <member name="P:Apq.Net.PersistentClient.CTS_PreConnect">
@@ -3636,12 +3646,12 @@
         </member>
         <member name="P:Apq.Net.PersistentClient.Provider_NewClient">
             <summary>
-            提供:断线重连时创建新连接的方法
+            提供:创建新连接实例的方法。重连时使用
             </summary>
         </member>
         <member name="M:Apq.Net.PersistentClient.Init">
             <summary>
-            对实例进行初始化
+            对实例进行初始化(绑定事件、启动任务等)
             </summary>
         </member>
         <member name="M:Apq.Net.PersistentClient.Dispose(System.Boolean)">
@@ -3657,43 +3667,55 @@
             取消Client相关事件的处理
             </summary>
         </member>
+        <member name="P:Apq.Net.PersistentClient.Connected">
+            <summary>
+            是否已连接
+            </summary>
+        </member>
         <member name="P:Apq.Net.PersistentClient.TryTimes">
             <summary>
             已尝试连接的次数
             </summary>
         </member>
         <!-- Badly formed XML comment ignored for member "P:Apq.Net.PersistentClient.MaxTryTimes" -->
-        <!-- Badly formed XML comment ignored for member "P:Apq.Net.PersistentClient.MaxTryTimes_Runtime" -->
         <member name="P:Apq.Net.PersistentClient.IsConnecting">
             <summary>
             是否正在连接(用于防止重复发起连接)
             </summary>
         </member>
+        <member name="P:Apq.Net.PersistentClient.LastConnectTime">
+            <summary>
+            最后发起连接的时间
+            </summary>
+        </member>
         <member name="P:Apq.Net.PersistentClient.HadConnected">
             <summary>
             是否曾连接成功过
             </summary>
         </member>
-        <member name="P:Apq.Net.PersistentClient.Timeout">
+        <member name="M:Apq.Net.PersistentClient.Connect(System.Threading.CancellationToken)">
             <summary>
-            单次连接超时(秒)(国内网络环境,一般情况下3秒就够久了)
+            连接到服务器(最多自动重连MaxTryTimes次)
             </summary>
-            <remarks> 总超时时长 = Timeout_Connect * (MaxTryTimes + 1) </remarks>
+            <returns>是否成功</returns>
         </member>
-        <member name="M:Apq.Net.PersistentClient.Connect">
+        <member name="M:Apq.Net.PersistentClient.TryConnect(System.Int32,System.Threading.CancellationToken)">
             <summary>
-            手动连接到服务器(先自动将已连接次数归0)
+            连接到服务器(最多重连指定次数)
             </summary>
+            <returns>是否成功</returns>
         </member>
-        <member name="M:Apq.Net.PersistentClient.DoConnect(System.Int32)">
+        <member name="M:Apq.Net.PersistentClient.TryConnectOnce(System.Threading.CancellationToken)">
             <summary>
-            开启新一轮连接后取消之前的连接
+            尝试连接到服务器(一次)
             </summary>
+            <returns>是否成功</returns>
         </member>
-        <member name="M:Apq.Net.PersistentClient.DoTask_Connect(System.Int32,System.Threading.CancellationToken)">
+        <member name="M:Apq.Net.PersistentClient.DoTask_Connect(System.Threading.CancellationToken)">
             <summary>
-            等待delay毫秒后启动一次连接
+            执行一次连接
             </summary>
+            <returns>是否连接成功</returns>
         </member>
         <member name="E:Apq.Net.PersistentClient.AfterConnectTimeout">
             <summary>
@@ -3712,12 +3734,7 @@
         </member>
         <member name="M:Apq.Net.PersistentClient.OnAfterConnected">
             <summary>
-            连接成功后
-            </summary>
-        </member>
-        <member name="P:Apq.Net.PersistentClient.Connected">
-            <summary>
-            是否已连接
+            连接成功后的处理
             </summary>
         </member>
         <member name="P:Apq.Net.PersistentClient.ShouldClose">
@@ -3747,7 +3764,7 @@
         </member>
         <member name="M:Apq.Net.PersistentClient.Close(System.String,System.Boolean)">
             <summary>
-            新任务中关闭长连接
+            新任务中关闭长连接
             </summary>
         </member>
         <member name="M:Apq.Net.PersistentClient.DoTask_Close(System.String,System.Boolean)">
@@ -3755,6 +3772,7 @@
             任务实现:关闭长连接
             </summary>
             <returns>是否关闭成功</returns>
+            <remarks>基类实现了停止连接任务</remarks>
         </member>
         <member name="M:Apq.Net.PersistentClient.Send(System.Collections.Generic.IList{System.Byte},System.Threading.CancellationToken)">
             <summary>
@@ -3809,8 +3827,6 @@
             <summary>
             任务实现:接收
             </summary>
-            <param name="token"></param>
-            <returns></returns>
         </member>
         <member name="E:Apq.Net.PersistentClient.AfterReceiveMsg">
             <summary>
@@ -3838,9 +3854,9 @@
             </summary>
         </member>
         <!-- Badly formed XML comment ignored for member "P:Apq.Net.PersistentClient.MaxTryTimesWhenInterrupted" -->
-        <member name="P:Apq.Net.PersistentClient.SuspendWorkTask">
+        <member name="P:Apq.Net.PersistentClient.CTS_ReconnectWhenInterrupted">
             <summary>
-            是否暂停工作任务(接收、[发送]、心跳)
+            任务的取消令牌:断线重连
             </summary>
         </member>
         <member name="M:Apq.Net.PersistentClient.StartHeartBeat(System.Threading.CancellationToken)">
@@ -3848,11 +3864,10 @@
             启动心跳任务
             </summary>
         </member>
-        <member name="M:Apq.Net.PersistentClient.DoTask_HeartBeat(System.Int32,System.Threading.CancellationToken)">
+        <member name="M:Apq.Net.PersistentClient.DoTask_HeartBeat(System.Threading.CancellationToken)">
             <summary>
             任务实现:心跳检测
             </summary>
-            <param name="interval">间隔(毫秒)</param>
         </member>
         <member name="E:Apq.Net.PersistentClient.AfterHeartBeatTimeout">
             <summary>
@@ -4088,6 +4103,47 @@
             参考来自 stackoverflow
             </summary>
         </member>
+        <!-- Badly formed XML comment ignored for member "T:Apq.Net.TcClient" -->
+        <!-- Badly formed XML comment ignored for member "M:Apq.Net.TcClient.#ctor(System.Net.Sockets.TcpClient)" -->
+        <member name="P:Apq.Net.TcClient.TcpClient">
+            <summary>
+            TcpClient
+            </summary>
+        </member>
+        <member name="P:Apq.Net.TcClient.Connected">
+            <summary>
+            是否已连接
+            </summary>
+        </member>
+        <member name="M:Apq.Net.TcClient.DoTask_Connect(System.Threading.CancellationToken)">
+            <summary>
+            执行一次连接
+            </summary>
+            <returns>是否连接成功</returns>
+        </member>
+        <member name="M:Apq.Net.TcClient.DoTask_Close(System.String,System.Boolean)">
+            <summary>
+            任务实现:关闭长连接
+            </summary>
+            <returns>是否关闭成功</returns>
+        </member>
+        <member name="M:Apq.Net.TcClient.DoSend(System.Collections.Generic.IList{System.Byte},System.Threading.CancellationToken)">
+            <summary>
+            发送数据到服务端(实现)
+            </summary>
+            <returns>是否发送成功</returns>
+        </member>
+        <member name="M:Apq.Net.TcClient.DoSend(System.String,System.Threading.CancellationToken)">
+            <summary>
+            发送消息到服务端
+            </summary>
+            <returns>是否发送成功</returns>
+        </member>
+        <member name="M:Apq.Net.TcClient.DoTask_Receive(System.Threading.CancellationToken)">
+            <summary>
+            任务实现:接收
+            </summary>
+        </member>
         <member name="M:Apq.Net.UrlHelper.GetUrlWithoutParams(System.String,System.Collections.Generic.IEnumerable{System.String})">
             <summary>
             获取不含参数的url

BIN
Wfj/Charge32/CP.dll


BIN
Wfj/Charge32/CP.pdb


BIN
Wfj/Charge32/Charge32.dll


BIN
Wfj/Charge32/Charge32.pdb


+ 1 - 1
Wfj/Charge32/Charge32.xml

@@ -107,7 +107,7 @@
             <param name="ApiVersion">接口版本</param>
             <param name="ActorID">角色ID</param>
         </member>
-        <member name="M:Charge32.Controllers.GsController.SavePets_OnStage(System.String,System.Int64,System.Collections.Generic.IList{System.String})">
+        <member name="M:Charge32.Controllers.GsController.SavePets_OnStage(System.String,System.Int64,System.String)">
             <summary>
             保存出战的宠物列表
             </summary>

BIN
Wfj/Charge32/DB.DS32.dll


BIN
Wfj/Charge32/DB.DS32.pdb


BIN
Wfj/Charge32/DB.DSUser32.dll


BIN
Wfj/Charge32/DB.DSUser32.pdb


+ 3 - 3
Wfj/Charge32/DockerBuild.txt

@@ -17,9 +17,9 @@ cd DockerImg/charge32/
 docker login [email protected] registry.cn-guangzhou.aliyuncs.com
 
 # amd64上
-docker rmi registry.cn-guangzhou.aliyuncs.com/apq/charge32:amd64_20240318
-docker build -t registry.cn-guangzhou.aliyuncs.com/apq/charge32:amd64_20240318 .
-docker push registry.cn-guangzhou.aliyuncs.com/apq/charge32:amd64_20240318
+docker rmi registry.cn-guangzhou.aliyuncs.com/apq/charge32:amd64_20240319
+docker build -t registry.cn-guangzhou.aliyuncs.com/apq/charge32:amd64_20240319 .
+docker push registry.cn-guangzhou.aliyuncs.com/apq/charge32:amd64_20240319
 
 # arm64上
 docker rmi registry.cn-guangzhou.aliyuncs.com/apq/charge32:arm64

BIN
Wfj/Charge32/OpenQQ.dll


BIN
Wfj/Charge32/OpenQQ.pdb