From 59f562c38e60157b1361394f6cbfe1cc05a9e271 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E8=8B=A5=E6=B1=9D=E6=A3=8B=E8=8C=97?= <505554090@qq.com>
Date: Fri, 13 Aug 2021 21:41:12 +0800
Subject: [PATCH] =?UTF-8?q?V5.5.0=E6=AD=A3=E5=BC=8F=E7=89=88?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.gitignore | 341 +++++
LICENSE | 201 +++
README.md | 397 ++++++
RRQMSocket.FileTransfer/Common/FileBlock.cs | 40 +
.../Common/FileHashGenerator.cs | 80 ++
.../Common/FileStreamPool.cs | 250 ++++
.../FileTransferErrorExceptionMapping.cs | 28 +
.../Common/FileWaitResult.cs | 20 +
.../Common/PBCollectionTemp.cs | 64 +
.../Common/ProgressBlockCollection.cs | 106 ++
RRQMSocket.FileTransfer/Common/RRQMStream.cs | 157 +++
.../Common/ReadOnlyList.cs | 93 ++
RRQMSocket.FileTransfer/Common/Speed.cs | 22 +
.../Common/TransferCollection.cs | 92 ++
.../Common/TransferFileHashDictionary.cs | 203 +++
RRQMSocket.FileTransfer/Common/UrlFileInfo.cs | 166 +++
.../Config/FileClientConfig.cs | 85 ++
.../Config/FileServiceConfig.cs | 59 +
.../Delegate/DelegateCollection.cs | 28 +
RRQMSocket.FileTransfer/Enum/FileHashType.cs | 39 +
RRQMSocket.FileTransfer/Enum/RequestStatus.cs | 34 +
.../Enum/StreamOperationType.cs | 29 +
RRQMSocket.FileTransfer/Enum/TransferFlags.cs | 37 +
.../Enum/TransferStatus.cs | 44 +
RRQMSocket.FileTransfer/Enum/TransferType.cs | 30 +
.../EventArgs/FileEventArgs.cs | 26 +
.../EventArgs/FileOperationEventArgs.cs | 24 +
.../EventArgs/TransferFileMessageArgs.cs | 29 +
.../Exceptions/RRQMTransferErrorException.cs | 48 +
.../Exceptions/RRQMTransferingException.cs | 52 +
.../Interface/IFileClient.cs | 40 +
.../Interface/IFileService.cs | 30 +
RRQMSocket.FileTransfer/LICENSE | 201 +++
RRQMSocket.FileTransfer/RRQM.ico | Bin 0 -> 249918 bytes
RRQMSocket.FileTransfer/RRQM.png | Bin 0 -> 87638 bytes
.../RRQMSocket.FileTransfer.csproj | 77 ++
RRQMSocket.FileTransfer/Socket/FileClient.cs | 1030 ++++++++++++++
RRQMSocket.FileTransfer/Socket/FileService.cs | 133 ++
.../Socket/FileSocketClient.cs | 692 ++++++++++
RRQMSocket.Http/Common/HttpBase.cs | 258 ++++
RRQMSocket.Http/Common/HttpRequest.cs | 222 +++
RRQMSocket.Http/Common/HttpResponse.cs | 123 ++
.../DataAdapter/HttpDataHandlingAdapter.cs | 185 +++
RRQMSocket.Http/Enum/HttpHeaders.cs | 327 +++++
RRQMSocket.Http/Enum/HttpType.cs | 30 +
RRQMSocket.Http/Helper/EnumHelper.cs | 72 +
RRQMSocket.Http/Helper/RequestHelper.cs | 58 +
RRQMSocket.Http/Helper/ResponseHelper.cs | 100 ++
RRQMSocket.Http/LICENSE | 201 +++
RRQMSocket.Http/RRQM.ico | Bin 0 -> 249918 bytes
RRQMSocket.Http/RRQM.png | Bin 0 -> 87638 bytes
RRQMSocket.Http/RRQMSocket.Http.csproj | 70 +
.../Attribute/JsonRpcAttribute.cs | 43 +
RRQMSocket.RPC.JsonRpc/Common/ActionMap.cs | 70 +
.../Common/JsonRequestContext.cs | 31 +
.../Common/JsonResponseContext.cs | 40 +
.../Common/JsonRpcWaitContext.cs | 22 +
.../Config/JsonRpcClientConfig.cs | 54 +
.../Config/JsonRpcParserConfig.cs | 55 +
.../Enum/JsonRpcProtocolType.cs | 29 +
.../Interface/IJsonRpcClient.cs | 22 +
RRQMSocket.RPC.JsonRpc/LICENSE | 201 +++
RRQMSocket.RPC.JsonRpc/RRQM.ico | Bin 0 -> 249918 bytes
RRQMSocket.RPC.JsonRpc/RRQM.png | Bin 0 -> 87638 bytes
.../RRQMSocket.RPC.JsonRpc.csproj | 71 +
.../Socket/JsonRpcClient.cs | 382 ++++++
.../Socket/JsonRpcParser.cs | 424 ++++++
.../Socket/JsonRpcSocketClient.cs | 29 +
.../Attribute/RouteAttribute.cs | 43 +
RRQMSocket.RPC.WebApi/Common/ActionResult.cs | 30 +
.../Common/ControllerBase.cs | 21 +
RRQMSocket.RPC.WebApi/Common/RouteMap.cs | 70 +
.../Config/WebApiParserConfig.cs | 53 +
.../Converter/ApiDataConverter.cs | 37 +
.../Converter/JsonDataConverter.cs | 128 ++
.../Converter/XmlDataConverter.cs | 129 ++
RRQMSocket.RPC.WebApi/LICENSE | 201 +++
RRQMSocket.RPC.WebApi/RRQM.ico | Bin 0 -> 249918 bytes
RRQMSocket.RPC.WebApi/RRQM.png | Bin 0 -> 87638 bytes
.../RRQMSocket.RPC.WebApi.csproj | 70 +
RRQMSocket.RPC.WebApi/Socket/WebApiParser.cs | 280 ++++
.../Socket/WebApiSocketClient.cs | 29 +
.../Attribute/XmlRpcAttribute.cs | 43 +
RRQMSocket.RPC.XmlRpc/Common/ActionMap.cs | 70 +
RRQMSocket.RPC.XmlRpc/Common/XmlDataTool.cs | 270 ++++
.../Config/XmlRpcClientConfig.cs | 54 +
.../Config/XmlRpcParserConfig.cs | 38 +
RRQMSocket.RPC.XmlRpc/LICENSE | 201 +++
RRQMSocket.RPC.XmlRpc/RRQM.ico | Bin 0 -> 249918 bytes
RRQMSocket.RPC.XmlRpc/RRQM.png | Bin 0 -> 87638 bytes
.../RRQMSocket.RPC.XmlRpc.csproj | 70 +
RRQMSocket.RPC.XmlRpc/Socket/XmlRpcClient.cs | 188 +++
RRQMSocket.RPC.XmlRpc/Socket/XmlRpcParser.cs | 234 ++++
.../Socket/XmlRpcSocketClient.cs | 29 +
RRQMSocket.RPC/Delegete.cs | 23 +
.../Global/Attribute/RPCAttribute.cs | 22 +
RRQMSocket.RPC/Global/Commond/InvokeStatus.cs | 55 +
.../Global/Commond/MethodInstance.cs | 77 ++
.../Global/Commond/MethodInvoker.cs | 50 +
RRQMSocket.RPC/Global/Commond/MethodMap.cs | 81 ++
.../Global/Commond/RPCParserCollection.cs | 79 ++
.../Global/Commond/ReadOnlyDictionary.cs | 85 ++
RRQMSocket.RPC/Global/Commond/ReadOnlyList.cs | 92 ++
.../Global/Commond/ServerProvider.cs | 62 +
.../Commond/ServerProviderCollection.cs | 74 +
.../Exceptions/RRQMAbandonRPCException.cs | 52 +
.../Global/Exceptions/RRQMRPCException.cs | 52 +
.../Exceptions/RRQMRPCInvokeException.cs | 48 +
.../Global/Interface/IServerProvider.cs | 55 +
RRQMSocket.RPC/Global/Parser/IRPCParser.cs | 75 +
RRQMSocket.RPC/Global/Service/RPCService.cs | 336 +++++
RRQMSocket.RPC/LICENSE | 201 +++
RRQMSocket.RPC/RRQM.ico | Bin 0 -> 249918 bytes
RRQMSocket.RPC/RRQM.png | Bin 0 -> 87638 bytes
.../RRQMRPC/Attribute/RRQMRPCAttribute.cs | 42 +
.../RRQMRPCCallBackMethodAttribute.cs | 36 +
.../Attribute/RRQMRPCMemberAttribute.cs | 23 +
RRQMSocket.RPC/RRQMRPC/Common/CellCode.cs | 36 +
.../RRQMRPC/Common/CodeGenerator.cs | 502 +++++++
RRQMSocket.RPC/RRQMRPC/Common/CodeType.cs | 31 +
RRQMSocket.RPC/RRQMRPC/Common/FeedbackType.cs | 35 +
RRQMSocket.RPC/RRQMRPC/Common/InvokeOption.cs | 77 ++
RRQMSocket.RPC/RRQMRPC/Common/MethodItem.cs | 40 +
RRQMSocket.RPC/RRQMRPC/Common/MethodStore.cs | 88 ++
.../RRQMRPC/Common/PropertyCodeGenerator.cs | 324 +++++
RRQMSocket.RPC/RRQMRPC/Common/RpcCompiler.cs | 103 ++
RRQMSocket.RPC/RRQMRPC/Common/RpcContext.cs | 74 +
RRQMSocket.RPC/RRQMRPC/Common/RpcProxyInfo.cs | 42 +
RRQMSocket.RPC/RRQMRPC/Common/Tools.cs | 240 ++++
.../RRQMRPC/Config/TcpRpcClientConfig.cs | 51 +
.../RRQMRPC/Config/TcpRpcParserConfig.cs | 82 ++
.../RRQMRPC/Config/UdpRpcClientConfig.cs | 51 +
.../RRQMRPC/Config/UdpRpcParserConfig.cs | 82 ++
.../RRQMRPC/Exceptions/RRQMRPCKeyException.cs | 47 +
.../Exceptions/RRQMRPCNoRegisterException.cs | 47 +
.../Exceptions/RRQMSerializationException.cs | 47 +
.../RRQMRPC/Interface/IRRQMRpcClient.cs | 62 +
.../RRQMRPC/Interface/IRRQMRpcParser.cs | 97 ++
.../RRQMRPC/Interface/IRpcClient.cs | 74 +
.../Serialization/BinarySerializeConverter.cs | 44 +
.../Serialization/JsonSerializeConverter.cs | 55 +
.../Serialization/SerializeConverter.cs | 36 +
.../Serialization/XmlSerializeConverter.cs | 44 +
.../RRQMRPC/Socket/RpcSocketClient .cs | 474 +++++++
RRQMSocket.RPC/RRQMRPC/Socket/TcpParser.cs | 374 +++++
RRQMSocket.RPC/RRQMRPC/Socket/TcpRpcClient.cs | 1201 +++++++++++++++++
RRQMSocket.RPC/RRQMRPC/Socket/TcpRpcParser.cs | 21 +
RRQMSocket.RPC/RRQMRPC/Socket/UdpRpcClient.cs | 712 ++++++++++
RRQMSocket.RPC/RRQMRPC/Socket/UdpRpcParser.cs | 382 ++++++
RRQMSocket.RPC/RRQMSocket.RPC.csproj | 72 +
RRQMSocket.sln | 61 +
RRQMSocket/BaseSocket.cs | 59 +
RRQMSocket/ClassDiagram.cd | 516 +++++++
RRQMSocket/Common/AsyncByte.cs | 23 +
RRQMSocket/Common/AsyncResult.cs | 29 +
RRQMSocket/Common/AsyncSender.cs | 199 +++
RRQMSocket/Common/CreateOption.cs | 31 +
RRQMSocket/Common/IPHost.cs | 96 ++
RRQMSocket/Common/ProcotolHelper.cs | 200 +++
RRQMSocket/Config/ClientConfig.cs | 20 +
RRQMSocket/Config/ProtocolClientConfig.cs | 21 +
RRQMSocket/Config/ProtocolServiceConfig.cs | 36 +
RRQMSocket/Config/RRQMConfig.cs | 84 ++
RRQMSocket/Config/ServiceConfig.cs | 82 ++
RRQMSocket/Config/TcpClientConfig.cs | 130 ++
RRQMSocket/Config/TcpServiceConfig.cs | 83 ++
RRQMSocket/Config/TokenClientConfig.cs | 57 +
RRQMSocket/Config/TokenServiceConfig.cs | 57 +
RRQMSocket/Config/UdpSessionConfig.cs | 52 +
RRQMSocket/DataAdapter/DataAdapterTester.cs | 201 +++
RRQMSocket/DataAdapter/DataHandlingAdapter.cs | 97 ++
.../FixedHeaderDataHandlingAdapter.cs | 279 ++++
.../FixedSizeDataHandlingAdapter.cs | 159 +++
.../JsonStringDataHandlingAdapter.cs | 135 ++
.../DataAdapter/NormalDataHandlingAdapter.cs | 42 +
.../TerminatorDataHandlingAdapter.cs | 220 +++
RRQMSocket/DelegateCollection.cs | 49 +
RRQMSocket/Enum/ClearType.cs | 32 +
RRQMSocket/Enum/FixedHeaderType.cs | 35 +
RRQMSocket/Enum/ServerState.cs | 39 +
RRQMSocket/EventArgs/BytesEventArgs.cs | 35 +
RRQMSocket/EventArgs/MesEventArgs.cs | 42 +
RRQMSocket/EventArgs/ReturnBytesEventArgs.cs | 32 +
.../Exceptions/RRQMNotConnectedException.cs | 52 +
.../Exceptions/RRQMOverlengthException.cs | 47 +
RRQMSocket/Exceptions/RRQMTimeoutException.cs | 48 +
.../Exceptions/RRQMTokenVerifyException.cs | 47 +
RRQMSocket/Interface/IClient.cs | 108 ++
RRQMSocket/Interface/IHandleBuffer.cs | 28 +
RRQMSocket/Interface/IService.cs | 71 +
RRQMSocket/Interface/ISocket.cs | 32 +
RRQMSocket/Interface/ISocketClient.cs | 34 +
RRQMSocket/Interface/ITcpClient.cs | 42 +
RRQMSocket/Interface/ITcpService.cs | 134 ++
RRQMSocket/Interface/IUserClient.cs | 42 +
RRQMSocket/Interface/IUserTcpClient.cs | 35 +
RRQMSocket/Interface/_ITcpService.cs | 27 +
RRQMSocket/InternalClass/BufferQueue.cs | 38 +
RRQMSocket/InternalClass/BufferQueueGroup.cs | 41 +
RRQMSocket/InternalClass/ClientBuffer.cs | 26 +
.../InternalClass/SocketCliectCollection.cs | 113 ++
RRQMSocket/LICENSE | 201 +++
RRQMSocket/Logger/Log.cs | 45 +
RRQMSocket/ParameterClass/VerifyOption.cs | 40 +
RRQMSocket/Pool/Interface/IClientGroup.cs | 21 +
RRQMSocket/Pool/Interface/IConnectionPool.cs | 91 ++
RRQMSocket/Pool/TcpConnectionPool.cs | 248 ++++
RRQMSocket/RRQM.ico | Bin 0 -> 249918 bytes
RRQMSocket/RRQM.png | Bin 0 -> 87638 bytes
RRQMSocket/RRQMSocket.csproj | 88 ++
RRQMSocket/TCP/Client/ProtocolClient.cs | 325 +++++
RRQMSocket/TCP/Client/SimpleProtocolClient.cs | 37 +
RRQMSocket/TCP/Client/SimpleTcpClient.cs | 47 +
RRQMSocket/TCP/Client/SimpleTokenClient.cs | 37 +
RRQMSocket/TCP/Client/TcpClient.cs | 636 +++++++++
RRQMSocket/TCP/Client/TokenClient.cs | 163 +++
RRQMSocket/TCP/Service/ProtocolService.cs | 56 +
.../TCP/Service/SimpleProtocolService.cs | 54 +
RRQMSocket/TCP/Service/SimpleTcpService.cs | 57 +
RRQMSocket/TCP/Service/SimpleTokenService.cs | 57 +
RRQMSocket/TCP/Service/TcpService.cs | 655 +++++++++
RRQMSocket/TCP/Service/TokenService.cs | 173 +++
.../TCP/SocketClient/ProtocolSocketClient.cs | 270 ++++
.../SimpleProtocolSocketClient.cs | 37 +
.../TCP/SocketClient/SimpleSocketClient.cs | 37 +
RRQMSocket/TCP/SocketClient/SocketClient.cs | 545 ++++++++
RRQMSocket/UDP/SimpleUdpSession.cs | 37 +
RRQMSocket/UDP/UdpSession.cs | 496 +++++++
228 files changed, 26352 insertions(+)
create mode 100644 .gitignore
create mode 100644 LICENSE
create mode 100644 README.md
create mode 100644 RRQMSocket.FileTransfer/Common/FileBlock.cs
create mode 100644 RRQMSocket.FileTransfer/Common/FileHashGenerator.cs
create mode 100644 RRQMSocket.FileTransfer/Common/FileStreamPool.cs
create mode 100644 RRQMSocket.FileTransfer/Common/FileTransferErrorExceptionMapping.cs
create mode 100644 RRQMSocket.FileTransfer/Common/FileWaitResult.cs
create mode 100644 RRQMSocket.FileTransfer/Common/PBCollectionTemp.cs
create mode 100644 RRQMSocket.FileTransfer/Common/ProgressBlockCollection.cs
create mode 100644 RRQMSocket.FileTransfer/Common/RRQMStream.cs
create mode 100644 RRQMSocket.FileTransfer/Common/ReadOnlyList.cs
create mode 100644 RRQMSocket.FileTransfer/Common/Speed.cs
create mode 100644 RRQMSocket.FileTransfer/Common/TransferCollection.cs
create mode 100644 RRQMSocket.FileTransfer/Common/TransferFileHashDictionary.cs
create mode 100644 RRQMSocket.FileTransfer/Common/UrlFileInfo.cs
create mode 100644 RRQMSocket.FileTransfer/Config/FileClientConfig.cs
create mode 100644 RRQMSocket.FileTransfer/Config/FileServiceConfig.cs
create mode 100644 RRQMSocket.FileTransfer/Delegate/DelegateCollection.cs
create mode 100644 RRQMSocket.FileTransfer/Enum/FileHashType.cs
create mode 100644 RRQMSocket.FileTransfer/Enum/RequestStatus.cs
create mode 100644 RRQMSocket.FileTransfer/Enum/StreamOperationType.cs
create mode 100644 RRQMSocket.FileTransfer/Enum/TransferFlags.cs
create mode 100644 RRQMSocket.FileTransfer/Enum/TransferStatus.cs
create mode 100644 RRQMSocket.FileTransfer/Enum/TransferType.cs
create mode 100644 RRQMSocket.FileTransfer/EventArgs/FileEventArgs.cs
create mode 100644 RRQMSocket.FileTransfer/EventArgs/FileOperationEventArgs.cs
create mode 100644 RRQMSocket.FileTransfer/EventArgs/TransferFileMessageArgs.cs
create mode 100644 RRQMSocket.FileTransfer/Exceptions/RRQMTransferErrorException.cs
create mode 100644 RRQMSocket.FileTransfer/Exceptions/RRQMTransferingException.cs
create mode 100644 RRQMSocket.FileTransfer/Interface/IFileClient.cs
create mode 100644 RRQMSocket.FileTransfer/Interface/IFileService.cs
create mode 100644 RRQMSocket.FileTransfer/LICENSE
create mode 100644 RRQMSocket.FileTransfer/RRQM.ico
create mode 100644 RRQMSocket.FileTransfer/RRQM.png
create mode 100644 RRQMSocket.FileTransfer/RRQMSocket.FileTransfer.csproj
create mode 100644 RRQMSocket.FileTransfer/Socket/FileClient.cs
create mode 100644 RRQMSocket.FileTransfer/Socket/FileService.cs
create mode 100644 RRQMSocket.FileTransfer/Socket/FileSocketClient.cs
create mode 100644 RRQMSocket.Http/Common/HttpBase.cs
create mode 100644 RRQMSocket.Http/Common/HttpRequest.cs
create mode 100644 RRQMSocket.Http/Common/HttpResponse.cs
create mode 100644 RRQMSocket.Http/DataAdapter/HttpDataHandlingAdapter.cs
create mode 100644 RRQMSocket.Http/Enum/HttpHeaders.cs
create mode 100644 RRQMSocket.Http/Enum/HttpType.cs
create mode 100644 RRQMSocket.Http/Helper/EnumHelper.cs
create mode 100644 RRQMSocket.Http/Helper/RequestHelper.cs
create mode 100644 RRQMSocket.Http/Helper/ResponseHelper.cs
create mode 100644 RRQMSocket.Http/LICENSE
create mode 100644 RRQMSocket.Http/RRQM.ico
create mode 100644 RRQMSocket.Http/RRQM.png
create mode 100644 RRQMSocket.Http/RRQMSocket.Http.csproj
create mode 100644 RRQMSocket.RPC.JsonRpc/Attribute/JsonRpcAttribute.cs
create mode 100644 RRQMSocket.RPC.JsonRpc/Common/ActionMap.cs
create mode 100644 RRQMSocket.RPC.JsonRpc/Common/JsonRequestContext.cs
create mode 100644 RRQMSocket.RPC.JsonRpc/Common/JsonResponseContext.cs
create mode 100644 RRQMSocket.RPC.JsonRpc/Common/JsonRpcWaitContext.cs
create mode 100644 RRQMSocket.RPC.JsonRpc/Config/JsonRpcClientConfig.cs
create mode 100644 RRQMSocket.RPC.JsonRpc/Config/JsonRpcParserConfig.cs
create mode 100644 RRQMSocket.RPC.JsonRpc/Enum/JsonRpcProtocolType.cs
create mode 100644 RRQMSocket.RPC.JsonRpc/Interface/IJsonRpcClient.cs
create mode 100644 RRQMSocket.RPC.JsonRpc/LICENSE
create mode 100644 RRQMSocket.RPC.JsonRpc/RRQM.ico
create mode 100644 RRQMSocket.RPC.JsonRpc/RRQM.png
create mode 100644 RRQMSocket.RPC.JsonRpc/RRQMSocket.RPC.JsonRpc.csproj
create mode 100644 RRQMSocket.RPC.JsonRpc/Socket/JsonRpcClient.cs
create mode 100644 RRQMSocket.RPC.JsonRpc/Socket/JsonRpcParser.cs
create mode 100644 RRQMSocket.RPC.JsonRpc/Socket/JsonRpcSocketClient.cs
create mode 100644 RRQMSocket.RPC.WebApi/Attribute/RouteAttribute.cs
create mode 100644 RRQMSocket.RPC.WebApi/Common/ActionResult.cs
create mode 100644 RRQMSocket.RPC.WebApi/Common/ControllerBase.cs
create mode 100644 RRQMSocket.RPC.WebApi/Common/RouteMap.cs
create mode 100644 RRQMSocket.RPC.WebApi/Config/WebApiParserConfig.cs
create mode 100644 RRQMSocket.RPC.WebApi/Converter/ApiDataConverter.cs
create mode 100644 RRQMSocket.RPC.WebApi/Converter/JsonDataConverter.cs
create mode 100644 RRQMSocket.RPC.WebApi/Converter/XmlDataConverter.cs
create mode 100644 RRQMSocket.RPC.WebApi/LICENSE
create mode 100644 RRQMSocket.RPC.WebApi/RRQM.ico
create mode 100644 RRQMSocket.RPC.WebApi/RRQM.png
create mode 100644 RRQMSocket.RPC.WebApi/RRQMSocket.RPC.WebApi.csproj
create mode 100644 RRQMSocket.RPC.WebApi/Socket/WebApiParser.cs
create mode 100644 RRQMSocket.RPC.WebApi/Socket/WebApiSocketClient.cs
create mode 100644 RRQMSocket.RPC.XmlRpc/Attribute/XmlRpcAttribute.cs
create mode 100644 RRQMSocket.RPC.XmlRpc/Common/ActionMap.cs
create mode 100644 RRQMSocket.RPC.XmlRpc/Common/XmlDataTool.cs
create mode 100644 RRQMSocket.RPC.XmlRpc/Config/XmlRpcClientConfig.cs
create mode 100644 RRQMSocket.RPC.XmlRpc/Config/XmlRpcParserConfig.cs
create mode 100644 RRQMSocket.RPC.XmlRpc/LICENSE
create mode 100644 RRQMSocket.RPC.XmlRpc/RRQM.ico
create mode 100644 RRQMSocket.RPC.XmlRpc/RRQM.png
create mode 100644 RRQMSocket.RPC.XmlRpc/RRQMSocket.RPC.XmlRpc.csproj
create mode 100644 RRQMSocket.RPC.XmlRpc/Socket/XmlRpcClient.cs
create mode 100644 RRQMSocket.RPC.XmlRpc/Socket/XmlRpcParser.cs
create mode 100644 RRQMSocket.RPC.XmlRpc/Socket/XmlRpcSocketClient.cs
create mode 100644 RRQMSocket.RPC/Delegete.cs
create mode 100644 RRQMSocket.RPC/Global/Attribute/RPCAttribute.cs
create mode 100644 RRQMSocket.RPC/Global/Commond/InvokeStatus.cs
create mode 100644 RRQMSocket.RPC/Global/Commond/MethodInstance.cs
create mode 100644 RRQMSocket.RPC/Global/Commond/MethodInvoker.cs
create mode 100644 RRQMSocket.RPC/Global/Commond/MethodMap.cs
create mode 100644 RRQMSocket.RPC/Global/Commond/RPCParserCollection.cs
create mode 100644 RRQMSocket.RPC/Global/Commond/ReadOnlyDictionary.cs
create mode 100644 RRQMSocket.RPC/Global/Commond/ReadOnlyList.cs
create mode 100644 RRQMSocket.RPC/Global/Commond/ServerProvider.cs
create mode 100644 RRQMSocket.RPC/Global/Commond/ServerProviderCollection.cs
create mode 100644 RRQMSocket.RPC/Global/Exceptions/RRQMAbandonRPCException.cs
create mode 100644 RRQMSocket.RPC/Global/Exceptions/RRQMRPCException.cs
create mode 100644 RRQMSocket.RPC/Global/Exceptions/RRQMRPCInvokeException.cs
create mode 100644 RRQMSocket.RPC/Global/Interface/IServerProvider.cs
create mode 100644 RRQMSocket.RPC/Global/Parser/IRPCParser.cs
create mode 100644 RRQMSocket.RPC/Global/Service/RPCService.cs
create mode 100644 RRQMSocket.RPC/LICENSE
create mode 100644 RRQMSocket.RPC/RRQM.ico
create mode 100644 RRQMSocket.RPC/RRQM.png
create mode 100644 RRQMSocket.RPC/RRQMRPC/Attribute/RRQMRPCAttribute.cs
create mode 100644 RRQMSocket.RPC/RRQMRPC/Attribute/RRQMRPCCallBackMethodAttribute.cs
create mode 100644 RRQMSocket.RPC/RRQMRPC/Attribute/RRQMRPCMemberAttribute.cs
create mode 100644 RRQMSocket.RPC/RRQMRPC/Common/CellCode.cs
create mode 100644 RRQMSocket.RPC/RRQMRPC/Common/CodeGenerator.cs
create mode 100644 RRQMSocket.RPC/RRQMRPC/Common/CodeType.cs
create mode 100644 RRQMSocket.RPC/RRQMRPC/Common/FeedbackType.cs
create mode 100644 RRQMSocket.RPC/RRQMRPC/Common/InvokeOption.cs
create mode 100644 RRQMSocket.RPC/RRQMRPC/Common/MethodItem.cs
create mode 100644 RRQMSocket.RPC/RRQMRPC/Common/MethodStore.cs
create mode 100644 RRQMSocket.RPC/RRQMRPC/Common/PropertyCodeGenerator.cs
create mode 100644 RRQMSocket.RPC/RRQMRPC/Common/RpcCompiler.cs
create mode 100644 RRQMSocket.RPC/RRQMRPC/Common/RpcContext.cs
create mode 100644 RRQMSocket.RPC/RRQMRPC/Common/RpcProxyInfo.cs
create mode 100644 RRQMSocket.RPC/RRQMRPC/Common/Tools.cs
create mode 100644 RRQMSocket.RPC/RRQMRPC/Config/TcpRpcClientConfig.cs
create mode 100644 RRQMSocket.RPC/RRQMRPC/Config/TcpRpcParserConfig.cs
create mode 100644 RRQMSocket.RPC/RRQMRPC/Config/UdpRpcClientConfig.cs
create mode 100644 RRQMSocket.RPC/RRQMRPC/Config/UdpRpcParserConfig.cs
create mode 100644 RRQMSocket.RPC/RRQMRPC/Exceptions/RRQMRPCKeyException.cs
create mode 100644 RRQMSocket.RPC/RRQMRPC/Exceptions/RRQMRPCNoRegisterException.cs
create mode 100644 RRQMSocket.RPC/RRQMRPC/Exceptions/RRQMSerializationException.cs
create mode 100644 RRQMSocket.RPC/RRQMRPC/Interface/IRRQMRpcClient.cs
create mode 100644 RRQMSocket.RPC/RRQMRPC/Interface/IRRQMRpcParser.cs
create mode 100644 RRQMSocket.RPC/RRQMRPC/Interface/IRpcClient.cs
create mode 100644 RRQMSocket.RPC/RRQMRPC/Serialization/BinarySerializeConverter.cs
create mode 100644 RRQMSocket.RPC/RRQMRPC/Serialization/JsonSerializeConverter.cs
create mode 100644 RRQMSocket.RPC/RRQMRPC/Serialization/SerializeConverter.cs
create mode 100644 RRQMSocket.RPC/RRQMRPC/Serialization/XmlSerializeConverter.cs
create mode 100644 RRQMSocket.RPC/RRQMRPC/Socket/RpcSocketClient .cs
create mode 100644 RRQMSocket.RPC/RRQMRPC/Socket/TcpParser.cs
create mode 100644 RRQMSocket.RPC/RRQMRPC/Socket/TcpRpcClient.cs
create mode 100644 RRQMSocket.RPC/RRQMRPC/Socket/TcpRpcParser.cs
create mode 100644 RRQMSocket.RPC/RRQMRPC/Socket/UdpRpcClient.cs
create mode 100644 RRQMSocket.RPC/RRQMRPC/Socket/UdpRpcParser.cs
create mode 100644 RRQMSocket.RPC/RRQMSocket.RPC.csproj
create mode 100644 RRQMSocket.sln
create mode 100644 RRQMSocket/BaseSocket.cs
create mode 100644 RRQMSocket/ClassDiagram.cd
create mode 100644 RRQMSocket/Common/AsyncByte.cs
create mode 100644 RRQMSocket/Common/AsyncResult.cs
create mode 100644 RRQMSocket/Common/AsyncSender.cs
create mode 100644 RRQMSocket/Common/CreateOption.cs
create mode 100644 RRQMSocket/Common/IPHost.cs
create mode 100644 RRQMSocket/Common/ProcotolHelper.cs
create mode 100644 RRQMSocket/Config/ClientConfig.cs
create mode 100644 RRQMSocket/Config/ProtocolClientConfig.cs
create mode 100644 RRQMSocket/Config/ProtocolServiceConfig.cs
create mode 100644 RRQMSocket/Config/RRQMConfig.cs
create mode 100644 RRQMSocket/Config/ServiceConfig.cs
create mode 100644 RRQMSocket/Config/TcpClientConfig.cs
create mode 100644 RRQMSocket/Config/TcpServiceConfig.cs
create mode 100644 RRQMSocket/Config/TokenClientConfig.cs
create mode 100644 RRQMSocket/Config/TokenServiceConfig.cs
create mode 100644 RRQMSocket/Config/UdpSessionConfig.cs
create mode 100644 RRQMSocket/DataAdapter/DataAdapterTester.cs
create mode 100644 RRQMSocket/DataAdapter/DataHandlingAdapter.cs
create mode 100644 RRQMSocket/DataAdapter/FixedHeaderDataHandlingAdapter.cs
create mode 100644 RRQMSocket/DataAdapter/FixedSizeDataHandlingAdapter.cs
create mode 100644 RRQMSocket/DataAdapter/JsonStringDataHandlingAdapter.cs
create mode 100644 RRQMSocket/DataAdapter/NormalDataHandlingAdapter.cs
create mode 100644 RRQMSocket/DataAdapter/TerminatorDataHandlingAdapter.cs
create mode 100644 RRQMSocket/DelegateCollection.cs
create mode 100644 RRQMSocket/Enum/ClearType.cs
create mode 100644 RRQMSocket/Enum/FixedHeaderType.cs
create mode 100644 RRQMSocket/Enum/ServerState.cs
create mode 100644 RRQMSocket/EventArgs/BytesEventArgs.cs
create mode 100644 RRQMSocket/EventArgs/MesEventArgs.cs
create mode 100644 RRQMSocket/EventArgs/ReturnBytesEventArgs.cs
create mode 100644 RRQMSocket/Exceptions/RRQMNotConnectedException.cs
create mode 100644 RRQMSocket/Exceptions/RRQMOverlengthException.cs
create mode 100644 RRQMSocket/Exceptions/RRQMTimeoutException.cs
create mode 100644 RRQMSocket/Exceptions/RRQMTokenVerifyException.cs
create mode 100644 RRQMSocket/Interface/IClient.cs
create mode 100644 RRQMSocket/Interface/IHandleBuffer.cs
create mode 100644 RRQMSocket/Interface/IService.cs
create mode 100644 RRQMSocket/Interface/ISocket.cs
create mode 100644 RRQMSocket/Interface/ISocketClient.cs
create mode 100644 RRQMSocket/Interface/ITcpClient.cs
create mode 100644 RRQMSocket/Interface/ITcpService.cs
create mode 100644 RRQMSocket/Interface/IUserClient.cs
create mode 100644 RRQMSocket/Interface/IUserTcpClient.cs
create mode 100644 RRQMSocket/Interface/_ITcpService.cs
create mode 100644 RRQMSocket/InternalClass/BufferQueue.cs
create mode 100644 RRQMSocket/InternalClass/BufferQueueGroup.cs
create mode 100644 RRQMSocket/InternalClass/ClientBuffer.cs
create mode 100644 RRQMSocket/InternalClass/SocketCliectCollection.cs
create mode 100644 RRQMSocket/LICENSE
create mode 100644 RRQMSocket/Logger/Log.cs
create mode 100644 RRQMSocket/ParameterClass/VerifyOption.cs
create mode 100644 RRQMSocket/Pool/Interface/IClientGroup.cs
create mode 100644 RRQMSocket/Pool/Interface/IConnectionPool.cs
create mode 100644 RRQMSocket/Pool/TcpConnectionPool.cs
create mode 100644 RRQMSocket/RRQM.ico
create mode 100644 RRQMSocket/RRQM.png
create mode 100644 RRQMSocket/RRQMSocket.csproj
create mode 100644 RRQMSocket/TCP/Client/ProtocolClient.cs
create mode 100644 RRQMSocket/TCP/Client/SimpleProtocolClient.cs
create mode 100644 RRQMSocket/TCP/Client/SimpleTcpClient.cs
create mode 100644 RRQMSocket/TCP/Client/SimpleTokenClient.cs
create mode 100644 RRQMSocket/TCP/Client/TcpClient.cs
create mode 100644 RRQMSocket/TCP/Client/TokenClient.cs
create mode 100644 RRQMSocket/TCP/Service/ProtocolService.cs
create mode 100644 RRQMSocket/TCP/Service/SimpleProtocolService.cs
create mode 100644 RRQMSocket/TCP/Service/SimpleTcpService.cs
create mode 100644 RRQMSocket/TCP/Service/SimpleTokenService.cs
create mode 100644 RRQMSocket/TCP/Service/TcpService.cs
create mode 100644 RRQMSocket/TCP/Service/TokenService.cs
create mode 100644 RRQMSocket/TCP/SocketClient/ProtocolSocketClient.cs
create mode 100644 RRQMSocket/TCP/SocketClient/SimpleProtocolSocketClient.cs
create mode 100644 RRQMSocket/TCP/SocketClient/SimpleSocketClient.cs
create mode 100644 RRQMSocket/TCP/SocketClient/SocketClient.cs
create mode 100644 RRQMSocket/UDP/SimpleUdpSession.cs
create mode 100644 RRQMSocket/UDP/UdpSession.cs
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 000000000..3e8a1553f
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,341 @@
+## Ignore Visual Studio temporary files, build results, and
+## files generated by popular Visual Studio add-ons.
+##
+## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
+
+# User-specific files
+*.rsuser
+*.suo
+*.user
+*.userosscache
+*.sln.docstates
+
+# User-specific files (MonoDevelop/Xamarin Studio)
+*.userprefs
+
+# Build results
+[Dd]ebug/
+[Dd]ebugPublic/
+[Rr]elease/
+[Rr]eleases/
+x64/
+x86/
+[Aa][Rr][Mm]/
+[Aa][Rr][Mm]64/
+bld/
+[Bb]in/
+[Oo]bj/
+[Ll]og/
+
+# Visual Studio 2015/2017 cache/options directory
+.vs/
+# Uncomment if you have tasks that create the project's static files in wwwroot
+#wwwroot/
+
+# Visual Studio 2017 auto generated files
+Generated\ Files/
+
+# MSTest test Results
+[Tt]est[Rr]esult*/
+[Bb]uild[Ll]og.*
+
+# NUNIT
+*.VisualState.xml
+TestResult.xml
+
+# Build Results of an ATL Project
+[Dd]ebugPS/
+[Rr]eleasePS/
+dlldata.c
+
+# Benchmark Results
+BenchmarkDotNet.Artifacts/
+
+# .NET Core
+project.lock.json
+project.fragment.lock.json
+artifacts/
+
+# StyleCop
+StyleCopReport.xml
+
+# Files built by Visual Studio
+*_i.c
+*_p.c
+*_h.h
+*.ilk
+*.meta
+*.obj
+*.iobj
+*.pch
+*.pdb
+*.ipdb
+*.pgc
+*.pgd
+*.rsp
+*.sbr
+*.tlb
+*.tli
+*.tlh
+*.tmp
+*.tmp_proj
+*_wpftmp.csproj
+*.log
+*.vspscc
+*.vssscc
+.builds
+*.pidb
+*.svclog
+*.scc
+
+# Chutzpah Test files
+_Chutzpah*
+
+# Visual C++ cache files
+ipch/
+*.aps
+*.ncb
+*.opendb
+*.opensdf
+*.sdf
+*.cachefile
+*.VC.db
+*.VC.VC.opendb
+
+# Visual Studio profiler
+*.psess
+*.vsp
+*.vspx
+*.sap
+
+# Visual Studio Trace Files
+*.e2e
+
+# TFS 2012 Local Workspace
+$tf/
+
+# Guidance Automation Toolkit
+*.gpState
+
+# ReSharper is a .NET coding add-in
+_ReSharper*/
+*.[Rr]e[Ss]harper
+*.DotSettings.user
+
+# JustCode is a .NET coding add-in
+.JustCode
+
+# TeamCity is a build add-in
+_TeamCity*
+
+# DotCover is a Code Coverage Tool
+*.dotCover
+
+# AxoCover is a Code Coverage Tool
+.axoCover/*
+!.axoCover/settings.json
+
+# Visual Studio code coverage results
+*.coverage
+*.coveragexml
+
+# NCrunch
+_NCrunch_*
+.*crunch*.local.xml
+nCrunchTemp_*
+
+# MightyMoose
+*.mm.*
+AutoTest.Net/
+
+# Web workbench (sass)
+.sass-cache/
+
+# Installshield output folder
+[Ee]xpress/
+
+# DocProject is a documentation generator add-in
+DocProject/buildhelp/
+DocProject/Help/*.HxT
+DocProject/Help/*.HxC
+DocProject/Help/*.hhc
+DocProject/Help/*.hhk
+DocProject/Help/*.hhp
+DocProject/Help/Html2
+DocProject/Help/html
+
+# Click-Once directory
+publish/
+
+# Publish Web Output
+*.[Pp]ublish.xml
+*.azurePubxml
+# Note: Comment the next line if you want to checkin your web deploy settings,
+# but database connection strings (with potential passwords) will be unencrypted
+*.pubxml
+*.publishproj
+
+# Microsoft Azure Web App publish settings. Comment the next line if you want to
+# checkin your Azure Web App publish settings, but sensitive information contained
+# in these scripts will be unencrypted
+PublishScripts/
+
+# NuGet Packages
+*.nupkg
+# The packages folder can be ignored because of Package Restore
+**/[Pp]ackages/*
+# except build/, which is used as an MSBuild target.
+!**/[Pp]ackages/build/
+# Uncomment if necessary however generally it will be regenerated when needed
+#!**/[Pp]ackages/repositories.config
+# NuGet v3's project.json files produces more ignorable files
+*.nuget.props
+*.nuget.targets
+
+# Microsoft Azure Build Output
+csx/
+*.build.csdef
+
+# Microsoft Azure Emulator
+ecf/
+rcf/
+
+# Windows Store app package directories and files
+AppPackages/
+BundleArtifacts/
+Package.StoreAssociation.xml
+_pkginfo.txt
+*.appx
+
+# Visual Studio cache files
+# files ending in .cache can be ignored
+*.[Cc]ache
+# but keep track of directories ending in .cache
+!?*.[Cc]ache/
+
+# Others
+ClientBin/
+~$*
+*~
+*.dbmdl
+*.dbproj.schemaview
+*.jfm
+*.pfx
+*.publishsettings
+orleans.codegen.cs
+
+# Including strong name files can present a security risk
+# (https://github.com/github/gitignore/pull/2483#issue-259490424)
+#*.snk
+
+# Since there are multiple workflows, uncomment next line to ignore bower_components
+# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
+#bower_components/
+# ASP.NET Core default setup: bower directory is configured as wwwroot/lib/ and bower restore is true
+**/wwwroot/lib/
+
+# RIA/Silverlight projects
+Generated_Code/
+
+# Backup & report files from converting an old project file
+# to a newer Visual Studio version. Backup files are not needed,
+# because we have git ;-)
+_UpgradeReport_Files/
+Backup*/
+UpgradeLog*.XML
+UpgradeLog*.htm
+ServiceFabricBackup/
+*.rptproj.bak
+
+# SQL Server files
+*.mdf
+*.ldf
+*.ndf
+
+# Business Intelligence projects
+*.rdl.data
+*.bim.layout
+*.bim_*.settings
+*.rptproj.rsuser
+
+# Microsoft Fakes
+FakesAssemblies/
+
+# GhostDoc plugin setting file
+*.GhostDoc.xml
+
+# Node.js Tools for Visual Studio
+.ntvs_analysis.dat
+node_modules/
+
+# Visual Studio 6 build log
+*.plg
+
+# Visual Studio 6 workspace options file
+*.opt
+
+# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
+*.vbw
+
+# Visual Studio LightSwitch build output
+**/*.HTMLClient/GeneratedArtifacts
+**/*.DesktopClient/GeneratedArtifacts
+**/*.DesktopClient/ModelManifest.xml
+**/*.Server/GeneratedArtifacts
+**/*.Server/ModelManifest.xml
+_Pvt_Extensions
+
+# Paket dependency manager
+.paket/paket.exe
+paket-files/
+
+# FAKE - F# Make
+.fake/
+
+# JetBrains Rider
+.idea/
+*.sln.iml
+
+# CodeRush personal settings
+.cr/personal
+
+# Python Tools for Visual Studio (PTVS)
+__pycache__/
+*.pyc
+
+# Cake - Uncomment if you are using it
+# tools/**
+# !tools/packages.config
+
+# Tabs Studio
+*.tss
+
+# Telerik's JustMock configuration file
+*.jmconfig
+
+# BizTalk build output
+*.btp.cs
+*.btm.cs
+*.odx.cs
+*.xsd.cs
+
+# OpenCover UI analysis results
+OpenCover/
+
+# Azure Stream Analytics local run output
+ASALocalRun/
+
+# MSBuild Binary and Structured Log
+*.binlog
+
+# NVidia Nsight GPU debugger configuration file
+*.nvuser
+
+# MFractors (Xamarin productivity tool) working folder
+.mfractor/
+
+# Local History for Visual Studio
+.localhistory/
+
+# BeatPulse healthcheck temp database
+healthchecksdb
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 000000000..b09cd7856
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,201 @@
+Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
diff --git a/README.md b/README.md
new file mode 100644
index 000000000..831734694
--- /dev/null
+++ b/README.md
@@ -0,0 +1,397 @@
+
+
+
+
+
+
+
+
+[](https://www.nuget.org/packages/RRQMSocket/)
+[](https://www.apache.org/licenses/LICENSE-2.0.html)
+[](https://www.nuget.org/packages/RRQMSocket/)
+[](https://gitee.com/dotnetchina/RRQMSocket/stargazers)
+[](https://gitee.com/dotnetchina/RRQMSocket/members)
+
+
+
+
+
+
+
+合抱之木,生于毫末;九层之台,起于垒土。
+
+
+
+

+
+
+## 💿描述
+| 名称 |描述|
+|---|---|
+|[](https://www.nuget.org/packages/RRQMSocket/)| **RRQMSocket**是一个整合性的、超轻量级的、可以免费商用使用的网络通信服务框架。
它具有 **高并发连接** 、 **高并发处理** 、 **事件订阅** 、 **插件式扩展** 、
**多线程处理** 、 **内存池** 、 **对象池** 等特点,
让使用者能够更加简单的、快速的搭建网络框架。|
+|[](https://www.nuget.org/packages/RRQMSocketFramework/)| **RRQMSocketFramework**是RRQMSocket系列的企业版,
两者在功能上几乎没有区别,但是RRQMSocketFramework无任何依赖,
且可以提供专属的定制功能。后续也会加入企业已定制的优秀功能,希望大家多多支持。|
+| [](https://www.nuget.org/packages/RRQMSocket.FileTransfer/) | RRQMSocket.FileTransfer是一个高性能的文件传输框架,
您可以用它传输**任意大小**的文件,它可以完美支持**上传下载混合式队列传输**、
**断点续传**、 **快速上传** 、**传输限速**、**获取文件信息**、**删除文件**等。
在实时测试中,它的传输速率可达500Mb/s。 |
+|[](https://www.nuget.org/packages/RRQMSocket.RPC/) |RPC是一个超轻量、高性能、可扩展的微服务管理平台框架,
目前已完成开发**RRQMRPC**、**XmlRpc**、**JsonRpc**、**WebApi**部分。
**RRQMRPC**部分使用RRQM专属协议,支持客户端**异步调用**,
服务端**异步触发**、以及**out**和**ref**关键字,**函数回调**等。
在调用效率上也是非常强悍,在调用空载函数,且返回状态时,
**10w**次调用仅用时**3.8**秒,不返回状态用时**0.9**秒。
其他协议调用性能详看性能评测。|
+|[](https://www.nuget.org/packages/RRQMSocket.RPC.WebApi/)| WebApi是一个扩展于RRQMSocket.RPC的WebApi组件,
可以通过该组件创建WebApi服务解析器,让桌面端、Web端、移动端可以跨语言调用RPC函数。
功能支持路由、Get传参、Post传参等。|
+|[](https://www.nuget.org/packages/RRQMSocket.RPC.XmlRpc/)| XmlRpc是一个扩展于RRQMSocket.RPC的XmlRpc组件,
可以通过该组件创建XmlRpc服务解析器,完美支持XmlRpc数据类型,类型嵌套,
Array等,也能与CookComputing.XmlRpcV2完美对接。不限Web,Android等平台。|
+| [](https://www.nuget.org/packages/RRQMSocket.RPC.JsonRpc/)| JsonRpc是一个扩展于RRQMSocket.RPC的JsonRpc组件,
可以通过该组件创建JsonRpc服务解析器,支持JsonRpc全部功能,可与Web,Android等平台无缝对接。|
+| [](https://www.nuget.org/packages/RRQMSocket.Http/) | RRQMSocket.Http是一个能够简单解析Http的服务组件,
能够快速响应Http服务请求。|
+
+
+## 🖥支持环境
+- .NET Framework4.5及以上。
+- .NET Core3.1及以上。
+- .NET Standard2.0及以上。
+
+## 🥪支持框架
+- WPF
+- Winform
+- Blazor
+- Xamarin
+- Mono
+- Unity
+- 其他(即所有C#系)
+
+## 🌴RRQMSocket特点速览
+
+#### 对象池
+
+对象池在RRQMSocket有很多应用,最主要的两个就是**连接对象池**和**处理对象池**。连接对象池就是当客户端成功连接时,首先会去连接对象池中找SocketClient,然后没有的话,才会创建。如果哪个客户端掉线了,它的SocketClient就会被回收。
+
+然后就是处理对象池,在RRQMSocket中,接收数据的线程和IOCP内核线程是分开的(也可以设置拥塞接收),也就是比如说客户端给服务器发送了1w条数据,但是服务器收到后处理起来很慢,那传统的iocp肯定会放慢接收速率,然后通知客户端的tcp窗口,发生拥塞,然后让客户端暂缓发送。但是在RRQMSocket中会把收到的数据通过队列全都存起来,首先不影响iocp的接收,同时再分配线程去处理收到的报文信息,这样就相当于一个“泄洪湖泊”,能很大程度的提高处理数据的能力。
+
+#### 多线程
+
+由于有**处理对象池**的存在,使多线程处理变得简单。在客户端连接完成时,会自动分配该客户端辅助类(TcpSocketClient)的消息处理逻辑线程,假如服务器线程数量为10,则第一个连接的客户端会被分配到0号线程中,第二个连接将被分配到1号线程中,以此类推,循环分配。当某个客户端收到数据时,会将数据排入当前线程所独自拥有的队列当中,并唤醒线程执行。
+
+#### 传统IOCP和RRQMSocket
+
+RRQMSocket的IOCP和传统也不一样,就以微软官方示例为例,使用MemoryBuffer开辟一块内存,均分,然后给每个会话分配一个区接收,等收到数据后,再**复制**源数据,然后把复制的数据进行处理。而RRQMSocket是每次接收之前,从内存池拿一个可用内存块,然后**直接用于接收**,等收到数据以后,直接就把这个内存块抛出处理,这样就避免了**复制操作**,虽然只是细小的设计,但是在传输**1000w**次**64kb**的数据时,性能相差了**10倍**。
+
+#### 数据处理适配器
+
+相信大家都使用过其他的Socket产品,例如HPSocket,SuperSocket等,那么RRQMSocket在设计时也是借鉴了其他产品的优秀设计理念,数据处理适配器就是其中之一,但和其他产品的设计不同的是,RRQMSocket的适配器功能更加强大,它不仅可以提前解析数据包,还可以解析数据对象。例如:可以使用固定包头对数据进行预处理,从而解决数据分包、粘包的问题。也可以直接解析HTTP协议,经过适配器处理后传回一个HttpRequest对象等。
+
+#### 粘包、分包解决
+
+在RRQMSocket中处理TCP粘包、分包问题是非常简单的。只需要更改不同的**数据处理适配器**即可。例如:使用**固定包头**,只需要给SocketClient和TcpClient配置注入**FixedHeaderDataHandlingAdapter**的实例即可。同样对应的处理器也有**固定长度** 、 **终止字符分割** 等。
+
+#### 兼容性与适配
+
+RRQMSocket提供多种框架模型,能够完全兼容基于TCP、UDP协议的所有协议。例如:TcpService与TcpClient,其基础功能和Socket一模一样,只是增强了框架的**坚固性**和**并发性**,将**连接**和**接收数据**通过事件的形式抛出,让使用者能够更加友好的使用。
+
+其次,RRQMSocket也提供了一些特定的服务器和客户端,如TokenService和TokenClient,这两个就必须配套使用,不然在验证Token时会被主动断开。
+
+## 🔗联系作者
+
+- [CSDN博客主页](https://blog.csdn.net/qq_40374647)
+- [哔哩哔哩视频](https://space.bilibili.com/94253567)
+- [源代码仓库主页](https://gitee.com/RRQM_Home)
+- 交流QQ群:234762506
+
+## 🍻RRQM系产品
+
+| 名称| 版本(Nuget Version)|下载(Nuget Download)| 描述 |
+|------|----------|-------------|-------|
+| [RRQMCore](https://gitee.com/RRQM_OS/RRQMCore) | [](https://www.nuget.org/packages/RRQMCore/) | [](https://www.nuget.org/packages/RRQMCore/) | RRQMCore是为RRQM系提供基础服务功能的库,其中包含:**内存池**、**对象池**、**等待逻辑池**、**AppMessenger**、**3DES加密**、**Xml快速存储**、**运行时间测量器**、**文件快捷操作**、**高性能序列化器**、**规范日志接口**等。 |
+| [RRQMMVVM](https://gitee.com/RRQM_OS/RRQMMVVM) | [](https://www.nuget.org/packages/RRQMMVVM/) | [](https://www.nuget.org/packages/RRQMMVVM/) | RRQMMVVM是超轻简的MVVM框架,但是麻雀虽小,五脏俱全。|
+| [RRQMSkin](https://gitee.com/RRQM_OS/RRQMSkin) | [](https://www.nuget.org/packages/RRQMSkin/) | [](https://www.nuget.org/packages/RRQMSkin/) | RRQMSkin是WPF的控件样式库,其中包含: **无边框窗体** 、 **圆角窗体** 、 **水波纹按钮** 、 **输入提示筛选框** 、 **控件拖动效果** 、**圆角图片框**、 **弧形文字** 、 **扇形元素** 、 **指针元素** 、 **饼图** 、 **时钟** 、 **速度表盘** 等。|
+
+## 一、TCP框架
+
+#### 1.1 说明
+
+TCP框架是RRQMSocket最基础的框架,它定制了后继成员的创建、管理,维护、使用等一系列的规则,让使用者无需关心连接、掉线、失活检测、多线程安全等问题,能够专注于数据处理。
+
+#### 1.2 安装
+
+工具 ➨ Nuegt包管理器 ➨ 程序包管理器控制台
+
+```CSharp
+Install-Package RRQMSocket
+```
+
+#### 1.3 特点
+
+- 简单易用。
+- 多线程。
+- **多地址监听**(可以一次性监听多个IP及端口)
+- 适配器预处理,一键式解决**分包**、**粘包**、对象解析(如HTTP,Json)等。
+- 超简单的同步发送、异步发送、接收等操作。
+- 基于事件驱动,让每一步操作尽在掌握。
+- 高性能(服务器每秒可接收200w条信息)
+- **独立线程内存池**(每个线程拥有自己的内存池)
+
+#### 1.4 应用场景
+
+- C/S服务器开发。
+- 制造业自动化控制服务器。
+- 物联网数据采集服务器。
+- 游戏服务器开发。
+
+#### 1.5 API文档
+
+[RRQMSocket API文档](https://gitee.com/RRQM_OS/RRQM/wikis/pages?sort_id=3984527&doc_id=1402901)
+
+#### 1.6 Demo
+
+[RRQMBox](https://gitee.com/RRQM_OS/RRQMBox)
+
+## 二、Token框架
+
+#### 2.1 说明
+
+TokenService框架是RRQMSocket提供的派生自TcpService的基础框架,它在TCP基础之上,通过验证Token的方式,可以规范、筛选连接者。这样可以很大程度的**保护服务器**不疲于非法连接者的攻击。
+
+#### 2.2 安装
+
+工具➨Nuegt包管理器 ➨ 程序包管理器控制台
+
+```CSharp
+Install-Package RRQMSocket
+```
+
+#### 2.3 特点
+
+- **规范**、**筛选**连接者,保护服务器。
+- 客户端与服务器必须**配套**使用。
+
+#### 2.4 应用场景
+
+- C/S服务器开发。
+- 制造业自动化控制服务器。
+- 游戏服务器开发。
+
+#### 2.5 API文档
+
+[RRQMSocket API文档](https://gitee.com/RRQM_OS/RRQM/wikis/pages?sort_id=3984517&doc_id=1402901)
+
+#### 2.6 Demo
+
+[RRQMBox](https://gitee.com/RRQM_OS/RRQMBox)
+
+## 三、Protocol框架
+
+#### 3.1 说明
+
+ProtocolService框架是RRQMSocket提供的派生自TokenService的基础框架,它在Token基础之上,提供**协议+数据**的形式发送,其中还包括**协议冲突检测**、**协议数据占位**等。
+
+#### 3.2 安装
+
+工具 ➨ Nuegt包管理器 ➨ 程序包管理器控制台
+
+```CSharp
+Install-Package RRQMSocket
+```
+
+#### 3.3 特点
+
+- 支持**ID同步**。
+- 快捷**协议发送**。
+
+#### 3.4 应用场景
+
+- C/S服务器开发。
+- 制造业自动化控制服务器。
+- 游戏服务器开发。
+
+#### 3.5 API文档
+
+[RRQMSocket API文档](https://gitee.com/RRQM_OS/RRQM/wikis/pages?sort_id=3984517&doc_id=1402901)
+
+#### 3.6 Demo
+
+[RRQMBox](https://gitee.com/RRQM_OS/RRQMBox)
+
+## 四、RPCService框架
+
+#### 4.1 说明
+
+RPCService框架是所有远程过程调用的微服务调用管理平台,在该平台的托管下,使多种协议、多种序列化方式调用成为可能。目前可使用RRQMRPC、WebApi、XmlRpc、JsonRpc共同调用。
+
+#### 4.2 RPC解析器
+
+**说明:** RPCService仅仅是对调用的服务进行管理和维护,并不参与实质性的通信过程。实际上由于通信协议、序列化方式的不同,需要创建相对应的解析器才能完成调用操作。
+
+#### 4.3 RPC解析器之RRQMRPC
+
+##### 4.3.1 说明
+
+RRQMRPC是基于Protocol框架、固定包头解析的远程调用框架,也是RRQM中性能最强悍、使用最简单、功能最强大的RPC框架。
+
+##### 4.3.2 特点
+
+- 支持**自定义**类型参数。
+- 支持具有**默认值**的参数设定。
+- 支持**out、ref** 关键字参数。
+- 支持服务器**回调客户端** 。
+- 支持**客户端**之间**相互调用**。
+- 支持TCP、UDP等不同的协议调用相同服务。
+- 支持异步调用。
+- 支持权限管理,让非法调用死在萌芽时期。
+- 支持**静态织入调用**,**静态编译调用**,也支持**方法名+参数**调用。
+- 支持**调用配置**(类似MQTT的AtMostOnce,AtLeastOnce,ExactlyOnce)。
+- **支持EventBus**(企业版支持)。
+- 支持**自定义序列化**。
+- **全异常反馈** ,服务器调用状态会完整的反馈到客户端(可以设置不反馈)。
+- 高性能,在保证送达但不返回的情况下,10w次调用用时0.8s,在返回的情况下,用时3.9s。
+
+##### 4.3.3 安装
+
+工具 ➨ Nuegt包管理器 ➨ 程序包管理器控制台
+
+```CSharp
+Install-Package RRQMSocket.RPC
+```
+
+##### 4.3.4 RRQMRPC性能测试
+
+ **说明:**
+图一、图二、图三分别为`UDP无反馈调用`、`TCP有反馈调用`、`TCP连接池有反馈调用`。调用次数均为10w次,调用性能非常nice。在无反馈中,吞吐量达14.28w,在有反馈中达2.72w。
+
+
+
+
+
+
+
+
+
+#### 4.4 RPC解析器之WebApi
+
+##### 4.4.1 说明
+
+使用WebApi解析器,就可以在RPCService中通过WebApi的调用方式直接调用服务。
+
+##### 4.4.2 特点
+
+- 高性能,100个客户端,10w次调用,仅用时17s。
+- **全异常反馈** 。
+- 支持大部分路由规则。
+- 支持js、Android等调用。
+
+##### 4.4.3 安装
+
+工具 ➨ Nuegt包管理器 ➨ 程序包管理器控制台
+
+```CSharp
+Install-Package RRQMSocket.RPC.WebApi
+```
+
+#### 4.5 RPC解析器之XmlRpc
+
+##### 4.5.1 说明
+
+使用XmlRpc解析器,就可以在RPCService中通过XmlRpc的调用方式直接调用服务,客户端可以使用**CookComputing.XmlRpcV2**进行对接。
+
+##### 4.5.2 特点
+
+- **异常反馈** 。
+- 支持自定义类型。
+- 支持类型嵌套。
+- 支持Array及自定义Array嵌套。
+- 支持js、Android等调用。
+
+##### 4.5.3 安装
+
+工具 ➨ Nuegt包管理器 ➨ 程序包管理器控制台
+
+```CSharp
+Install-Package RRQMSocket.RPC.XmlRpc
+```
+
+#### 4.6 RPC解析器之JsonRpc
+
+##### 4.6.1 说明
+
+使用JsonRpc解析器,就可以在RPCService中通过Json字符串直接调用服务。
+
+##### 4.6.2 特点
+
+- **异常反馈** 。
+- 支持自定义类型。
+- 支持类型嵌套。
+- 支持js、Android等调用。
+
+##### 4.6.3 安装
+
+工具 ➨ Nuegt包管理器 ➨ 程序包管理器控制台
+
+```CSharp
+Install-Package RRQMSocket.RPC.JsonRpc
+```
+
+#### 4.7 API文档
+
+[RRQMSocket API文档](https://gitee.com/RRQM_OS/RRQM/wikis/pages?sort_id=3984517&doc_id=1402901)
+
+#### 4.8 Demo
+
+[RRQMBox](https://gitee.com/RRQM_OS/RRQMBox)
+
+## 五、文件传输框架
+
+#### 5.1 说明
+
+RRQMSocket.FileTransfer是一个高性能的文件传输框架,由于它派生自RRQMRPC,所以也具备RPC的全部特性。
+
+#### 5.2 特点
+
+- 简单易用。
+- 多线程处理。
+- 高性能,传输速度可达**500Mb/s**。
+- 超简单的**传输限速**设置,1k-10Gb 无级调节。
+- 超简单的传输速度、传输进度获取。
+- 随心所欲的暂停、继续、停止传输。
+- 系统化的权限管理,让敏感文件只允许**私有化下载**。
+- **RPC交互**,让客户端和服务器交流不延迟。
+- 基于**事件驱动**,让每一步操作尽在掌握。
+- 可视化的文件块流,可以实现像迅雷一样的**填充式进度条**。
+- 超简单的**断点续传**设置,为大文件传输保驾护航。
+- 无状态上传断点续传设置,让同一个文件,在不同客户端之间**接力上传**。
+- **断网续传**(企业版支持)
+- 已经上传的文件,再次上传时,可实现**快速上传**。
+- 极少的GC释放。
+
+#### 5.3 安装
+
+工具 ➨ Nuegt包管理器 ➨ 程序包管理器控制台
+
+```CSharp
+Install-Package RRQMSocket.FileTransfer
+```
+
+#### 5.4 Demo示例
+
+ **Demo位置:** [RRQMBox](https://gitee.com/RRQM_OS/RRQMBox)
+
+#### 5.5 性能测试
+
+ **说明:** 可以看到,图一正在上传一个Window的系统镜像文件,大约4.2Gb,传输速度已达到346Mb/s,这是因为服务器和客户端在同一电脑上,磁盘性能限制导致的。其次,GC基本上没有释放,性能非常强悍,图二是下载文件,性能依旧非常强悍。
+
+
+
+
+
+## 致谢
+
+谢谢大家对我的支持,如果还有其他问题,请加群QQ:234762506讨论。
+
+
+## 💕 支持本项目
+您的支持就是我不懈努力的动力。
+
+#### 爱心赞助名单(以下排名只按照打赏时间顺序)
+
+ 1. Bobo Joker(200¥)
+ 2. UnitySir(66¥)
+ 3. Coffee(100¥)
+ 4. Ninety(50¥)
+ 5. *琼(100¥)
+ 6. **安(5¥)
+
+#### 商业采购名单(以下排名只按照商业采购时间顺序)
+1.凯斯得****有限公司
+
+
+
diff --git a/RRQMSocket.FileTransfer/Common/FileBlock.cs b/RRQMSocket.FileTransfer/Common/FileBlock.cs
new file mode 100644
index 000000000..5d8216cf6
--- /dev/null
+++ b/RRQMSocket.FileTransfer/Common/FileBlock.cs
@@ -0,0 +1,40 @@
+//------------------------------------------------------------------------------
+// 此代码版权(除特别声明或在RRQMCore.XREF命名空间的代码)归作者本人若汝棋茗所有
+// 源代码使用协议遵循本仓库的开源协议及附加协议,若本仓库没有设置,则按MIT开源协议授权
+// CSDN博客:https://blog.csdn.net/qq_40374647
+// 哔哩哔哩视频:https://space.bilibili.com/94253567
+// Gitee源代码仓库:https://gitee.com/RRQM_Home
+// Github源代码仓库:https://github.com/RRQM
+// 交流QQ群:234762506
+// 感谢您的下载和使用
+//------------------------------------------------------------------------------
+//------------------------------------------------------------------------------
+
+namespace RRQMSocket.FileTransfer
+{
+ ///
+ /// 文件块
+ ///
+ public class FileBlock
+ {
+ ///
+ /// 文件快索引
+ ///
+ public int Index { get; internal set; }
+
+ ///
+ /// 文件流位置
+ ///
+ public long Position { get; internal set; }
+
+ ///
+ /// 文件块长度
+ ///
+ public long UnitLength { get; internal set; }
+
+ ///
+ /// 请求状态
+ ///
+ public RequestStatus RequestStatus { get; internal set; }
+ }
+}
\ No newline at end of file
diff --git a/RRQMSocket.FileTransfer/Common/FileHashGenerator.cs b/RRQMSocket.FileTransfer/Common/FileHashGenerator.cs
new file mode 100644
index 000000000..e964c7c43
--- /dev/null
+++ b/RRQMSocket.FileTransfer/Common/FileHashGenerator.cs
@@ -0,0 +1,80 @@
+//------------------------------------------------------------------------------
+// 此代码版权(除特别声明或在RRQMCore.XREF命名空间的代码)归作者本人若汝棋茗所有
+// 源代码使用协议遵循本仓库的开源协议及附加协议,若本仓库没有设置,则按MIT开源协议授权
+// CSDN博客:https://blog.csdn.net/qq_40374647
+// 哔哩哔哩视频:https://space.bilibili.com/94253567
+// Gitee源代码仓库:https://gitee.com/RRQM_Home
+// Github源代码仓库:https://github.com/RRQM
+// 交流QQ群:234762506
+// 感谢您的下载和使用
+//------------------------------------------------------------------------------
+//------------------------------------------------------------------------------
+using RRQMCore.IO;
+using System.IO;
+using System.Security.Cryptography;
+
+namespace RRQMSocket.FileTransfer
+{
+ ///
+ /// 文件Hash校验
+ ///
+ public static class FileHashGenerator
+ {
+ private static FileHashType fileCheckType;
+
+ ///
+ /// 文件
+ ///
+ public static FileHashType FileCheckType
+ {
+ get { return fileCheckType; }
+ set { fileCheckType = value; }
+ }
+
+ ///
+ /// 获取文件Hash
+ ///
+ ///
+ ///
+ public static string GetFileHash(string path)
+ {
+ using (FileStream fileStream = new FileStream(path, FileMode.Open, FileAccess.Read))
+ {
+ return GetFileHash(fileStream);
+ }
+ }
+
+ ///
+ /// 获取文件Hash
+ ///
+ ///
+ ///
+ public static string GetFileHash(FileStream fileStream)
+ {
+ HashAlgorithm hash;
+ switch (fileCheckType)
+ {
+ case FileHashType.MD5:
+ hash = MD5.Create();
+ break;
+
+ case FileHashType.SHA1:
+ hash = SHA1.Create();
+ break;
+
+ case FileHashType.SHA256:
+ hash = SHA256.Create();
+ break;
+
+ case FileHashType.SHA512:
+ hash = SHA512.Create();
+ break;
+
+ default:
+ hash = null;
+ break;
+ }
+ return FileControler.GetStreamHash(fileStream, hash);
+ }
+ }
+}
\ No newline at end of file
diff --git a/RRQMSocket.FileTransfer/Common/FileStreamPool.cs b/RRQMSocket.FileTransfer/Common/FileStreamPool.cs
new file mode 100644
index 000000000..08dd010b7
--- /dev/null
+++ b/RRQMSocket.FileTransfer/Common/FileStreamPool.cs
@@ -0,0 +1,250 @@
+//------------------------------------------------------------------------------
+// 此代码版权(除特别声明或在RRQMCore.XREF命名空间的代码)归作者本人若汝棋茗所有
+// 源代码使用协议遵循本仓库的开源协议及附加协议,若本仓库没有设置,则按MIT开源协议授权
+// CSDN博客:https://blog.csdn.net/qq_40374647
+// 哔哩哔哩视频:https://space.bilibili.com/94253567
+// Gitee源代码仓库:https://gitee.com/RRQM_Home
+// Github源代码仓库:https://github.com/RRQM
+// 交流QQ群:234762506
+// 感谢您的下载和使用
+//------------------------------------------------------------------------------
+//------------------------------------------------------------------------------
+using RRQMCore.ByteManager;
+using RRQMCore.Exceptions;
+using System;
+using System.Collections.Concurrent;
+using System.Threading;
+
+namespace RRQMSocket.FileTransfer
+{
+ ///
+ /// 文件流池
+ ///
+ public static class FileStreamPool
+ {
+ internal static ConcurrentDictionary pathStream = new ConcurrentDictionary();
+ private readonly static object locker = new object();
+ private static ReaderWriterLockSlim lockSlim = new ReaderWriterLockSlim();
+
+ internal static bool CheckAllFileBlockFinished(string path)
+ {
+ lock (locker)
+ {
+ RRQMStream stream;
+ if (!pathStream.TryGetValue(path, out stream))
+ {
+ return false;
+ }
+ if (stream.StreamType == StreamOperationType.Read)
+ {
+ return false;
+ }
+ foreach (var block in stream.Blocks)
+ {
+ if (block.RequestStatus != RequestStatus.Finished)
+ {
+ return false;
+ }
+ }
+ return true;
+ }
+ }
+
+ internal static void DisposeReadStream(string path)
+ {
+ RRQMStream stream;
+ if (pathStream.TryGetValue(path, out stream))
+ {
+ if (Interlocked.Decrement(ref stream.reference) == 0)
+ {
+ if (pathStream.TryRemove(path, out stream))
+ {
+ stream.Dispose();
+ }
+ }
+ }
+ }
+
+ internal static void DisposeWriteStream(string path, bool finished)
+ {
+ RRQMStream stream;
+ if (pathStream.TryGetValue(path, out stream))
+ {
+ if (Interlocked.Decrement(ref stream.reference) == 0)
+ {
+ if (pathStream.TryRemove(path, out stream))
+ {
+ if (finished)
+ {
+ stream.FinishStream();
+ }
+ else
+ {
+ stream.Dispose();
+ }
+ }
+ }
+ }
+ }
+
+ internal static bool GetFreeFileBlock(string path, out FileBlock fileBlock, out string mes)
+ {
+ lock (locker)
+ {
+ RRQMStream stream;
+ if (!pathStream.TryGetValue(path, out stream))
+ {
+ mes = "没有此路径的写入信息";
+ fileBlock = null;
+ return false;
+ }
+ if (stream.StreamType == StreamOperationType.Read)
+ {
+ mes = "该路径的流为只读";
+ fileBlock = null;
+ return false;
+ }
+ foreach (var block in stream.Blocks)
+ {
+ if (block.RequestStatus == RequestStatus.Hovering)
+ {
+ block.RequestStatus = RequestStatus.InProgress;
+ fileBlock = block;
+ mes = null;
+ return true;
+ }
+ }
+ fileBlock = null;
+ mes = null;
+ return true;
+ }
+ }
+
+ internal static bool LoadReadStream(ref UrlFileInfo urlFileInfo, out string mes)
+ {
+ RRQMStream stream;
+ if (pathStream.TryGetValue(urlFileInfo.FilePath, out stream))
+ {
+ Interlocked.Increment(ref stream.reference);
+ mes = null;
+ return true;
+ }
+ else
+ {
+ if (RRQMStream.CreateReadStream(out stream, ref urlFileInfo, out mes))
+ {
+ Interlocked.Increment(ref stream.reference);
+ pathStream.TryAdd(urlFileInfo.FilePath, stream);
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+ }
+ }
+
+ internal static bool LoadWriteStream(ref ProgressBlockCollection blocks, bool onlySearch, out string mes)
+ {
+ RRQMStream stream;
+ string rrqmPath = blocks.UrlFileInfo.SaveFullPath + ".rrqm";
+ if (!pathStream.TryGetValue(rrqmPath, out stream))
+ {
+ if (RRQMStream.CreateWriteStream(out stream, ref blocks, out mes))
+ {
+ Interlocked.Increment(ref stream.reference);
+ mes = null;
+ return pathStream.TryAdd(rrqmPath, stream);
+ }
+ else
+ {
+ return false;
+ }
+ }
+ else
+ {
+ if (onlySearch)
+ {
+ blocks = stream.Blocks;
+ mes = null;
+ return true;
+ }
+ mes = "该文件流正在被其他客户端拥有";
+ return false;
+ }
+ }
+
+ internal static bool ReadFile(string path, out string mes, long beginPosition, ByteBlock byteBlock, int offset, int length)
+ {
+ lockSlim.EnterReadLock();
+ try
+ {
+ if (pathStream.TryGetValue(path, out RRQMStream stream))
+ {
+ stream.FileStream.Position = beginPosition;
+
+ if (byteBlock.Buffer.Length < length + offset)
+ {
+ byteBlock.SetBuffer(new byte[length + offset]);
+ }
+
+ int r = stream.FileStream.Read(byteBlock.Buffer, offset, length);
+ if (r == length)
+ {
+ byteBlock.Position = offset + length;
+ byteBlock.SetLength(offset + length);
+ mes = null;
+ return true;
+ }
+ }
+ mes = "没有找到该路径下的流文件";
+ return false;
+ }
+ catch (Exception ex)
+ {
+ mes = ex.Message;
+ return false;
+ }
+ finally
+ {
+ lockSlim.ExitReadLock();
+ }
+ }
+
+ internal static void SaveProgressBlockCollection(string path)
+ {
+ RRQMStream stream;
+ if (pathStream.TryGetValue(path, out stream))
+ {
+ stream.SaveProgressBlockCollection();
+ }
+ else
+ {
+ throw new RRQMException("没有找到该路径下的流文件");
+ }
+ }
+
+ internal static bool WriteFile(string path, out string mes, out RRQMStream stream, long streamPosition, byte[] buffer, int offset, int length)
+ {
+ try
+ {
+ if (pathStream.TryGetValue(path, out stream))
+ {
+ stream.FileStream.Position = streamPosition;
+ stream.FileStream.Write(buffer, offset, length);
+ stream.FileStream.Flush();
+ mes = null;
+ return true;
+ }
+ mes = "未找到该路径下的流";
+ return false;
+ }
+ catch (Exception ex)
+ {
+ mes = ex.Message;
+ stream = null;
+ return false;
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/RRQMSocket.FileTransfer/Common/FileTransferErrorExceptionMapping.cs b/RRQMSocket.FileTransfer/Common/FileTransferErrorExceptionMapping.cs
new file mode 100644
index 000000000..f1f92fbe1
--- /dev/null
+++ b/RRQMSocket.FileTransfer/Common/FileTransferErrorExceptionMapping.cs
@@ -0,0 +1,28 @@
+//------------------------------------------------------------------------------
+// 此代码版权(除特别声明或在RRQMCore.XREF命名空间的代码)归作者本人若汝棋茗所有
+// 源代码使用协议遵循本仓库的开源协议及附加协议,若本仓库没有设置,则按MIT开源协议授权
+// CSDN博客:https://blog.csdn.net/qq_40374647
+// 哔哩哔哩视频:https://space.bilibili.com/94253567
+// Gitee源代码仓库:https://gitee.com/RRQM_Home
+// Github源代码仓库:https://github.com/RRQM
+// 交流QQ群:234762506
+// 感谢您的下载和使用
+//------------------------------------------------------------------------------
+//------------------------------------------------------------------------------
+using RRQMCore.Exceptions;
+
+namespace RRQMSocket.FileTransfer
+{
+ ///
+ /// 文件传输错误码映射
+ ///
+ public class FileTransferErrorExceptionMapping : ErrorExceptionMapping
+ {
+ private static FileTransferErrorExceptionMapping _instance = new FileTransferErrorExceptionMapping();
+
+ ///
+ /// 默认实例
+ ///
+ public static FileTransferErrorExceptionMapping Default { get => _instance; }
+ }
+}
\ No newline at end of file
diff --git a/RRQMSocket.FileTransfer/Common/FileWaitResult.cs b/RRQMSocket.FileTransfer/Common/FileWaitResult.cs
new file mode 100644
index 000000000..b52fa4483
--- /dev/null
+++ b/RRQMSocket.FileTransfer/Common/FileWaitResult.cs
@@ -0,0 +1,20 @@
+//------------------------------------------------------------------------------
+// 此代码版权(除特别声明或在RRQMCore.XREF命名空间的代码)归作者本人若汝棋茗所有
+// 源代码使用协议遵循本仓库的开源协议及附加协议,若本仓库没有设置,则按MIT开源协议授权
+// CSDN博客:https://blog.csdn.net/qq_40374647
+// 哔哩哔哩视频:https://space.bilibili.com/94253567
+// Gitee源代码仓库:https://gitee.com/RRQM_Home
+// Github源代码仓库:https://github.com/RRQM
+// 交流QQ群:234762506
+// 感谢您的下载和使用
+//------------------------------------------------------------------------------
+//------------------------------------------------------------------------------
+using RRQMCore.Run;
+
+namespace RRQMSocket.FileTransfer
+{
+ internal class FileWaitResult : WaitResult
+ {
+ public PBCollectionTemp PBCollectionTemp { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/RRQMSocket.FileTransfer/Common/PBCollectionTemp.cs b/RRQMSocket.FileTransfer/Common/PBCollectionTemp.cs
new file mode 100644
index 000000000..353a177c7
--- /dev/null
+++ b/RRQMSocket.FileTransfer/Common/PBCollectionTemp.cs
@@ -0,0 +1,64 @@
+//------------------------------------------------------------------------------
+// 此代码版权(除特别声明或在RRQMCore.XREF命名空间的代码)归作者本人若汝棋茗所有
+// 源代码使用协议遵循本仓库的开源协议及附加协议,若本仓库没有设置,则按MIT开源协议授权
+// CSDN博客:https://blog.csdn.net/qq_40374647
+// 哔哩哔哩视频:https://space.bilibili.com/94253567
+// Gitee源代码仓库:https://gitee.com/RRQM_Home
+// Github源代码仓库:https://github.com/RRQM
+// 交流QQ群:234762506
+// 感谢您的下载和使用
+//------------------------------------------------------------------------------
+//------------------------------------------------------------------------------
+using System.Collections.Generic;
+
+namespace RRQMSocket.FileTransfer
+{
+ ///
+ /// 临时序列化
+ ///
+ public class PBCollectionTemp
+ {
+ ///
+ /// 文件信息
+ ///
+ public UrlFileInfo UrlFileInfo { get; internal set; }
+
+ ///
+ /// 块集合
+ ///
+ public List Blocks { get; internal set; }
+
+ ///
+ /// 从文件块转换
+ ///
+ ///
+ ///
+ public static PBCollectionTemp GetFromProgressBlockCollection(ProgressBlockCollection progressBlocks)
+ {
+ if (progressBlocks == null)
+ {
+ return null;
+ }
+ PBCollectionTemp collectionTemp = new PBCollectionTemp();
+ collectionTemp.UrlFileInfo = progressBlocks.UrlFileInfo;
+ collectionTemp.Blocks = new List();
+ collectionTemp.Blocks.AddRange(progressBlocks);
+ return collectionTemp;
+ }
+
+ ///
+ /// 转换为ProgressBlockCollection
+ ///
+ ///
+ public ProgressBlockCollection ToPBCollection()
+ {
+ ProgressBlockCollection progressBlocks = new ProgressBlockCollection();
+ progressBlocks.UrlFileInfo = this.UrlFileInfo;
+ if (this.Blocks != null)
+ {
+ progressBlocks.AddRange(this.Blocks);
+ }
+ return progressBlocks;
+ }
+ }
+}
\ No newline at end of file
diff --git a/RRQMSocket.FileTransfer/Common/ProgressBlockCollection.cs b/RRQMSocket.FileTransfer/Common/ProgressBlockCollection.cs
new file mode 100644
index 000000000..3eb8e2f46
--- /dev/null
+++ b/RRQMSocket.FileTransfer/Common/ProgressBlockCollection.cs
@@ -0,0 +1,106 @@
+//------------------------------------------------------------------------------
+// 此代码版权(除特别声明或在RRQMCore.XREF命名空间的代码)归作者本人若汝棋茗所有
+// 源代码使用协议遵循本仓库的开源协议及附加协议,若本仓库没有设置,则按MIT开源协议授权
+// CSDN博客:https://blog.csdn.net/qq_40374647
+// 哔哩哔哩视频:https://space.bilibili.com/94253567
+// Gitee源代码仓库:https://gitee.com/RRQM_Home
+// Github源代码仓库:https://github.com/RRQM
+// 交流QQ群:234762506
+// 感谢您的下载和使用
+//------------------------------------------------------------------------------
+//------------------------------------------------------------------------------
+using RRQMCore.Serialization;
+using System;
+using System.IO;
+
+namespace RRQMSocket.FileTransfer
+{
+ ///
+ /// 文件进度块集合
+ ///
+ public class ProgressBlockCollection : ReadOnlyList
+ {
+ ///
+ /// 文件信息
+ ///
+ public UrlFileInfo UrlFileInfo { get; internal set; }
+
+ private static int blockLength = 1024 * 1024 * 10;
+
+ ///
+ /// 分块长度,min=1024*1024*5
+ ///
+ public static int BlockLength
+ {
+ get { return blockLength; }
+ set
+ {
+ if (value < 1024 * 1024 * 5)
+ {
+ value = 1024 * 1024 * 5;
+ }
+ blockLength = value;
+ }
+ }
+
+ ///
+ /// 保存
+ ///
+ ///
+ internal void Save(string path)
+ {
+ if (File.Exists(path))
+ {
+ File.Delete(path);
+ }
+ byte[] buffer = SerializeConvert.RRQMBinarySerialize(this, true);
+ using (FileStream fileStream = new FileStream(path, FileMode.OpenOrCreate, FileAccess.ReadWrite))
+ {
+ fileStream.Write(buffer, 0, buffer.Length);
+ }
+ }
+
+ ///
+ /// 读取
+ ///
+ ///
+ ///
+ internal static ProgressBlockCollection Read(string path)
+ {
+ try
+ {
+ using (FileStream stream = File.OpenRead(path))
+ {
+ byte[] buffer = new byte[stream.Length];
+ stream.Read(buffer, 0, buffer.Length);
+ return SerializeConvert.RRQMBinaryDeserialize(buffer, 0);
+ }
+ }
+ catch (Exception)
+ {
+ return null;
+ }
+ }
+
+ internal static ProgressBlockCollection CreateProgressBlockCollection(UrlFileInfo urlFileInfo)
+ {
+ ProgressBlockCollection blocks = new ProgressBlockCollection();
+ blocks.UrlFileInfo = urlFileInfo;
+ long position = 0;
+ long surLength = urlFileInfo.FileLength;
+ int index = 0;
+ while (surLength > 0)
+ {
+ FileBlock block = new FileBlock();
+ block.Index = index++;
+ block.RequestStatus = RequestStatus.Hovering;
+ block.Position = position;
+ block.UnitLength = surLength > blockLength ? blockLength : surLength;
+ blocks.Add(block);
+ position += block.UnitLength;
+ surLength -= block.UnitLength;
+ }
+ return blocks;
+ }
+ }
+}
\ No newline at end of file
diff --git a/RRQMSocket.FileTransfer/Common/RRQMStream.cs b/RRQMSocket.FileTransfer/Common/RRQMStream.cs
new file mode 100644
index 000000000..e03d7fc3b
--- /dev/null
+++ b/RRQMSocket.FileTransfer/Common/RRQMStream.cs
@@ -0,0 +1,157 @@
+//------------------------------------------------------------------------------
+// 此代码版权(除特别声明或在RRQMCore.XREF命名空间的代码)归作者本人若汝棋茗所有
+// 源代码使用协议遵循本仓库的开源协议及附加协议,若本仓库没有设置,则按MIT开源协议授权
+// CSDN博客:https://blog.csdn.net/qq_40374647
+// 哔哩哔哩视频:https://space.bilibili.com/94253567
+// Gitee源代码仓库:https://gitee.com/RRQM_Home
+// Github源代码仓库:https://github.com/RRQM
+// 交流QQ群:234762506
+// 感谢您的下载和使用
+//------------------------------------------------------------------------------
+//------------------------------------------------------------------------------
+using RRQMCore.Serialization;
+using System;
+using System.IO;
+
+namespace RRQMSocket.FileTransfer
+{
+ internal class RRQMStream
+ {
+ internal int reference;
+
+ private ProgressBlockCollection blocks;
+
+ private FileStream fileStream;
+ private string rrqmPath;
+ private StreamOperationType streamType;
+
+ private UrlFileInfo urlFileInfo;
+
+ private RRQMStream()
+ {
+ }
+
+ public ProgressBlockCollection Blocks { get { return blocks; } }
+
+ public FileStream FileStream
+ {
+ get { return fileStream; }
+ }
+
+ public StreamOperationType StreamType
+ {
+ get { return streamType; }
+ }
+
+ public UrlFileInfo UrlFileInfo { get => urlFileInfo; }
+
+ internal static bool CreateReadStream(out RRQMStream stream, ref UrlFileInfo urlFileInfo, out string mes)
+ {
+ stream = new RRQMStream();
+ try
+ {
+ stream.streamType = StreamOperationType.Read;
+ stream.fileStream = File.OpenRead(urlFileInfo.FilePath);
+ urlFileInfo.FileLength = stream.fileStream.Length;
+ stream.urlFileInfo = urlFileInfo;
+ mes = null;
+ return true;
+ }
+ catch (Exception ex)
+ {
+ stream.Dispose();
+ stream = null;
+ mes = ex.Message;
+ return false;
+ }
+ }
+
+ internal static bool CreateWriteStream(out RRQMStream stream, ref ProgressBlockCollection blocks, out string mes)
+ {
+ stream = new RRQMStream();
+ stream.rrqmPath = blocks.UrlFileInfo.SaveFullPath + ".rrqm";
+ stream.urlFileInfo = blocks.UrlFileInfo;
+ stream.streamType = StreamOperationType.Write;
+ try
+ {
+ if (blocks.UrlFileInfo.Flags.HasFlag(TransferFlags.BreakpointResume) && File.Exists(stream.rrqmPath))
+ {
+ stream.fileStream = new FileStream(stream.rrqmPath, FileMode.OpenOrCreate, FileAccess.ReadWrite);
+ int blocksLength = (int)(stream.fileStream.Length - blocks.UrlFileInfo.FileLength);
+ if (blocksLength > 0)
+ {
+ stream.fileStream.Position = blocks.UrlFileInfo.FileLength;
+ byte[] buffer = new byte[blocksLength];
+ stream.fileStream.Read(buffer, 0, buffer.Length);
+ try
+ {
+ PBCollectionTemp readBlocks = SerializeConvert.RRQMBinaryDeserialize(buffer);
+ if (readBlocks.UrlFileInfo != null && blocks.UrlFileInfo != null && readBlocks.UrlFileInfo.FileHash != null)
+ {
+ if (readBlocks.UrlFileInfo.FileHash == blocks.UrlFileInfo.FileHash)
+ {
+ stream.blocks = blocks = readBlocks.ToPBCollection();
+ mes = null;
+ return true;
+ }
+ }
+ }
+ catch
+ {
+ }
+ }
+ stream.fileStream.Dispose();
+ }
+ stream.blocks = blocks;
+ if (File.Exists(stream.rrqmPath))
+ {
+ File.Delete(stream.rrqmPath);
+ }
+ stream.fileStream = new FileStream(stream.rrqmPath, FileMode.Create, FileAccess.ReadWrite);
+ stream.SaveProgressBlockCollection();
+ mes = null;
+ return true;
+ }
+ catch (Exception ex)
+ {
+ mes = ex.Message;
+ stream.Dispose();
+ stream = null;
+ return false;
+ }
+ }
+
+ internal bool FinishStream()
+ {
+ this.fileStream.SetLength(this.urlFileInfo.FileLength);
+ this.fileStream.Flush();
+ UrlFileInfo info = this.urlFileInfo;
+ this.Dispose();
+ if (File.Exists(info.SaveFullPath))
+ {
+ File.Delete(info.SaveFullPath);
+ }
+ File.Move(info.SaveFullPath + ".rrqm", info.SaveFullPath);
+ return true;
+ }
+
+ internal void Dispose()
+ {
+ this.blocks = null;
+ this.urlFileInfo = null;
+ if (this.fileStream != null)
+ {
+ this.fileStream.Dispose();
+ this.fileStream = null;
+ }
+ }
+
+ internal void SaveProgressBlockCollection()
+ {
+ byte[] dataBuffer = SerializeConvert.RRQMBinarySerialize(PBCollectionTemp.GetFromProgressBlockCollection(blocks), true);
+ this.fileStream.Position = this.urlFileInfo.FileLength;
+ this.fileStream.WriteAsync(dataBuffer, 0, dataBuffer.Length);
+ this.fileStream.Flush();
+ }
+ }
+}
\ No newline at end of file
diff --git a/RRQMSocket.FileTransfer/Common/ReadOnlyList.cs b/RRQMSocket.FileTransfer/Common/ReadOnlyList.cs
new file mode 100644
index 000000000..ca2da9cab
--- /dev/null
+++ b/RRQMSocket.FileTransfer/Common/ReadOnlyList.cs
@@ -0,0 +1,93 @@
+//------------------------------------------------------------------------------
+// 此代码版权(除特别声明或在RRQMCore.XREF命名空间的代码)归作者本人若汝棋茗所有
+// 源代码使用协议遵循本仓库的开源协议及附加协议,若本仓库没有设置,则按MIT开源协议授权
+// CSDN博客:https://blog.csdn.net/qq_40374647
+// 哔哩哔哩视频:https://space.bilibili.com/94253567
+// Gitee源代码仓库:https://gitee.com/RRQM_Home
+// Github源代码仓库:https://github.com/RRQM
+// 交流QQ群:234762506
+// 感谢您的下载和使用
+//------------------------------------------------------------------------------
+//------------------------------------------------------------------------------
+using System;
+using System.Collections;
+using System.Collections.Generic;
+
+namespace RRQMSocket.FileTransfer
+{
+ ///
+ /// 只读
+ ///
+ ///
+
+ public class ReadOnlyList : IEnumerable
+ {
+ private List list = new List();
+
+ internal void Add(T block)
+ {
+ list.Add(block);
+ }
+
+ internal void AddRange(IEnumerable collection)
+ {
+ list.AddRange(collection);
+ }
+
+ internal void Remove(T block)
+ {
+ list.Remove(block);
+ }
+
+ internal void RemoveAt(int index)
+ {
+ list.RemoveAt(index);
+ }
+
+ internal void RemoveAll(Predicate match)
+ {
+ list.RemoveAll(match);
+ }
+
+ internal void RemoveRange(int index, int range)
+ {
+ list.RemoveRange(index, range);
+ }
+
+ internal void Clear()
+ {
+ list.Clear();
+ }
+
+ internal void Insert(int index, T item)
+ {
+ list.Insert(index, item);
+ }
+
+ internal void InsertRange(int index, IEnumerable collection)
+ {
+ list.InsertRange(index, collection);
+ }
+
+ ///
+ /// 返回迭代器
+ ///
+ ///
+ public IEnumerator GetEnumerator()
+ {
+ return this.list.GetEnumerator();
+ }
+
+ IEnumerator IEnumerable.GetEnumerator()
+ {
+ return this.list.GetEnumerator();
+ }
+
+ ///
+ /// 获取对象
+ ///
+ ///
+ ///
+ public T this[int index] { get { return list[index]; } }
+ }
+}
\ No newline at end of file
diff --git a/RRQMSocket.FileTransfer/Common/Speed.cs b/RRQMSocket.FileTransfer/Common/Speed.cs
new file mode 100644
index 000000000..19951c904
--- /dev/null
+++ b/RRQMSocket.FileTransfer/Common/Speed.cs
@@ -0,0 +1,22 @@
+//------------------------------------------------------------------------------
+// 此代码版权(除特别声明或在RRQMCore.XREF命名空间的代码)归作者本人若汝棋茗所有
+// 源代码使用协议遵循本仓库的开源协议及附加协议,若本仓库没有设置,则按MIT开源协议授权
+// CSDN博客:https://blog.csdn.net/qq_40374647
+// 哔哩哔哩视频:https://space.bilibili.com/94253567
+// Gitee源代码仓库:https://gitee.com/RRQM_Home
+// Github源代码仓库:https://github.com/RRQM
+// 交流QQ群:234762506
+// 感谢您的下载和使用
+//------------------------------------------------------------------------------
+//------------------------------------------------------------------------------
+namespace RRQMSocket.FileTransfer
+{
+ ///
+ ///
+ ///
+ internal class Speed
+ {
+ internal static long downloadSpeed;
+ internal static long uploadSpeed;
+ }
+}
\ No newline at end of file
diff --git a/RRQMSocket.FileTransfer/Common/TransferCollection.cs b/RRQMSocket.FileTransfer/Common/TransferCollection.cs
new file mode 100644
index 000000000..38d847c6f
--- /dev/null
+++ b/RRQMSocket.FileTransfer/Common/TransferCollection.cs
@@ -0,0 +1,92 @@
+//------------------------------------------------------------------------------
+// 此代码版权(除特别声明或在RRQMCore.XREF命名空间的代码)归作者本人若汝棋茗所有
+// 源代码使用协议遵循本仓库的开源协议及附加协议,若本仓库没有设置,则按MIT开源协议授权
+// CSDN博客:https://blog.csdn.net/qq_40374647
+// 哔哩哔哩视频:https://space.bilibili.com/94253567
+// Gitee源代码仓库:https://gitee.com/RRQM_Home
+// Github源代码仓库:https://github.com/RRQM
+// 交流QQ群:234762506
+// 感谢您的下载和使用
+//------------------------------------------------------------------------------
+//------------------------------------------------------------------------------
+using System.Collections;
+using System.Collections.Generic;
+using System.Threading.Tasks;
+
+namespace RRQMSocket.FileTransfer
+{
+ ///
+ /// 传输集合
+ ///
+ public class TransferCollection : IEnumerable
+ {
+ internal TransferCollection()
+ {
+ list = new List();
+ }
+
+ internal event RRQMMessageEventHandler OnCollectionChanged;
+
+ private List list;
+
+ ///
+ /// 返回一个循环访问集合的枚举器
+ ///
+ ///
+ public IEnumerator GetEnumerator()
+ {
+ return list.GetEnumerator();
+ }
+
+ IEnumerator IEnumerable.GetEnumerator()
+ {
+ return list.GetEnumerator();
+ }
+
+ internal void Add(UrlFileInfo fileInfo)
+ {
+ this.list.Add(fileInfo);
+ Task.Run(() =>
+ {
+ OnCollectionChanged?.Invoke(null, new MesEventArgs("添加"));
+ });
+ }
+
+ internal void Clear()
+ {
+ this.list.Clear();
+ Task.Run(() =>
+ {
+ OnCollectionChanged?.Invoke(null, new MesEventArgs("清空"));
+ });
+ }
+
+ internal bool Remove(UrlFileInfo fileInfo)
+ {
+ Task.Run(() =>
+ {
+ OnCollectionChanged?.Invoke(null, new MesEventArgs("移除"));
+ });
+ return this.list.Remove(fileInfo);
+ }
+
+ internal bool GetFirst(out UrlFileInfo fileInfo)
+ {
+ lock (this)
+ {
+ if (this.list.Count > 0)
+ {
+ fileInfo = this.list[0];
+ this.list.RemoveAt(0);
+ Task.Run(() =>
+ {
+ OnCollectionChanged?.Invoke(null, new MesEventArgs("进入传输"));
+ });
+ return true;
+ }
+ fileInfo = null;
+ return false;
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/RRQMSocket.FileTransfer/Common/TransferFileHashDictionary.cs b/RRQMSocket.FileTransfer/Common/TransferFileHashDictionary.cs
new file mode 100644
index 000000000..524f0d120
--- /dev/null
+++ b/RRQMSocket.FileTransfer/Common/TransferFileHashDictionary.cs
@@ -0,0 +1,203 @@
+//------------------------------------------------------------------------------
+// 此代码版权(除特别声明或在RRQMCore.XREF命名空间的代码)归作者本人若汝棋茗所有
+// 源代码使用协议遵循本仓库的开源协议及附加协议,若本仓库没有设置,则按MIT开源协议授权
+// CSDN博客:https://blog.csdn.net/qq_40374647
+// 哔哩哔哩视频:https://space.bilibili.com/94253567
+// Gitee源代码仓库:https://gitee.com/RRQM_Home
+// Github源代码仓库:https://github.com/RRQM
+// 交流QQ群:234762506
+// 感谢您的下载和使用
+//------------------------------------------------------------------------------
+//------------------------------------------------------------------------------
+using System.Collections.Concurrent;
+using System.IO;
+
+namespace RRQMSocket.FileTransfer
+{
+ ///
+ /// 传输文件Hash暂存字典
+ ///
+ public static class TransferFileHashDictionary
+ {
+ private static ConcurrentDictionary fileHashAndInfo = new ConcurrentDictionary();
+ private static ConcurrentDictionary filePathAndInfo = new ConcurrentDictionary();
+
+ ///
+ /// 字典存储文件Hash的最大数量,默认为10000
+ ///
+ public static int MaxCount { get; set; } = 10000;
+
+ ///
+ /// 添加文件信息
+ ///
+ ///
+ ///
+ ///
+ public static UrlFileInfo AddFile(string filePath, bool breakpointResume = true)
+ {
+ UrlFileInfo urlFileInfo = new UrlFileInfo();
+ using (FileStream stream = File.OpenRead(filePath))
+ {
+ urlFileInfo.FilePath = filePath;
+ urlFileInfo.FileLength = stream.Length;
+ urlFileInfo.FileName = Path.GetFileName(filePath);
+ if (breakpointResume)
+ {
+ urlFileInfo.FileHash = FileHashGenerator.GetFileHash(stream);
+ }
+ }
+ AddFile(urlFileInfo);
+ return urlFileInfo;
+ }
+
+ ///
+ /// 添加文件信息
+ ///
+ ///
+ public static void AddFile(UrlFileInfo urlFileInfo)
+ {
+ if (urlFileInfo == null)
+ {
+ return;
+ }
+ filePathAndInfo.AddOrUpdate(urlFileInfo.FilePath, urlFileInfo, (key, oldValue) =>
+ {
+ return urlFileInfo;
+ });
+
+ if (!string.IsNullOrEmpty(urlFileInfo.FileHash))
+ {
+ fileHashAndInfo.AddOrUpdate(urlFileInfo.FileHash, urlFileInfo, (key, oldValue) =>
+ {
+ return urlFileInfo;
+ });
+ }
+
+ if (filePathAndInfo.Count > MaxCount)
+ {
+ foreach (var item in filePathAndInfo.Keys)
+ {
+ if (filePathAndInfo.TryRemove(item, out _))
+ {
+ break;
+ }
+ }
+ }
+
+ if (fileHashAndInfo.Count > MaxCount)
+ {
+ foreach (var item in fileHashAndInfo.Keys)
+ {
+ if (fileHashAndInfo.TryRemove(item, out _))
+ {
+ break;
+ }
+ }
+ }
+ }
+
+ ///
+ /// 清除全部
+ ///
+ public static void ClearDictionary()
+ {
+ if (filePathAndInfo == null)
+ {
+ return;
+ }
+ filePathAndInfo.Clear();
+ }
+
+ ///
+ /// 获取文件信息
+ ///
+ ///
+ ///
+ ///
+ ///
+ public static bool GetFileInfo(string filePath, out UrlFileInfo urlFileInfo, bool breakpointResume)
+ {
+ if (filePathAndInfo == null)
+ {
+ urlFileInfo = null;
+ return false;
+ }
+ if (filePathAndInfo.ContainsKey(filePath))
+ {
+ urlFileInfo = filePathAndInfo[filePath];
+ if (File.Exists(filePath))
+ {
+ using (FileStream stream = File.OpenRead(filePath))
+ {
+ if (urlFileInfo.FileLength == stream.Length)
+ {
+ if (breakpointResume && urlFileInfo.FileHash == null)
+ {
+ urlFileInfo.FileHash = FileHashGenerator.GetFileHash(stream);
+ AddFile(urlFileInfo);
+ }
+ return true;
+ }
+ }
+ }
+ }
+
+ urlFileInfo = null;
+ return false;
+ }
+
+ ///
+ /// 通过FileHash获取文件信息
+ ///
+ ///
+ ///
+ ///
+ public static bool GetFileInfoFromHash(string fileHash, out UrlFileInfo urlFileInfo)
+ {
+ if (fileHashAndInfo == null)
+ {
+ urlFileInfo = null;
+ return false;
+ }
+ if (string.IsNullOrEmpty(fileHash))
+ {
+ urlFileInfo = null;
+ return false;
+ }
+
+ if (fileHashAndInfo.TryGetValue(fileHash, out urlFileInfo))
+ {
+ if (urlFileInfo.FileHash == fileHash)
+ {
+ if (File.Exists(urlFileInfo.FilePath))
+ {
+ using (FileStream stream = File.OpenRead(urlFileInfo.FilePath))
+ {
+ if (urlFileInfo.FileLength == stream.Length)
+ {
+ return true;
+ }
+ }
+ }
+ }
+ }
+
+ urlFileInfo = null;
+ return false;
+ }
+
+ ///
+ /// 移除
+ ///
+ ///
+ ///
+ public static bool Remove(string filePath)
+ {
+ if (filePathAndInfo == null)
+ {
+ return false;
+ }
+ return filePathAndInfo.TryRemove(filePath, out _);
+ }
+ }
+}
\ No newline at end of file
diff --git a/RRQMSocket.FileTransfer/Common/UrlFileInfo.cs b/RRQMSocket.FileTransfer/Common/UrlFileInfo.cs
new file mode 100644
index 000000000..9b63ab055
--- /dev/null
+++ b/RRQMSocket.FileTransfer/Common/UrlFileInfo.cs
@@ -0,0 +1,166 @@
+//------------------------------------------------------------------------------
+// 此代码版权(除特别声明或在RRQMCore.XREF命名空间的代码)归作者本人若汝棋茗所有
+// 源代码使用协议遵循本仓库的开源协议及附加协议,若本仓库没有设置,则按MIT开源协议授权
+// CSDN博客:https://blog.csdn.net/qq_40374647
+// 哔哩哔哩视频:https://space.bilibili.com/94253567
+// Gitee源代码仓库:https://gitee.com/RRQM_Home
+// Github源代码仓库:https://github.com/RRQM
+// 交流QQ群:234762506
+// 感谢您的下载和使用
+//------------------------------------------------------------------------------
+//------------------------------------------------------------------------------
+
+using System.IO;
+
+namespace RRQMSocket.FileTransfer
+{
+ ///
+ /// 文件信息类
+ ///
+ public class UrlFileInfo
+ {
+ private string saveFullPath = string.Empty;
+
+ private int timeout = 30 * 1000;
+
+ ///
+ /// 文件哈希值
+ ///
+ public string FileHash { get; internal set; }
+
+ ///
+ /// 文件大小
+ ///
+ public long FileLength { get; internal set; }
+
+ ///
+ /// 文件名
+ ///
+ public string FileName { get; internal set; }
+
+ ///
+ /// 文件路径
+ ///
+ public string FilePath { get; internal set; }
+
+ ///
+ /// 传输标识
+ ///
+ public TransferFlags Flags { get; set; }
+
+ ///
+ /// 携带消息
+ ///
+ public string Message { get; set; }
+
+ ///
+ /// 存放目录
+ ///
+ public string SaveFullPath
+ {
+ get { return saveFullPath; }
+ set
+ {
+ if (value == null)
+ {
+ value = string.Empty;
+ }
+ saveFullPath = value;
+ }
+ }
+
+ ///
+ /// 超时时间,默认30*1000 ms
+ ///
+ public int Timeout
+ {
+ get { return timeout; }
+ set { timeout = value; }
+ }
+
+ ///
+ /// 请求传输类型
+ ///
+ public TransferType TransferType { get; internal set; }
+
+ ///
+ /// 生成下载请求必要信息
+ ///
+ ///
+ ///
+ ///
+ public static UrlFileInfo CreateDownload(string path, TransferFlags flags)
+ {
+ UrlFileInfo fileInfo = new UrlFileInfo();
+ fileInfo.FilePath = path;
+ fileInfo.Flags = flags;
+ fileInfo.FileName = Path.GetFileName(path);
+ fileInfo.TransferType = TransferType.Download;
+ return fileInfo;
+ }
+
+ ///
+ /// 生成上传请求必要信息
+ ///
+ ///
+ ///
+ ///
+ public static UrlFileInfo CreateUpload(string path, TransferFlags flags)
+ {
+ UrlFileInfo fileInfo = new UrlFileInfo();
+ fileInfo.TransferType = TransferType.Upload;
+ using (FileStream stream = File.OpenRead(path))
+ {
+ fileInfo.Flags = flags;
+ fileInfo.FilePath = path;
+ if (flags.HasFlag(TransferFlags.BreakpointResume) || flags.HasFlag(TransferFlags.QuickTransfer))
+ {
+ fileInfo.FileHash = FileHashGenerator.GetFileHash(stream);
+ }
+ fileInfo.FileLength = stream.Length;
+ fileInfo.FileName = Path.GetFileName(path);
+ }
+
+ return fileInfo;
+ }
+
+ ///
+ /// 复制
+ ///
+ ///
+ public void CopyFrom(UrlFileInfo urlFileInfo)
+ {
+ this.FileHash = urlFileInfo.FileHash;
+ this.FileLength = urlFileInfo.FileLength;
+ this.FileName = urlFileInfo.FileName;
+ this.FilePath = urlFileInfo.FilePath;
+ }
+
+ ///
+ /// 判断参数是否相同
+ ///
+ ///
+ ///
+ public bool Equals(UrlFileInfo urlFileInfo)
+ {
+ if (urlFileInfo.FileHash != this.FileHash)
+ {
+ return false;
+ }
+ if (urlFileInfo.FileLength != this.FileLength)
+ {
+ return false;
+ }
+ if (urlFileInfo.FileName != this.FileName)
+ {
+ return false;
+ }
+ if (urlFileInfo.FilePath != this.FilePath)
+ {
+ return false;
+ }
+
+ return true;
+ }
+ }
+}
\ No newline at end of file
diff --git a/RRQMSocket.FileTransfer/Config/FileClientConfig.cs b/RRQMSocket.FileTransfer/Config/FileClientConfig.cs
new file mode 100644
index 000000000..18d2b0868
--- /dev/null
+++ b/RRQMSocket.FileTransfer/Config/FileClientConfig.cs
@@ -0,0 +1,85 @@
+//------------------------------------------------------------------------------
+// 此代码版权(除特别声明或在RRQMCore.XREF命名空间的代码)归作者本人若汝棋茗所有
+// 源代码使用协议遵循本仓库的开源协议及附加协议,若本仓库没有设置,则按MIT开源协议授权
+// CSDN博客:https://blog.csdn.net/qq_40374647
+// 哔哩哔哩视频:https://space.bilibili.com/94253567
+// Gitee源代码仓库:https://gitee.com/RRQM_Home
+// Github源代码仓库:https://github.com/RRQM
+// 交流QQ群:234762506
+// 感谢您的下载和使用
+//------------------------------------------------------------------------------
+//------------------------------------------------------------------------------
+using RRQMCore.Dependency;
+
+namespace RRQMSocket.FileTransfer
+{
+ ///
+ /// 文件客户端配置
+ ///
+ public class FileClientConfig : TokenClientConfig
+ {
+ ///
+ /// 构造函数
+ ///
+ public FileClientConfig()
+ {
+ this.BufferLength = 64 * 1024;
+ }
+
+ ///
+ /// 默认接收文件的存放目录
+ ///
+ public string ReceiveDirectory
+ {
+ get { return (string)GetValue(ReceiveDirectoryProperty); }
+ set
+ {
+ if (value == null)
+ {
+ value = string.Empty;
+ }
+ SetValue(ReceiveDirectoryProperty, value);
+ }
+ }
+
+ ///
+ /// 默认接收文件的存放目录, 所需类型
+ ///
+ public static readonly DependencyProperty ReceiveDirectoryProperty =
+ DependencyProperty.Register("ReceiveDirectory", typeof(string), typeof(FileClientConfig), string.Empty);
+
+ ///
+ /// 单次请求超时时间 min=5000,max=60*1000 ms
+ ///
+ public int Timeout
+ {
+ get { return (int)GetValue(TimeoutProperty); }
+ set
+ {
+ SetValue(TimeoutProperty, value);
+ }
+ }
+
+ ///
+ /// 单次请求超时时间 min=5000,max=60*1000 ms, 所需类型
+ ///
+ public static readonly DependencyProperty TimeoutProperty =
+ DependencyProperty.Register("Timeout", typeof(int), typeof(FileClientConfig), 10*1000);
+
+ ///
+ /// 数据包尺寸
+ ///
+ public int PacketSize
+ {
+ get { return (int)GetValue(PacketSizeProperty); }
+ set { SetValue(PacketSizeProperty, value); }
+ }
+
+ ///
+ /// 数据包尺寸, 所需类型
+ ///
+ [RRQMCore.Range]
+ public static readonly DependencyProperty PacketSizeProperty =
+ DependencyProperty.Register("PacketSize", typeof(int), typeof(FileClientConfig), 1024 * 1024);
+ }
+}
\ No newline at end of file
diff --git a/RRQMSocket.FileTransfer/Config/FileServiceConfig.cs b/RRQMSocket.FileTransfer/Config/FileServiceConfig.cs
new file mode 100644
index 000000000..40d0d60f0
--- /dev/null
+++ b/RRQMSocket.FileTransfer/Config/FileServiceConfig.cs
@@ -0,0 +1,59 @@
+//------------------------------------------------------------------------------
+// 此代码版权(除特别声明或在RRQMCore.XREF命名空间的代码)归作者本人若汝棋茗所有
+// 源代码使用协议遵循本仓库的开源协议及附加协议,若本仓库没有设置,则按MIT开源协议授权
+// CSDN博客:https://blog.csdn.net/qq_40374647
+// 哔哩哔哩视频:https://space.bilibili.com/94253567
+// Gitee源代码仓库:https://gitee.com/RRQM_Home
+// Github源代码仓库:https://github.com/RRQM
+// 交流QQ群:234762506
+// 感谢您的下载和使用
+//------------------------------------------------------------------------------
+//------------------------------------------------------------------------------
+using RRQMCore.Dependency;
+
+namespace RRQMSocket.FileTransfer
+{
+ ///
+ /// 文件服务器配置
+ ///
+ public class FileServiceConfig : TokenServiceConfig
+ {
+ ///
+ /// 构造函数
+ ///
+ public FileServiceConfig()
+ {
+ this.BufferLength = 64 * 1024;
+ }
+
+ ///
+ /// 最大下载速度
+ ///
+ public long MaxDownloadSpeed
+ {
+ get { return (long)GetValue(MaxDownloadSpeedProperty); }
+ set { SetValue(MaxDownloadSpeedProperty, value); }
+ }
+
+ ///
+ /// 最大下载速度, 所需类型
+ ///
+ public static readonly DependencyProperty MaxDownloadSpeedProperty =
+ DependencyProperty.Register("MaxDownloadSpeed", typeof(long), typeof(FileServiceConfig), 1024 * 1024L);
+
+ ///
+ /// 最大上传速度
+ ///
+ public long MaxUploadSpeed
+ {
+ get { return (long)GetValue(MaxUploadSpeedProperty); }
+ set { SetValue(MaxUploadSpeedProperty, value); }
+ }
+
+ ///
+ /// 最大上传速度, 所需类型
+ ///
+ public static readonly DependencyProperty MaxUploadSpeedProperty =
+ DependencyProperty.Register("MaxUploadSpeed", typeof(long), typeof(FileServiceConfig), 1024 * 1024L);
+ }
+}
\ No newline at end of file
diff --git a/RRQMSocket.FileTransfer/Delegate/DelegateCollection.cs b/RRQMSocket.FileTransfer/Delegate/DelegateCollection.cs
new file mode 100644
index 000000000..a205109a9
--- /dev/null
+++ b/RRQMSocket.FileTransfer/Delegate/DelegateCollection.cs
@@ -0,0 +1,28 @@
+//------------------------------------------------------------------------------
+// 此代码版权(除特别声明或在RRQMCore.XREF命名空间的代码)归作者本人若汝棋茗所有
+// 源代码使用协议遵循本仓库的开源协议及附加协议,若本仓库没有设置,则按MIT开源协议授权
+// CSDN博客:https://blog.csdn.net/qq_40374647
+// 哔哩哔哩视频:https://space.bilibili.com/94253567
+// Gitee源代码仓库:https://gitee.com/RRQM_Home
+// Github源代码仓库:https://github.com/RRQM
+// 交流QQ群:234762506
+// 感谢您的下载和使用
+//------------------------------------------------------------------------------
+//------------------------------------------------------------------------------
+
+namespace RRQMSocket.FileTransfer
+{
+ ///
+ /// 传输文件操作处理
+ ///
+ ///
+ ///
+ public delegate void RRQMFileOperationEventHandler(object sender, FileOperationEventArgs e);
+
+ ///
+ /// 传输文件消息
+ ///
+ ///
+ ///
+ public delegate void RRQMTransferFileMessageEventHandler(object sender, TransferFileMessageArgs e);
+}
\ No newline at end of file
diff --git a/RRQMSocket.FileTransfer/Enum/FileHashType.cs b/RRQMSocket.FileTransfer/Enum/FileHashType.cs
new file mode 100644
index 000000000..63e78a7ed
--- /dev/null
+++ b/RRQMSocket.FileTransfer/Enum/FileHashType.cs
@@ -0,0 +1,39 @@
+//------------------------------------------------------------------------------
+// 此代码版权(除特别声明或在RRQMCore.XREF命名空间的代码)归作者本人若汝棋茗所有
+// 源代码使用协议遵循本仓库的开源协议及附加协议,若本仓库没有设置,则按MIT开源协议授权
+// CSDN博客:https://blog.csdn.net/qq_40374647
+// 哔哩哔哩视频:https://space.bilibili.com/94253567
+// Gitee源代码仓库:https://gitee.com/RRQM_Home
+// Github源代码仓库:https://github.com/RRQM
+// 交流QQ群:234762506
+// 感谢您的下载和使用
+//------------------------------------------------------------------------------
+//------------------------------------------------------------------------------
+namespace RRQMSocket.FileTransfer
+{
+ ///
+ /// 文件Hash检验类型
+ ///
+ public enum FileHashType : byte
+ {
+ ///
+ /// MD5
+ ///
+ MD5,
+
+ ///
+ /// SHA1
+ ///
+ SHA1,
+
+ ///
+ /// SHA256
+ ///
+ SHA256,
+
+ ///
+ /// SHA512
+ ///
+ SHA512
+ }
+}
\ No newline at end of file
diff --git a/RRQMSocket.FileTransfer/Enum/RequestStatus.cs b/RRQMSocket.FileTransfer/Enum/RequestStatus.cs
new file mode 100644
index 000000000..9853e83d1
--- /dev/null
+++ b/RRQMSocket.FileTransfer/Enum/RequestStatus.cs
@@ -0,0 +1,34 @@
+//------------------------------------------------------------------------------
+// 此代码版权(除特别声明或在RRQMCore.XREF命名空间的代码)归作者本人若汝棋茗所有
+// 源代码使用协议遵循本仓库的开源协议及附加协议,若本仓库没有设置,则按MIT开源协议授权
+// CSDN博客:https://blog.csdn.net/qq_40374647
+// 哔哩哔哩视频:https://space.bilibili.com/94253567
+// Gitee源代码仓库:https://gitee.com/RRQM_Home
+// Github源代码仓库:https://github.com/RRQM
+// 交流QQ群:234762506
+// 感谢您的下载和使用
+//------------------------------------------------------------------------------
+//------------------------------------------------------------------------------
+namespace RRQMSocket.FileTransfer
+{
+ ///
+ /// 请求状态
+ ///
+ public enum RequestStatus : byte
+ {
+ ///
+ /// 未开始
+ ///
+ Hovering,
+
+ ///
+ /// 正在进行
+ ///
+ InProgress,
+
+ ///
+ /// 完成
+ ///
+ Finished
+ }
+}
\ No newline at end of file
diff --git a/RRQMSocket.FileTransfer/Enum/StreamOperationType.cs b/RRQMSocket.FileTransfer/Enum/StreamOperationType.cs
new file mode 100644
index 000000000..228181223
--- /dev/null
+++ b/RRQMSocket.FileTransfer/Enum/StreamOperationType.cs
@@ -0,0 +1,29 @@
+//------------------------------------------------------------------------------
+// 此代码版权(除特别声明或在RRQMCore.XREF命名空间的代码)归作者本人若汝棋茗所有
+// 源代码使用协议遵循本仓库的开源协议及附加协议,若本仓库没有设置,则按MIT开源协议授权
+// CSDN博客:https://blog.csdn.net/qq_40374647
+// 哔哩哔哩视频:https://space.bilibili.com/94253567
+// Gitee源代码仓库:https://gitee.com/RRQM_Home
+// Github源代码仓库:https://github.com/RRQM
+// 交流QQ群:234762506
+// 感谢您的下载和使用
+//------------------------------------------------------------------------------
+//------------------------------------------------------------------------------
+namespace RRQMSocket.FileTransfer
+{
+ ///
+ /// 流操作类型
+ ///
+ public enum StreamOperationType : byte
+ {
+ ///
+ /// 读
+ ///
+ Read,
+
+ ///
+ /// 写
+ ///
+ Write
+ }
+}
\ No newline at end of file
diff --git a/RRQMSocket.FileTransfer/Enum/TransferFlags.cs b/RRQMSocket.FileTransfer/Enum/TransferFlags.cs
new file mode 100644
index 000000000..4a6e1cd52
--- /dev/null
+++ b/RRQMSocket.FileTransfer/Enum/TransferFlags.cs
@@ -0,0 +1,37 @@
+//------------------------------------------------------------------------------
+// 此代码版权(除特别声明或在RRQMCore.XREF命名空间的代码)归作者本人若汝棋茗所有
+// 源代码使用协议遵循本仓库的开源协议及附加协议,若本仓库没有设置,则按MIT开源协议授权
+// CSDN博客:https://blog.csdn.net/qq_40374647
+// 哔哩哔哩视频:https://space.bilibili.com/94253567
+// Gitee源代码仓库:https://gitee.com/RRQM_Home
+// Github源代码仓库:https://github.com/RRQM
+// 交流QQ群:234762506
+// 感谢您的下载和使用
+//------------------------------------------------------------------------------
+//------------------------------------------------------------------------------
+using System;
+
+namespace RRQMSocket.FileTransfer
+{
+ ///
+ /// 传输标识
+ ///
+ [Flags]
+ public enum TransferFlags
+ {
+ ///
+ /// 无任何标识
+ ///
+ None = 0,
+
+ ///
+ /// 断点续传
+ ///
+ BreakpointResume = 1,
+
+ ///
+ /// 快速传输
+ ///
+ QuickTransfer = 2
+ }
+}
\ No newline at end of file
diff --git a/RRQMSocket.FileTransfer/Enum/TransferStatus.cs b/RRQMSocket.FileTransfer/Enum/TransferStatus.cs
new file mode 100644
index 000000000..2f9d84fa4
--- /dev/null
+++ b/RRQMSocket.FileTransfer/Enum/TransferStatus.cs
@@ -0,0 +1,44 @@
+//------------------------------------------------------------------------------
+// 此代码版权(除特别声明或在RRQMCore.XREF命名空间的代码)归作者本人若汝棋茗所有
+// 源代码使用协议遵循本仓库的开源协议及附加协议,若本仓库没有设置,则按MIT开源协议授权
+// CSDN博客:https://blog.csdn.net/qq_40374647
+// 哔哩哔哩视频:https://space.bilibili.com/94253567
+// Gitee源代码仓库:https://gitee.com/RRQM_Home
+// Github源代码仓库:https://github.com/RRQM
+// 交流QQ群:234762506
+// 感谢您的下载和使用
+//------------------------------------------------------------------------------
+//------------------------------------------------------------------------------
+namespace RRQMSocket.FileTransfer
+{
+ ///
+ /// 传输类型
+ ///
+ public enum TransferStatus
+ {
+ ///
+ /// 无下载
+ ///
+ None,
+
+ ///
+ /// 上传
+ ///
+ Upload,
+
+ ///
+ /// 下载
+ ///
+ Download,
+
+ ///
+ /// 暂停下载状态
+ ///
+ PauseDownload,
+
+ ///
+ /// 暂停上传状态
+ ///
+ PauseUpload
+ }
+}
\ No newline at end of file
diff --git a/RRQMSocket.FileTransfer/Enum/TransferType.cs b/RRQMSocket.FileTransfer/Enum/TransferType.cs
new file mode 100644
index 000000000..d8a1c0159
--- /dev/null
+++ b/RRQMSocket.FileTransfer/Enum/TransferType.cs
@@ -0,0 +1,30 @@
+//------------------------------------------------------------------------------
+// 此代码版权(除特别声明或在RRQMCore.XREF命名空间的代码)归作者本人若汝棋茗所有
+// 源代码使用协议遵循本仓库的开源协议及附加协议,若本仓库没有设置,则按MIT开源协议授权
+// CSDN博客:https://blog.csdn.net/qq_40374647
+// 哔哩哔哩视频:https://space.bilibili.com/94253567
+// Gitee源代码仓库:https://gitee.com/RRQM_Home
+// Github源代码仓库:https://github.com/RRQM
+// 交流QQ群:234762506
+// 感谢您的下载和使用
+//------------------------------------------------------------------------------
+//------------------------------------------------------------------------------
+
+namespace RRQMSocket.FileTransfer
+{
+ ///
+ /// 传输类型
+ ///
+ public enum TransferType
+ {
+ ///
+ /// 上传
+ ///
+ Upload,
+
+ ///
+ /// 下载
+ ///
+ Download,
+ }
+}
\ No newline at end of file
diff --git a/RRQMSocket.FileTransfer/EventArgs/FileEventArgs.cs b/RRQMSocket.FileTransfer/EventArgs/FileEventArgs.cs
new file mode 100644
index 000000000..04083ea11
--- /dev/null
+++ b/RRQMSocket.FileTransfer/EventArgs/FileEventArgs.cs
@@ -0,0 +1,26 @@
+//------------------------------------------------------------------------------
+// 此代码版权(除特别声明或在RRQMCore.XREF命名空间的代码)归作者本人若汝棋茗所有
+// 源代码使用协议遵循本仓库的开源协议及附加协议,若本仓库没有设置,则按MIT开源协议授权
+// CSDN博客:https://blog.csdn.net/qq_40374647
+// 哔哩哔哩视频:https://space.bilibili.com/94253567
+// Gitee源代码仓库:https://gitee.com/RRQM_Home
+// Github源代码仓库:https://github.com/RRQM
+// 交流QQ群:234762506
+// 感谢您的下载和使用
+//------------------------------------------------------------------------------
+//------------------------------------------------------------------------------
+using RRQMCore.Event;
+
+namespace RRQMSocket.FileTransfer
+{
+ ///
+ /// 文件事件
+ ///
+ public class FileEventArgs : RRQMEventArgs
+ {
+ ///
+ /// 文件信息
+ ///
+ public UrlFileInfo UrlFileInfo { get; internal set; }
+ }
+}
\ No newline at end of file
diff --git a/RRQMSocket.FileTransfer/EventArgs/FileOperationEventArgs.cs b/RRQMSocket.FileTransfer/EventArgs/FileOperationEventArgs.cs
new file mode 100644
index 000000000..aba8cbd17
--- /dev/null
+++ b/RRQMSocket.FileTransfer/EventArgs/FileOperationEventArgs.cs
@@ -0,0 +1,24 @@
+//------------------------------------------------------------------------------
+// 此代码版权(除特别声明或在RRQMCore.XREF命名空间的代码)归作者本人若汝棋茗所有
+// 源代码使用协议遵循本仓库的开源协议及附加协议,若本仓库没有设置,则按MIT开源协议授权
+// CSDN博客:https://blog.csdn.net/qq_40374647
+// 哔哩哔哩视频:https://space.bilibili.com/94253567
+// Gitee源代码仓库:https://gitee.com/RRQM_Home
+// Github源代码仓库:https://github.com/RRQM
+// 交流QQ群:234762506
+// 感谢您的下载和使用
+//------------------------------------------------------------------------------
+//------------------------------------------------------------------------------
+namespace RRQMSocket.FileTransfer
+{
+ ///
+ /// 操作文件事件类
+ ///
+ public class FileOperationEventArgs : TransferFileMessageArgs
+ {
+ ///
+ /// 是否允许操作
+ ///
+ public bool IsPermitOperation { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/RRQMSocket.FileTransfer/EventArgs/TransferFileMessageArgs.cs b/RRQMSocket.FileTransfer/EventArgs/TransferFileMessageArgs.cs
new file mode 100644
index 000000000..8e964b77d
--- /dev/null
+++ b/RRQMSocket.FileTransfer/EventArgs/TransferFileMessageArgs.cs
@@ -0,0 +1,29 @@
+//------------------------------------------------------------------------------
+// 此代码版权(除特别声明或在RRQMCore.XREF命名空间的代码)归作者本人若汝棋茗所有
+// 源代码使用协议遵循本仓库的开源协议及附加协议,若本仓库没有设置,则按MIT开源协议授权
+// CSDN博客:https://blog.csdn.net/qq_40374647
+// 哔哩哔哩视频:https://space.bilibili.com/94253567
+// Gitee源代码仓库:https://gitee.com/RRQM_Home
+// Github源代码仓库:https://github.com/RRQM
+// 交流QQ群:234762506
+// 感谢您的下载和使用
+//------------------------------------------------------------------------------
+//------------------------------------------------------------------------------
+namespace RRQMSocket.FileTransfer
+{
+ ///
+ /// 文件传输消息
+ ///
+ public class TransferFileMessageArgs : FileEventArgs
+ {
+ ///
+ /// 信息
+ ///
+ public string Message { get; internal set; }
+
+ ///
+ /// 传输类型
+ ///
+ public TransferType TransferType { get; internal set; }
+ }
+}
\ No newline at end of file
diff --git a/RRQMSocket.FileTransfer/Exceptions/RRQMTransferErrorException.cs b/RRQMSocket.FileTransfer/Exceptions/RRQMTransferErrorException.cs
new file mode 100644
index 000000000..688f354fd
--- /dev/null
+++ b/RRQMSocket.FileTransfer/Exceptions/RRQMTransferErrorException.cs
@@ -0,0 +1,48 @@
+//------------------------------------------------------------------------------
+// 此代码版权(除特别声明或在RRQMCore.XREF命名空间的代码)归作者本人若汝棋茗所有
+// 源代码使用协议遵循本仓库的开源协议及附加协议,若本仓库没有设置,则按MIT开源协议授权
+// CSDN博客:https://blog.csdn.net/qq_40374647
+// 哔哩哔哩视频:https://space.bilibili.com/94253567
+// Gitee源代码仓库:https://gitee.com/RRQM_Home
+// Github源代码仓库:https://github.com/RRQM
+// 交流QQ群:234762506
+// 感谢您的下载和使用
+//------------------------------------------------------------------------------
+//------------------------------------------------------------------------------
+using RRQMCore.Exceptions;
+
+namespace RRQMSocket.FileTransfer
+{
+ ///
+ /// 传输错误
+ ///
+
+ public class RRQMTransferErrorException : RRQMException
+ {
+ ///
+ ///
+ ///
+ public RRQMTransferErrorException() : base() { }
+
+ ///
+ ///
+ ///
+ ///
+ public RRQMTransferErrorException(string message) : base(message) { }
+
+ ///
+ ///
+ ///
+ ///
+ ///
+ public RRQMTransferErrorException(string message, System.Exception inner) : base(message, inner) { }
+
+ ///
+ ///
+ ///
+ ///
+ ///
+ protected RRQMTransferErrorException(System.Runtime.Serialization.SerializationInfo info,
+ System.Runtime.Serialization.StreamingContext context) : base(info, context) { }
+ }
+}
\ No newline at end of file
diff --git a/RRQMSocket.FileTransfer/Exceptions/RRQMTransferingException.cs b/RRQMSocket.FileTransfer/Exceptions/RRQMTransferingException.cs
new file mode 100644
index 000000000..4483a684e
--- /dev/null
+++ b/RRQMSocket.FileTransfer/Exceptions/RRQMTransferingException.cs
@@ -0,0 +1,52 @@
+//------------------------------------------------------------------------------
+// 此代码版权(除特别声明或在RRQMCore.XREF命名空间的代码)归作者本人若汝棋茗所有
+// 源代码使用协议遵循本仓库的开源协议及附加协议,若本仓库没有设置,则按MIT开源协议授权
+// CSDN博客:https://blog.csdn.net/qq_40374647
+// 哔哩哔哩视频:https://space.bilibili.com/94253567
+// Gitee源代码仓库:https://gitee.com/RRQM_Home
+// Github源代码仓库:https://github.com/RRQM
+// 交流QQ群:234762506
+// 感谢您的下载和使用
+//------------------------------------------------------------------------------
+//------------------------------------------------------------------------------
+using RRQMCore.Exceptions;
+
+namespace RRQMSocket.FileTransfer
+{
+ /*
+ 若汝棋茗
+ */
+
+ ///
+ /// 没有传输任务异常
+ ///
+
+ public class RRQMTransferingException : RRQMException
+ {
+ ///
+ ///
+ ///
+ public RRQMTransferingException() : base() { }
+
+ ///
+ ///
+ ///
+ ///
+ public RRQMTransferingException(string message) : base(message) { }
+
+ ///
+ ///
+ ///
+ ///
+ ///
+ public RRQMTransferingException(string message, System.Exception inner) : base(message, inner) { }
+
+ ///
+ ///
+ ///
+ ///
+ ///
+ protected RRQMTransferingException(System.Runtime.Serialization.SerializationInfo info,
+ System.Runtime.Serialization.StreamingContext context) : base(info, context) { }
+ }
+}
\ No newline at end of file
diff --git a/RRQMSocket.FileTransfer/Interface/IFileClient.cs b/RRQMSocket.FileTransfer/Interface/IFileClient.cs
new file mode 100644
index 000000000..f39f32ce1
--- /dev/null
+++ b/RRQMSocket.FileTransfer/Interface/IFileClient.cs
@@ -0,0 +1,40 @@
+//------------------------------------------------------------------------------
+// 此代码版权(除特别声明或在RRQMCore.XREF命名空间的代码)归作者本人若汝棋茗所有
+// 源代码使用协议遵循本仓库的开源协议及附加协议,若本仓库没有设置,则按MIT开源协议授权
+// CSDN博客:https://blog.csdn.net/qq_40374647
+// 哔哩哔哩视频:https://space.bilibili.com/94253567
+// Gitee源代码仓库:https://gitee.com/RRQM_Home
+// Github源代码仓库:https://github.com/RRQM
+// 交流QQ群:234762506
+// 感谢您的下载和使用
+//------------------------------------------------------------------------------
+//------------------------------------------------------------------------------
+
+namespace RRQMSocket.FileTransfer
+{
+ ///
+ /// 文件终端接口
+ ///
+ public interface IFileClient
+ {
+ ///
+ /// 获取当前传输文件信息
+ ///
+ UrlFileInfo TransferFileInfo { get; }
+
+ ///
+ /// 获取当前传输进度
+ ///
+ float TransferProgress { get; }
+
+ ///
+ /// 获取当前传输速度
+ ///
+ long TransferSpeed { get; }
+
+ ///
+ /// 获取当前传输状态
+ ///
+ TransferStatus TransferStatus { get; }
+ }
+}
\ No newline at end of file
diff --git a/RRQMSocket.FileTransfer/Interface/IFileService.cs b/RRQMSocket.FileTransfer/Interface/IFileService.cs
new file mode 100644
index 000000000..e09bb3db2
--- /dev/null
+++ b/RRQMSocket.FileTransfer/Interface/IFileService.cs
@@ -0,0 +1,30 @@
+//------------------------------------------------------------------------------
+// 此代码版权(除特别声明或在RRQMCore.XREF命名空间的代码)归作者本人若汝棋茗所有
+// 源代码使用协议遵循本仓库的开源协议及附加协议,若本仓库没有设置,则按MIT开源协议授权
+// CSDN博客:https://blog.csdn.net/qq_40374647
+// 哔哩哔哩视频:https://space.bilibili.com/94253567
+// Gitee源代码仓库:https://gitee.com/RRQM_Home
+// Github源代码仓库:https://github.com/RRQM
+// 交流QQ群:234762506
+// 感谢您的下载和使用
+//------------------------------------------------------------------------------
+//------------------------------------------------------------------------------
+
+namespace RRQMSocket.FileTransfer
+{
+ ///
+ /// 服务器接口
+ ///
+ public interface IFileService
+ {
+ ///
+ /// 最大下载速度
+ ///
+ long MaxDownloadSpeed { get; set; }
+
+ ///
+ /// 最大上传速度
+ ///
+ long MaxUploadSpeed { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/RRQMSocket.FileTransfer/LICENSE b/RRQMSocket.FileTransfer/LICENSE
new file mode 100644
index 000000000..5a9bb6217
--- /dev/null
+++ b/RRQMSocket.FileTransfer/LICENSE
@@ -0,0 +1,201 @@
+Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license procotol you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
diff --git a/RRQMSocket.FileTransfer/RRQM.ico b/RRQMSocket.FileTransfer/RRQM.ico
new file mode 100644
index 0000000000000000000000000000000000000000..6465fb16e389ed1804d54b368018596580c6672e
GIT binary patch
literal 249918
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