Showing preview only (310K chars total). Download the full file or copy to clipboard to get everything.
Repository: passiony/kcp-unity
Branch: master
Commit: 4350fcc2fd77
Files: 143
Total size: 271.8 KB
Directory structure:
gitextract_xqrk26b3/
├── .gitignore
├── Assets/
│ ├── Plugins/
│ │ ├── Kcp/
│ │ │ ├── Android/
│ │ │ │ ├── libs/
│ │ │ │ │ ├── armeabi-v7a/
│ │ │ │ │ │ └── libkcp.so.meta
│ │ │ │ │ ├── armeabi-v7a.meta
│ │ │ │ │ ├── x86/
│ │ │ │ │ │ └── libkcp.so.meta
│ │ │ │ │ └── x86.meta
│ │ │ │ └── libs.meta
│ │ │ ├── Android.meta
│ │ │ ├── MacOS/
│ │ │ │ ├── kcp.bundle/
│ │ │ │ │ ├── Contents/
│ │ │ │ │ │ ├── MacOS/
│ │ │ │ │ │ │ ├── kcp
│ │ │ │ │ │ │ └── kcp.meta
│ │ │ │ │ │ └── MacOS.meta
│ │ │ │ │ └── Contents.meta
│ │ │ │ └── kcp.bundle.meta
│ │ │ ├── MacOS.meta
│ │ │ ├── iOS/
│ │ │ │ ├── kcp.a
│ │ │ │ └── kcp.a.meta
│ │ │ ├── iOS.meta
│ │ │ ├── x86/
│ │ │ │ └── kcp.dll.meta
│ │ │ ├── x86.meta
│ │ │ ├── x86_64/
│ │ │ │ └── kcp.dll.meta
│ │ │ └── x86_64.meta
│ │ └── Kcp.meta
│ ├── Plugins.meta
│ ├── Scenes/
│ │ ├── Client.unity
│ │ ├── Client.unity.meta
│ │ ├── Server.unity
│ │ └── Server.unity.meta
│ ├── Scenes.meta
│ ├── Scripts/
│ │ ├── Helper/
│ │ │ ├── ByteHelper.cs
│ │ │ ├── ByteHelper.cs.meta
│ │ │ ├── MonoSingleton.cs
│ │ │ ├── MonoSingleton.cs.meta
│ │ │ ├── NetworkHelper.cs
│ │ │ ├── NetworkHelper.cs.meta
│ │ │ ├── RandomHelper.cs
│ │ │ ├── RandomHelper.cs.meta
│ │ │ ├── TimeHelper.cs
│ │ │ └── TimeHelper.cs.meta
│ │ ├── Helper.meta
│ │ ├── Network/
│ │ │ ├── AChannel.cs
│ │ │ ├── AChannel.cs.meta
│ │ │ ├── AService.cs
│ │ │ ├── AService.cs.meta
│ │ │ ├── ClientManager.cs
│ │ │ ├── ClientManager.cs.meta
│ │ │ ├── Core/
│ │ │ │ ├── KCP/
│ │ │ │ │ ├── KCP.cs
│ │ │ │ │ ├── KCP.cs.meta
│ │ │ │ │ ├── KChannel.cs
│ │ │ │ │ ├── KChannel.cs.meta
│ │ │ │ │ ├── KService.cs
│ │ │ │ │ ├── KService.cs.meta
│ │ │ │ │ ├── KcpDll.cs
│ │ │ │ │ └── KcpDll.cs.meta
│ │ │ │ ├── KCP.meta
│ │ │ │ ├── TCP/
│ │ │ │ │ ├── PacketParser.cs
│ │ │ │ │ ├── PacketParser.cs.meta
│ │ │ │ │ ├── TChannel.cs
│ │ │ │ │ ├── TChannel.cs.meta
│ │ │ │ │ ├── TChannelConnector.cs
│ │ │ │ │ ├── TChannelConnector.cs.meta
│ │ │ │ │ ├── TChannelServer.cs
│ │ │ │ │ ├── TChannelServer.cs.meta
│ │ │ │ │ ├── TService.cs
│ │ │ │ │ ├── TService.cs.meta
│ │ │ │ │ ├── TServiceServer.cs
│ │ │ │ │ └── TServiceServer.cs.meta
│ │ │ │ ├── TCP.meta
│ │ │ │ ├── WebSocket/
│ │ │ │ │ ├── WChannel.cs
│ │ │ │ │ ├── WChannel.cs.meta
│ │ │ │ │ ├── WService.cs
│ │ │ │ │ └── WService.cs.meta
│ │ │ │ └── WebSocket.meta
│ │ │ ├── Core.meta
│ │ │ ├── INetworkManager.cs
│ │ │ ├── INetworkManager.cs.meta
│ │ │ ├── Message/
│ │ │ │ ├── Circularbuffer.cs
│ │ │ │ ├── Circularbuffer.cs.meta
│ │ │ │ ├── ErrorCode.cs
│ │ │ │ ├── ErrorCode.cs.meta
│ │ │ │ ├── IMessage.cs
│ │ │ │ ├── IMessage.cs.meta
│ │ │ │ ├── IMessageDispatcher.cs
│ │ │ │ ├── IMessageDispatcher.cs.meta
│ │ │ │ ├── IMessagePacker.cs
│ │ │ │ ├── IMessagePacker.cs.meta
│ │ │ │ ├── MessageInfo.cs
│ │ │ │ ├── MessageInfo.cs.meta
│ │ │ │ ├── MessagePool.cs
│ │ │ │ ├── MessagePool.cs.meta
│ │ │ │ ├── Opcode.cs
│ │ │ │ ├── Opcode.cs.meta
│ │ │ │ ├── OuterMessageDispatcher.cs
│ │ │ │ ├── OuterMessageDispatcher.cs.meta
│ │ │ │ ├── ProtobufPacker.cs
│ │ │ │ ├── ProtobufPacker.cs.meta
│ │ │ │ ├── RecyclableMemoryStream/
│ │ │ │ │ ├── Events.cs
│ │ │ │ │ ├── Events.cs.meta
│ │ │ │ │ ├── OneThreadSynchronizationContext.cs
│ │ │ │ │ ├── OneThreadSynchronizationContext.cs.meta
│ │ │ │ │ ├── RecyclableMemoryStream.cs
│ │ │ │ │ ├── RecyclableMemoryStream.cs.meta
│ │ │ │ │ ├── RecyclableMemoryStreamManager.cs
│ │ │ │ │ └── RecyclableMemoryStreamManager.cs.meta
│ │ │ │ ├── RecyclableMemoryStream.meta
│ │ │ │ ├── Session.cs
│ │ │ │ ├── Session.cs.meta
│ │ │ │ ├── SessionConnector.cs
│ │ │ │ ├── SessionConnector.cs.meta
│ │ │ │ ├── SessionServer.cs
│ │ │ │ └── SessionServer.cs.meta
│ │ │ ├── Message.meta
│ │ │ ├── ServerManager.cs
│ │ │ └── ServerManager.cs.meta
│ │ ├── Network.meta
│ │ ├── TestClient.cs
│ │ ├── TestClient.cs.meta
│ │ ├── TestServer.cs
│ │ └── TestServer.cs.meta
│ └── Scripts.meta
├── ProjectSettings/
│ ├── AudioManager.asset
│ ├── AutoStreamingSettings.asset
│ ├── ClusterInputManager.asset
│ ├── DynamicsManager.asset
│ ├── EditorBuildSettings.asset
│ ├── EditorSettings.asset
│ ├── GraphicsSettings.asset
│ ├── InputManager.asset
│ ├── MemorySettings.asset
│ ├── NavMeshAreas.asset
│ ├── NetworkManager.asset
│ ├── PackageManagerSettings.asset
│ ├── Physics2DSettings.asset
│ ├── PresetManager.asset
│ ├── ProjectSettings.asset
│ ├── ProjectVersion.txt
│ ├── QualitySettings.asset
│ ├── SceneTemplateSettings.json
│ ├── TagManager.asset
│ ├── TimeManager.asset
│ ├── UnityConnectSettings.asset
│ ├── VFXManager.asset
│ ├── VersionControlSettings.asset
│ └── boot.config
└── README.md
================================================
FILE CONTENTS
================================================
================================================
FILE: .gitignore
================================================
# =============== #
# Unity generated #
# =============== #
[Tt]emp/
[Oo]bj/
[Bb]uild
[Ll]ibrary/
[Gg]oogle/
[Ll]ogs/
[Pp]ackages/
sysinfo.txt
*.stackdump
StreamingAssets/
# ===================================== #
# Visual Studio / MonoDevelop generated #
# ===================================== #
[Ee]xported[Oo]bj/
.vs/
.idea/
.vscode/
/*.userprefs
/*.csproj
/*.pidb
/*.suo
/*.sln*
/*.user
/*.unityproj
/*.booproj
/*.pdb
# ============ #
# OS generated #
# ============ #
.DS_Store*
._*
.Spotlight-V100
.Trashes
Icon?
ehthumbs.db
[Tt]humbs.db
*.apk
================================================
FILE: Assets/Plugins/Kcp/Android/libs/armeabi-v7a/libkcp.so.meta
================================================
fileFormatVersion: 2
guid: 8e03e31ef66b1d340bfd9de539878633
timeCreated: 1530266293
licenseType: Pro
PluginImporter:
serializedVersion: 2
iconMap: {}
executionOrder: {}
isPreloaded: 0
isOverridable: 0
platformData:
data:
first:
Android: Android
second:
enabled: 1
settings:
CPU: ARMv7
data:
first:
Any:
second:
enabled: 0
settings: {}
data:
first:
Editor: Editor
second:
enabled: 0
settings:
DefaultValueInitialized: true
userData:
assetBundleName:
assetBundleVariant:
================================================
FILE: Assets/Plugins/Kcp/Android/libs/armeabi-v7a.meta
================================================
fileFormatVersion: 2
guid: 4b9de99f882e1334f88d3fffa436fe26
folderAsset: yes
timeCreated: 1529980199
licenseType: Pro
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:
================================================
FILE: Assets/Plugins/Kcp/Android/libs/x86/libkcp.so.meta
================================================
fileFormatVersion: 2
guid: 3869fe202d9b7494cbf94cbd4c9ae4c5
timeCreated: 1530266298
licenseType: Pro
PluginImporter:
serializedVersion: 2
iconMap: {}
executionOrder: {}
isPreloaded: 0
isOverridable: 0
platformData:
data:
first:
Android: Android
second:
enabled: 1
settings:
CPU: x86
data:
first:
Any:
second:
enabled: 0
settings: {}
data:
first:
Editor: Editor
second:
enabled: 0
settings:
DefaultValueInitialized: true
userData:
assetBundleName:
assetBundleVariant:
================================================
FILE: Assets/Plugins/Kcp/Android/libs/x86.meta
================================================
fileFormatVersion: 2
guid: af440bcca3a80614185db5d493411e3e
folderAsset: yes
timeCreated: 1529980199
licenseType: Pro
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:
================================================
FILE: Assets/Plugins/Kcp/Android/libs.meta
================================================
fileFormatVersion: 2
guid: e683bde7d2130ef4e9cd605a119c319e
folderAsset: yes
timeCreated: 1529980199
licenseType: Pro
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:
================================================
FILE: Assets/Plugins/Kcp/Android.meta
================================================
fileFormatVersion: 2
guid: 89f91d9886713c242b08fc47677c6cd6
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
================================================
FILE: Assets/Plugins/Kcp/MacOS/kcp.bundle/Contents/MacOS/kcp.meta
================================================
fileFormatVersion: 2
guid: ca685b77470a94b838156da4c499b38a
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
================================================
FILE: Assets/Plugins/Kcp/MacOS/kcp.bundle/Contents/MacOS.meta
================================================
fileFormatVersion: 2
guid: 957c90d60724445898ad398879db8b83
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
================================================
FILE: Assets/Plugins/Kcp/MacOS/kcp.bundle/Contents.meta
================================================
fileFormatVersion: 2
guid: 19bc16a76b8ac49e6bafebcacef13384
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
================================================
FILE: Assets/Plugins/Kcp/MacOS/kcp.bundle.meta
================================================
fileFormatVersion: 2
guid: eb0cef4b32a23b24688b70b0d9b607e6
folderAsset: yes
PluginImporter:
externalObjects: {}
serializedVersion: 2
iconMap: {}
executionOrder: {}
isPreloaded: 0
isOverridable: 0
platformData:
- first:
'': OSXIntel
second:
enabled: 1
settings: {}
- first:
'': OSXIntel64
second:
enabled: 1
settings: {}
- first:
Any:
second:
enabled: 0
settings: {}
- first:
Editor: Editor
second:
enabled: 1
settings:
DefaultValueInitialized: true
- first:
Standalone: OSXUniversal
second:
enabled: 1
settings: {}
userData:
assetBundleName:
assetBundleVariant:
================================================
FILE: Assets/Plugins/Kcp/MacOS.meta
================================================
fileFormatVersion: 2
guid: 747c6b8c8af2e794da1e88402d7cc394
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
================================================
FILE: Assets/Plugins/Kcp/iOS/kcp.a.meta
================================================
fileFormatVersion: 2
guid: 81c5e3645249f404986889388c75e6de
PluginImporter:
externalObjects: {}
serializedVersion: 2
iconMap: {}
executionOrder: {}
isPreloaded: 0
isOverridable: 0
platformData:
- first:
Any:
second:
enabled: 0
settings: {}
- first:
Editor: Editor
second:
enabled: 0
settings:
DefaultValueInitialized: true
- first:
iPhone: iOS
second:
enabled: 1
settings: {}
userData:
assetBundleName:
assetBundleVariant:
================================================
FILE: Assets/Plugins/Kcp/iOS.meta
================================================
fileFormatVersion: 2
guid: fd0f4e125884b09478cd65e157e73225
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
================================================
FILE: Assets/Plugins/Kcp/x86/kcp.dll.meta
================================================
fileFormatVersion: 2
guid: 5163e0119c1604a43adbc28ec6fb277e
timeCreated: 1530266315
licenseType: Pro
PluginImporter:
serializedVersion: 2
iconMap: {}
executionOrder: {}
isPreloaded: 0
isOverridable: 0
platformData:
data:
first:
'': Any
second:
enabled: 0
settings:
Exclude Android: 1
Exclude Editor: 1
Exclude Linux: 0
Exclude Linux64: 0
Exclude LinuxUniversal: 0
Exclude OSXIntel: 0
Exclude OSXIntel64: 0
Exclude OSXUniversal: 0
Exclude Win: 0
Exclude Win64: 1
data:
first:
Android: Android
second:
enabled: 0
settings:
CPU: ARMv7
data:
first:
Any:
second:
enabled: 0
settings: {}
data:
first:
Editor: Editor
second:
enabled: 0
settings:
CPU: x86
DefaultValueInitialized: true
OS: AnyOS
data:
first:
Facebook: Win
second:
enabled: 1
settings:
CPU: AnyCPU
data:
first:
Facebook: Win64
second:
enabled: 0
settings:
CPU: None
data:
first:
Standalone: Linux
second:
enabled: 1
settings:
CPU: x86
data:
first:
Standalone: Linux64
second:
enabled: 1
settings:
CPU: None
data:
first:
Standalone: LinuxUniversal
second:
enabled: 1
settings:
CPU: AnyCPU
data:
first:
Standalone: OSXIntel
second:
enabled: 1
settings:
CPU: AnyCPU
data:
first:
Standalone: OSXIntel64
second:
enabled: 1
settings:
CPU: None
data:
first:
Standalone: OSXUniversal
second:
enabled: 1
settings:
CPU: AnyCPU
data:
first:
Standalone: Win
second:
enabled: 1
settings:
CPU: AnyCPU
data:
first:
Standalone: Win64
second:
enabled: 0
settings:
CPU: None
userData:
assetBundleName:
assetBundleVariant:
================================================
FILE: Assets/Plugins/Kcp/x86.meta
================================================
fileFormatVersion: 2
guid: 93e339b4ca47c8f4b81c2d9742800ec5
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
================================================
FILE: Assets/Plugins/Kcp/x86_64/kcp.dll.meta
================================================
fileFormatVersion: 2
guid: 803f7857fdb47b34fbe04eda49b8aa85
PluginImporter:
externalObjects: {}
serializedVersion: 2
iconMap: {}
executionOrder: {}
isPreloaded: 0
isOverridable: 0
platformData:
- first:
'': Any
second:
enabled: 0
settings:
Exclude Android: 1
Exclude Editor: 0
Exclude Linux: 0
Exclude Linux64: 0
Exclude LinuxUniversal: 0
Exclude OSXIntel: 1
Exclude OSXIntel64: 1
Exclude OSXUniversal: 0
Exclude Win: 1
Exclude Win64: 0
- first:
Android: Android
second:
enabled: 0
settings:
CPU: ARMv7
- first:
Any:
second:
enabled: 0
settings: {}
- first:
Editor: Editor
second:
enabled: 1
settings:
CPU: x86_64
DefaultValueInitialized: true
OS: Windows
- first:
Facebook: Win
second:
enabled: 0
settings:
CPU: None
- first:
Facebook: Win64
second:
enabled: 1
settings:
CPU: AnyCPU
- first:
Standalone: Linux
second:
enabled: 1
settings:
CPU: None
- first:
Standalone: Linux64
second:
enabled: 1
settings:
CPU: x86_64
- first:
Standalone: LinuxUniversal
second:
enabled: 1
settings:
CPU: AnyCPU
- first:
Standalone: OSXIntel
second:
enabled: 0
settings:
CPU: None
- first:
Standalone: OSXIntel64
second:
enabled: 0
settings:
CPU: AnyCPU
- first:
Standalone: OSXUniversal
second:
enabled: 1
settings:
CPU: None
- first:
Standalone: Win
second:
enabled: 0
settings:
CPU: None
- first:
Standalone: Win64
second:
enabled: 1
settings:
CPU: AnyCPU
userData:
assetBundleName:
assetBundleVariant:
================================================
FILE: Assets/Plugins/Kcp/x86_64.meta
================================================
fileFormatVersion: 2
guid: 06020764b763c6647b21f6933162724f
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
================================================
FILE: Assets/Plugins/Kcp.meta
================================================
fileFormatVersion: 2
guid: 3c6e92a7004dbcd45bed3397705d35bd
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
================================================
FILE: Assets/Plugins.meta
================================================
fileFormatVersion: 2
guid: a20cd3483a2a77b4bb8d9638ea3dde5f
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
================================================
FILE: Assets/Scenes/Client.unity
================================================
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!29 &1
OcclusionCullingSettings:
m_ObjectHideFlags: 0
serializedVersion: 2
m_OcclusionBakeSettings:
smallestOccluder: 5
smallestHole: 0.25
backfaceThreshold: 100
m_SceneGUID: 00000000000000000000000000000000
m_OcclusionCullingData: {fileID: 0}
--- !u!104 &2
RenderSettings:
m_ObjectHideFlags: 0
serializedVersion: 9
m_Fog: 0
m_FogColor: {r: 0.5, g: 0.5, b: 0.5, a: 1}
m_FogMode: 3
m_FogDensity: 0.01
m_LinearFogStart: 0
m_LinearFogEnd: 300
m_AmbientSkyColor: {r: 0.212, g: 0.227, b: 0.259, a: 1}
m_AmbientEquatorColor: {r: 0.114, g: 0.125, b: 0.133, a: 1}
m_AmbientGroundColor: {r: 0.047, g: 0.043, b: 0.035, a: 1}
m_AmbientIntensity: 1
m_AmbientMode: 3
m_SubtractiveShadowColor: {r: 0.42, g: 0.478, b: 0.627, a: 1}
m_SkyboxMaterial: {fileID: 0}
m_HaloStrength: 0.5
m_FlareStrength: 1
m_FlareFadeSpeed: 3
m_HaloTexture: {fileID: 0}
m_SpotCookie: {fileID: 10001, guid: 0000000000000000e000000000000000, type: 0}
m_DefaultReflectionMode: 0
m_DefaultReflectionResolution: 128
m_ReflectionBounces: 1
m_ReflectionIntensity: 1
m_CustomReflection: {fileID: 0}
m_Sun: {fileID: 0}
m_IndirectSpecularColor: {r: 0, g: 0, b: 0, a: 1}
m_UseRadianceAmbientProbe: 0
--- !u!157 &3
LightmapSettings:
m_ObjectHideFlags: 0
serializedVersion: 11
m_GIWorkflowMode: 1
m_GISettings:
serializedVersion: 2
m_BounceScale: 1
m_IndirectOutputScale: 1
m_AlbedoBoost: 1
m_EnvironmentLightingMode: 0
m_EnableBakedLightmaps: 0
m_EnableRealtimeLightmaps: 0
m_LightmapEditorSettings:
serializedVersion: 10
m_Resolution: 2
m_BakeResolution: 40
m_AtlasSize: 1024
m_AO: 0
m_AOMaxDistance: 1
m_CompAOExponent: 1
m_CompAOExponentDirect: 0
m_Padding: 2
m_LightmapParameters: {fileID: 0}
m_LightmapsBakeMode: 1
m_TextureCompression: 1
m_FinalGather: 0
m_FinalGatherFiltering: 1
m_FinalGatherRayCount: 256
m_ReflectionCompression: 2
m_MixedBakeMode: 2
m_BakeBackend: 0
m_PVRSampling: 1
m_PVRDirectSampleCount: 32
m_PVRSampleCount: 500
m_PVRBounces: 2
m_PVRFilterTypeDirect: 0
m_PVRFilterTypeIndirect: 0
m_PVRFilterTypeAO: 0
m_PVRFilteringMode: 1
m_PVRCulling: 1
m_PVRFilteringGaussRadiusDirect: 1
m_PVRFilteringGaussRadiusIndirect: 5
m_PVRFilteringGaussRadiusAO: 2
m_PVRFilteringAtrousPositionSigmaDirect: 0.5
m_PVRFilteringAtrousPositionSigmaIndirect: 2
m_PVRFilteringAtrousPositionSigmaAO: 1
m_ShowResolutionOverlay: 1
m_LightingDataAsset: {fileID: 0}
m_UseShadowmask: 1
--- !u!196 &4
NavMeshSettings:
serializedVersion: 2
m_ObjectHideFlags: 0
m_BuildSettings:
serializedVersion: 2
agentTypeID: 0
agentRadius: 0.5
agentHeight: 2
agentSlope: 45
agentClimb: 0.4
ledgeDropHeight: 0
maxJumpAcrossDistance: 0
minRegionArea: 2
manualCellSize: 0
cellSize: 0.16666667
manualTileSize: 0
tileSize: 256
accuratePlacement: 0
debug:
m_Flags: 0
m_NavMeshData: {fileID: 0}
--- !u!1 &519420028
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 519420032}
- component: {fileID: 519420031}
- component: {fileID: 519420029}
- component: {fileID: 519420033}
- component: {fileID: 519420030}
m_Layer: 0
m_Name: Main Camera
m_TagString: MainCamera
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!81 &519420029
AudioListener:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 519420028}
m_Enabled: 1
--- !u!114 &519420030
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 519420028}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: c47d1a2e288e53f4285b397665f9a1dc, type: 3}
m_Name:
m_EditorClassIdentifier:
--- !u!20 &519420031
Camera:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 519420028}
m_Enabled: 1
serializedVersion: 2
m_ClearFlags: 2
m_BackGroundColor: {r: 0.19215687, g: 0.3019608, b: 0.4745098, a: 0}
m_projectionMatrixMode: 1
m_SensorSize: {x: 36, y: 24}
m_LensShift: {x: 0, y: 0}
m_GateFitMode: 2
m_FocalLength: 50
m_NormalizedViewPortRect:
serializedVersion: 2
x: 0
y: 0
width: 1
height: 1
near clip plane: 0.3
far clip plane: 1000
field of view: 60
orthographic: 1
orthographic size: 5
m_Depth: -1
m_CullingMask:
serializedVersion: 2
m_Bits: 4294967295
m_RenderingPath: -1
m_TargetTexture: {fileID: 0}
m_TargetDisplay: 0
m_TargetEye: 0
m_HDR: 1
m_AllowMSAA: 0
m_AllowDynamicResolution: 0
m_ForceIntoRT: 0
m_OcclusionCulling: 0
m_StereoConvergence: 10
m_StereoSeparation: 0.022
--- !u!4 &519420032
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 519420028}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: -10}
m_LocalScale: {x: 1, y: 1, z: 1}
m_Children: []
m_Father: {fileID: 0}
m_RootOrder: 0
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!114 &519420033
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 519420028}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 151d2db7aab5bc8438bc039443ba0e3b, type: 3}
m_Name:
m_EditorClassIdentifier:
Protocol: 1
================================================
FILE: Assets/Scenes/Client.unity.meta
================================================
fileFormatVersion: 2
guid: 53e18807e282965479d061608139b64b
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
================================================
FILE: Assets/Scenes/Server.unity
================================================
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!29 &1
OcclusionCullingSettings:
m_ObjectHideFlags: 0
serializedVersion: 2
m_OcclusionBakeSettings:
smallestOccluder: 5
smallestHole: 0.25
backfaceThreshold: 100
m_SceneGUID: 00000000000000000000000000000000
m_OcclusionCullingData: {fileID: 0}
--- !u!104 &2
RenderSettings:
m_ObjectHideFlags: 0
serializedVersion: 9
m_Fog: 0
m_FogColor: {r: 0.5, g: 0.5, b: 0.5, a: 1}
m_FogMode: 3
m_FogDensity: 0.01
m_LinearFogStart: 0
m_LinearFogEnd: 300
m_AmbientSkyColor: {r: 0.212, g: 0.227, b: 0.259, a: 1}
m_AmbientEquatorColor: {r: 0.114, g: 0.125, b: 0.133, a: 1}
m_AmbientGroundColor: {r: 0.047, g: 0.043, b: 0.035, a: 1}
m_AmbientIntensity: 1
m_AmbientMode: 3
m_SubtractiveShadowColor: {r: 0.42, g: 0.478, b: 0.627, a: 1}
m_SkyboxMaterial: {fileID: 0}
m_HaloStrength: 0.5
m_FlareStrength: 1
m_FlareFadeSpeed: 3
m_HaloTexture: {fileID: 0}
m_SpotCookie: {fileID: 10001, guid: 0000000000000000e000000000000000, type: 0}
m_DefaultReflectionMode: 0
m_DefaultReflectionResolution: 128
m_ReflectionBounces: 1
m_ReflectionIntensity: 1
m_CustomReflection: {fileID: 0}
m_Sun: {fileID: 0}
m_IndirectSpecularColor: {r: 0, g: 0, b: 0, a: 1}
m_UseRadianceAmbientProbe: 0
--- !u!157 &3
LightmapSettings:
m_ObjectHideFlags: 0
serializedVersion: 12
m_GIWorkflowMode: 1
m_GISettings:
serializedVersion: 2
m_BounceScale: 1
m_IndirectOutputScale: 1
m_AlbedoBoost: 1
m_EnvironmentLightingMode: 0
m_EnableBakedLightmaps: 0
m_EnableRealtimeLightmaps: 0
m_LightmapEditorSettings:
serializedVersion: 12
m_Resolution: 2
m_BakeResolution: 40
m_AtlasSize: 1024
m_AO: 0
m_AOMaxDistance: 1
m_CompAOExponent: 1
m_CompAOExponentDirect: 0
m_ExtractAmbientOcclusion: 0
m_Padding: 2
m_LightmapParameters: {fileID: 0}
m_LightmapsBakeMode: 1
m_TextureCompression: 1
m_FinalGather: 0
m_FinalGatherFiltering: 1
m_FinalGatherRayCount: 256
m_ReflectionCompression: 2
m_MixedBakeMode: 2
m_BakeBackend: 1
m_PVRSampling: 1
m_PVRDirectSampleCount: 32
m_PVRSampleCount: 512
m_PVRBounces: 2
m_PVREnvironmentSampleCount: 256
m_PVREnvironmentReferencePointCount: 2048
m_PVRFilteringMode: 1
m_PVRDenoiserTypeDirect: 1
m_PVRDenoiserTypeIndirect: 1
m_PVRDenoiserTypeAO: 1
m_PVRFilterTypeDirect: 0
m_PVRFilterTypeIndirect: 0
m_PVRFilterTypeAO: 0
m_PVREnvironmentMIS: 1
m_PVRCulling: 1
m_PVRFilteringGaussRadiusDirect: 1
m_PVRFilteringGaussRadiusIndirect: 5
m_PVRFilteringGaussRadiusAO: 2
m_PVRFilteringAtrousPositionSigmaDirect: 0.5
m_PVRFilteringAtrousPositionSigmaIndirect: 2
m_PVRFilteringAtrousPositionSigmaAO: 1
m_ExportTrainingData: 0
m_TrainingDataDestination: TrainingData
m_LightProbeSampleCountMultiplier: 4
m_LightingDataAsset: {fileID: 0}
m_LightingSettings: {fileID: 0}
--- !u!196 &4
NavMeshSettings:
serializedVersion: 2
m_ObjectHideFlags: 0
m_BuildSettings:
serializedVersion: 2
agentTypeID: 0
agentRadius: 0.5
agentHeight: 2
agentSlope: 45
agentClimb: 0.4
ledgeDropHeight: 0
maxJumpAcrossDistance: 0
minRegionArea: 2
manualCellSize: 0
cellSize: 0.16666667
manualTileSize: 0
tileSize: 256
accuratePlacement: 0
maxJobWorkers: 0
preserveTilesOutsideBounds: 0
debug:
m_Flags: 0
m_NavMeshData: {fileID: 0}
--- !u!1 &2029809421
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 2029809422}
- component: {fileID: 2029809424}
- component: {fileID: 2029809423}
m_Layer: 0
m_Name: ServerManager
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!4 &2029809422
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 2029809421}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 0}
m_RootOrder: 0
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!114 &2029809423
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 2029809421}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 8518a6a6d5ca49ecb048613cc3a03e07, type: 3}
m_Name:
m_EditorClassIdentifier:
--- !u!114 &2029809424
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 2029809421}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 84fd225f324f42999874057579220d14, type: 3}
m_Name:
m_EditorClassIdentifier:
================================================
FILE: Assets/Scenes/Server.unity.meta
================================================
fileFormatVersion: 2
guid: 7a58935d2e567f043835f59be74400f6
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
================================================
FILE: Assets/Scenes.meta
================================================
fileFormatVersion: 2
guid: e865c368c8aa84b4783f03af294abb01
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
================================================
FILE: Assets/Scripts/Helper/ByteHelper.cs
================================================
using System.Text;
namespace UNetwork
{
public static class ByteHelper
{
public static string ToHex(this byte b)
{
return b.ToString("X2");
}
public static string ToHex(this byte[] bytes)
{
StringBuilder stringBuilder = new StringBuilder();
foreach (byte b in bytes)
{
stringBuilder.Append(b.ToString("X2"));
}
return stringBuilder.ToString();
}
public static string ToHex(this byte[] bytes, string format)
{
StringBuilder stringBuilder = new StringBuilder();
foreach (byte b in bytes)
{
stringBuilder.Append(b.ToString(format));
}
return stringBuilder.ToString();
}
public static string ToHex(this byte[] bytes, int offset, int count)
{
StringBuilder stringBuilder = new StringBuilder();
for (int i = offset; i < offset + count; ++i)
{
stringBuilder.Append(bytes[i].ToString("X2"));
}
return stringBuilder.ToString();
}
public static string ToStr(this byte[] bytes)
{
return Encoding.Default.GetString(bytes);
}
public static string ToStr(this byte[] bytes, int index, int count)
{
return Encoding.Default.GetString(bytes, index, count);
}
public static string Utf8ToStr(this byte[] bytes)
{
return Encoding.UTF8.GetString(bytes);
}
public static string Utf8ToStr(this byte[] bytes, int index, int count)
{
return Encoding.UTF8.GetString(bytes, index, count);
}
public static void WriteTo(this byte[] bytes, int offset, uint num)
{
bytes[offset] = (byte)(num & 0xff);
bytes[offset + 1] = (byte)((num & 0xff00) >> 8);
bytes[offset + 2] = (byte)((num & 0xff0000) >> 16);
bytes[offset + 3] = (byte)((num & 0xff000000) >> 24);
}
public static void WriteTo(this byte[] bytes, int offset, int num)
{
bytes[offset] = (byte)(num & 0xff);
bytes[offset + 1] = (byte)((num & 0xff00) >> 8);
bytes[offset + 2] = (byte)((num & 0xff0000) >> 16);
bytes[offset + 3] = (byte)((num & 0xff000000) >> 24);
}
public static void WriteTo(this byte[] bytes, int offset, byte num)
{
bytes[offset] = num;
}
public static void WriteTo(this byte[] bytes, int offset, short num)
{
bytes[offset] = (byte)(num & 0xff);
bytes[offset + 1] = (byte)((num & 0xff00) >> 8);
}
public static void WriteTo(this byte[] bytes, int offset, ushort num)
{
bytes[offset] = (byte)(num & 0xff);
bytes[offset + 1] = (byte)((num & 0xff00) >> 8);
}
}
}
================================================
FILE: Assets/Scripts/Helper/ByteHelper.cs.meta
================================================
fileFormatVersion: 2
guid: c31f9c17b9d7c0e45b3b3f77811cb795
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
================================================
FILE: Assets/Scripts/Helper/MonoSingleton.cs
================================================
using UnityEngine;
public abstract class MonoSingleton<T> : MonoBehaviour where T : MonoSingleton<T>
{
private static T mInstance = null;
public static T Instance
{
get
{
if (mInstance == null)
{
mInstance = GameObject.FindObjectOfType(typeof(T)) as T;
if (mInstance == null)
{
GameObject go = new GameObject(typeof(T).Name);
mInstance = go.AddComponent<T>();
GameObject parent = GameObject.Find("Boot");
if (parent != null)
{
go.transform.parent = parent.transform;
}
}
}
return mInstance;
}
}
/*
* 没有任何实现的函数,用于保证MonoSingleton在使用前已创建
*/
public void Startup()
{
}
private void Awake()
{
if (mInstance == null)
{
mInstance = this as T;
}
DontDestroyOnLoad(gameObject);
Init();
}
public virtual void Init()
{
}
public void DestroySelf()
{
Dispose();
mInstance = null;
Destroy(gameObject);
}
public virtual void Dispose()
{
}
}
================================================
FILE: Assets/Scripts/Helper/MonoSingleton.cs.meta
================================================
fileFormatVersion: 2
guid: bbde26f5f28b63743b17d086fd52d70a
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
================================================
FILE: Assets/Scripts/Helper/NetworkHelper.cs
================================================
using System.Net;
namespace UNetwork
{
public static class NetworkHelper
{
public static IPEndPoint ToIPEndPoint(string host, int port)
{
return new IPEndPoint(IPAddress.Parse(host), port);
}
public static IPEndPoint ToIPEndPoint(string address)
{
int index = address.LastIndexOf(':');
string host = address.Substring(0, index);
string p = address.Substring(index + 1);
int port = int.Parse(p);
return ToIPEndPoint(host, port);
}
}
}
================================================
FILE: Assets/Scripts/Helper/NetworkHelper.cs.meta
================================================
fileFormatVersion: 2
guid: 5f24e42ac059909498f35805b76f9102
timeCreated: 1511941046
licenseType: Free
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
================================================
FILE: Assets/Scripts/Helper/RandomHelper.cs
================================================
using System;
namespace UNetwork
{
public static class RandomHelper
{
private static readonly Random random = new Random();
public static UInt64 RandUInt64()
{
var bytes = new byte[8];
random.NextBytes(bytes);
return BitConverter.ToUInt64(bytes, 0);
}
public static Int64 RandInt64()
{
var bytes = new byte[8];
random.NextBytes(bytes);
return BitConverter.ToInt64(bytes, 0);
}
/// <summary>
/// 获取lower与Upper之间的随机数
/// </summary>
/// <param name="lower"></param>
/// <param name="upper"></param>
/// <returns></returns>
public static int RandomNumber(int lower, int upper)
{
int value = random.Next(lower, upper);
return value;
}
}
}
================================================
FILE: Assets/Scripts/Helper/RandomHelper.cs.meta
================================================
fileFormatVersion: 2
guid: ec912a7512f681b43bb4cc56873631af
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
================================================
FILE: Assets/Scripts/Helper/TimeHelper.cs
================================================
using System;
namespace UNetwork
{
public static class TimeHelper
{
private static readonly long epoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc).Ticks;
/// <summary>
/// 客户端时间
/// </summary>
/// <returns></returns>
public static long ClientNow()
{
return (DateTime.UtcNow.Ticks - epoch) / 10000;
}
public static long ClientNowSeconds()
{
return (DateTime.UtcNow.Ticks - epoch) / 10000000;
}
public static long Now()
{
return ClientNow();
}
}
}
================================================
FILE: Assets/Scripts/Helper/TimeHelper.cs.meta
================================================
fileFormatVersion: 2
guid: 53e39d24f06688d4d961473c5a977410
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
================================================
FILE: Assets/Scripts/Helper.meta
================================================
fileFormatVersion: 2
guid: 3a479f7d4b18e0f439a7ba86124bebe4
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
================================================
FILE: Assets/Scripts/Network/AChannel.cs
================================================
using System;
using System.IO;
using System.Net;
using UnityEngine;
namespace UNetwork
{
public enum ChannelType
{
Connect,
Accept,
}
public class AChannel
{
public ChannelType ChannelType { get; }
public AService Service { get; }
protected MemoryStream memoryStream;
public MemoryStream Stream => this.memoryStream;
public int Error { get; set; }
public IPEndPoint RemoteAddress { get; protected set; }
private Action<AChannel, int> connectCallback;
public event Action<AChannel, int> ConnectCallback
{
add { this.connectCallback += value; }
remove { this.connectCallback -= value; }
}
private Action<AChannel, int> errorCallback;
public event Action<AChannel, int> ErrorCallback
{
add { this.errorCallback += value; }
remove { this.errorCallback -= value; }
}
private Action<MemoryStream> readCallback;
public event Action<MemoryStream> ReadCallback
{
add { this.readCallback += value; }
remove { this.readCallback -= value; }
}
public void OnConnect(int code)
{
Debug.Log("connect success");
this.connectCallback.Invoke(this, code);
}
protected void OnRead(MemoryStream memoryStream)
{
this.readCallback.Invoke(memoryStream);
}
protected void OnError(int e)
{
this.Error = e;
this.errorCallback?.Invoke(this, e);
}
protected AChannel(AService service, ChannelType channelType)
{
this.ChannelType = channelType;
this.Service = service;
}
public virtual void Start()
{
}
public virtual void Send(MemoryStream stream)
{
}
public virtual void Dispose()
{
this.Service.Dispose();
}
}
}
================================================
FILE: Assets/Scripts/Network/AChannel.cs.meta
================================================
fileFormatVersion: 2
guid: 05a074f965a8c214f8f1f1af1ecf4dcc
timeCreated: 1503986857
licenseType: Free
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
================================================
FILE: Assets/Scripts/Network/AService.cs
================================================
using System;
using System.Net;
namespace UNetwork
{
public enum NetworkProtocol
{
KCP,
TCP,
WebSocket,
}
public abstract class AService
{
public abstract AChannel GetChannel();
public abstract AChannel ConnectChannel(IPEndPoint ipEndPoint);
public abstract AChannel ConnectChannel(string address);
public abstract void Update();
public abstract void Dispose();
}
}
================================================
FILE: Assets/Scripts/Network/AService.cs.meta
================================================
fileFormatVersion: 2
guid: b5af0de1c471e6c43989dc0349cc2bba
timeCreated: 1503986858
licenseType: Free
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
================================================
FILE: Assets/Scripts/Network/ClientManager.cs
================================================
using System;
using System.Net;
using System.Threading;
namespace UNetwork
{
/// <summary>
/// 客户端的 业务逻辑 管理类
/// </summary>
public class ClientManager : MonoSingleton<ClientManager>, INetworkManager
{
public AService Service { get; private set; }
public Session Session { get; private set; }
public IMessagePacker MessagePacker { get; set; }
public IMessageDispatcher MessageDispatcher { get; set; }
public Action<int> OnConnect { get; set; }
public Action<int> OnError { get; set; }
public Action<byte[]> OnMessage { get; set; }
public override void Init()
{
SynchronizationContext.SetSynchronizationContext(OneThreadSynchronizationContext.Instance);
}
//clinet
public void InitService(NetworkProtocol protocol, int packetSize = Packet.PacketSizeLength4)
{
switch (protocol)
{
case NetworkProtocol.KCP:
this.Service = new KService() { };
break;
case NetworkProtocol.TCP:
this.Service = new TService(packetSize) { };
break;
case NetworkProtocol.WebSocket:
this.Service = new WService() { };
break;
}
}
/// <summary>
/// 创建一个新Session
/// </summary>
public void Connect(IPEndPoint ipEndPoint)
{
AChannel channel = this.Service.ConnectChannel(ipEndPoint);
Session = new Session(channel);
Session.Start(this);
}
/// <summary>
/// 创建一个新Session
/// </summary>
public void Connect(string address)
{
AChannel channel = this.Service.ConnectChannel(address);
Session = new Session(channel);
Session.Start(this);
}
public void Connect(string ip, int port)
{
AChannel channel = this.Service.ConnectChannel(NetworkHelper.ToIPEndPoint(ip, port));
Session = new Session(channel);
Session.Start(this);
}
public void Update()
{
OneThreadSynchronizationContext.Instance.Update();
if (this.Service == null)
{
return;
}
this.Service.Update();
}
public void Send(byte[] data)
{
Session.Send(data);
}
public override void Dispose()
{
Session.Dispose();
}
}
}
================================================
FILE: Assets/Scripts/Network/ClientManager.cs.meta
================================================
fileFormatVersion: 2
guid: 151d2db7aab5bc8438bc039443ba0e3b
timeCreated: 1498117616
licenseType: Free
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
================================================
FILE: Assets/Scripts/Network/Core/KCP/KCP.cs
================================================
// Copyright (C) 2017 prototyped.cn All rights reserved.
// Distributed under the terms and conditions of the MIT License.
// See accompanying files LICENSE.
using System;
using System.Diagnostics;
using System.Collections.Generic;
namespace UNetwork
{
public class KCP
{
public const int IKCP_RTO_NDL = 30; // no delay min rto
public const int IKCP_RTO_MIN = 100; // normal min rto
public const int IKCP_RTO_DEF = 200;
public const int IKCP_RTO_MAX = 60000;
public const int IKCP_CMD_PUSH = 81; // cmd: push data
public const int IKCP_CMD_ACK = 82; // cmd: ack
public const int IKCP_CMD_WASK = 83; // cmd: window probe (ask)
public const int IKCP_CMD_WINS = 84; // cmd: window size (tell)
public const int IKCP_ASK_SEND = 1; // need to send IKCP_CMD_WASK
public const int IKCP_ASK_TELL = 2; // need to send IKCP_CMD_WINS
public const int IKCP_WND_SND = 32;
public const int IKCP_WND_RCV = 32;
public const int IKCP_MTU_DEF = 1400;
public const int IKCP_ACK_FAST = 3;
public const int IKCP_INTERVAL = 100;
public const int IKCP_OVERHEAD = 24;
public const int IKCP_DEADLINK = 20;
public const int IKCP_THRESH_INIT = 2;
public const int IKCP_THRESH_MIN = 2;
public const int IKCP_PROBE_INIT = 7000; // 7 secs to probe window size
public const int IKCP_PROBE_LIMIT = 120000; // up to 120 secs to probe window
public const int IKCP_LOG_OUTPUT = 0x1;
public const int IKCP_LOG_INPUT = 0x2;
public const int IKCP_LOG_SEND = 0x4;
public const int IKCP_LOG_RECV = 0x8;
public const int IKCP_LOG_IN_DATA = 0x10;
public const int IKCP_LOG_IN_ACK = 0x20;
public const int IKCP_LOG_IN_PROBE = 0x40;
public const int IKCP_LOG_IN_WINS = 0x80;
public const int IKCP_LOG_OUT_DATA = 0x100;
public const int IKCP_LOG_OUT_ACK = 0x200;
public const int IKCP_LOG_OUT_PROBE = 0x400;
public const int IKCP_LOG_OUT_WINS = 0x800;
// encode 8 bits unsigned int
public static void ikcp_encode8u(byte[] p, int offset, byte c)
{
p[offset] = c;
}
// decode 8 bits unsigned int
public static byte ikcp_decode8u(byte[] p, ref int offset)
{
return p[offset++];
}
// encode 16 bits unsigned int (lsb)
public static void ikcp_encode16u(byte[] p, int offset, UInt16 v)
{
p[offset] = (byte)(v & 0xFF);
p[offset + 1] = (byte)(v >> 8);
}
// decode 16 bits unsigned int (lsb)
public static UInt16 ikcp_decode16u(byte[] p, ref int offset)
{
int pos = offset;
offset += 2;
return (UInt16)((UInt16)p[pos] | (UInt16)(p[pos + 1] << 8));
}
// encode 32 bits unsigned int (lsb)
public static void ikcp_encode32u(byte[] p, int offset, UInt32 l)
{
p[offset] = (byte)(l & 0xFF);
p[offset + 1] = (byte)(l >> 8);
p[offset + 2] = (byte)(l >> 16);
p[offset + 3] = (byte)(l >> 24);
}
// decode 32 bits unsigned int (lsb)
public static UInt32 ikcp_decode32u(byte[] p, ref int offset)
{
int pos = offset;
offset += 4;
return ((UInt32)p[pos] | (UInt32)(p[pos + 1] << 8)
| (UInt32)(p[pos + 2] << 16) | (UInt32)(p[pos + 3] << 24));
}
public static UInt32 _imin_(UInt32 a, UInt32 b)
{
return a <= b ? a : b;
}
public static UInt32 _imax_(UInt32 a, UInt32 b)
{
return a >= b ? a : b;
}
public static UInt32 _ibound_(UInt32 lower, UInt32 middle, UInt32 upper)
{
return _imin_(_imax_(lower, middle), upper);
}
public static Int32 _itimediff(UInt32 later, UInt32 earlier)
{
return (Int32)(later - earlier);
}
internal class Segment
{
internal UInt32 conv = 0;
internal UInt32 cmd = 0;
internal UInt32 frg = 0;
internal UInt32 wnd = 0;
internal UInt32 ts = 0;
internal UInt32 sn = 0;
internal UInt32 una = 0;
internal UInt32 resendts = 0;
internal UInt32 rto = 0;
internal UInt32 faskack = 0;
internal UInt32 xmit = 0;
internal byte[] data;
internal Segment(int size = 0)
{
data = new byte[size];
}
internal void Encode(byte[] ptr, ref int offset)
{
UInt32 len = (UInt32)data.Length;
ikcp_encode32u(ptr, offset, conv);
ikcp_encode8u(ptr, offset + 4, (byte)cmd);
ikcp_encode8u(ptr, offset + 5, (byte)frg);
ikcp_encode16u(ptr, offset + 6, (UInt16)wnd);
ikcp_encode32u(ptr, offset + 8, ts);
ikcp_encode32u(ptr, offset + 12, sn);
ikcp_encode32u(ptr, offset + 16, una);
ikcp_encode32u(ptr, offset + 20, len);
offset += IKCP_OVERHEAD;
}
}
UInt32 conv_ = 0;
UInt32 mtu_ = 0;
UInt32 mss_ = 0;
UInt32 state_ = 0;
UInt32 snd_una_ = 0;
UInt32 snd_nxt_ = 0;
UInt32 rcv_nxt_ = 0;
UInt32 ts_recent_ = 0;
UInt32 ts_lastack_ = 0;
UInt32 ssthresh_ = 0;
Int32 rx_rttval_ = 0;
Int32 rx_srtt_ = 0;
Int32 rx_rto_ = 0;
Int32 rx_minrto_ = 0;
UInt32 snd_wnd_ = 0;
UInt32 rcv_wnd_ = 0;
UInt32 rmt_wnd_ = 0;
UInt32 cwnd_ = 0;
UInt32 probe_ = 0;
UInt32 current_ = 0;
UInt32 interval_ = 0;
UInt32 ts_flush_ = 0;
UInt32 xmit_ = 0;
UInt32 nrcv_buf_ = 0;
UInt32 nsnd_buf_ = 0;
UInt32 nrcv_que_ = 0;
UInt32 nsnd_que_ = 0;
UInt32 nodelay_ = 0;
UInt32 updated_ = 0;
UInt32 ts_probe_ = 0;
UInt32 probe_wait_ = 0;
UInt32 dead_link_ = 0;
UInt32 incr_ = 0;
LinkedList<Segment> snd_queue_;
LinkedList<Segment> rcv_queue_;
LinkedList<Segment> snd_buf_;
LinkedList<Segment> rcv_buf_;
UInt32[] acklist_;
UInt32 ackcount_ = 0;
UInt32 ackblock_ = 0;
byte[] buffer_;
object user_;
Int32 fastresend_ = 0;
Int32 nocwnd_ = 0;
public delegate void OutputDelegate(byte[] data, int size, object user);
OutputDelegate output_;
// create a new kcp control object, 'conv' must equal in two endpoint
// from the same connection. 'user' will be passed to the output callback
// output callback can be setup like this: 'kcp->output = my_udp_output'
public KCP(UInt32 conv, object user)
{
Debug.Assert(BitConverter.IsLittleEndian); // we only support little endian device
user_ = user;
conv_ = conv;
snd_wnd_ = IKCP_WND_SND;
rcv_wnd_ = IKCP_WND_RCV;
rmt_wnd_ = IKCP_WND_RCV;
mtu_ = IKCP_MTU_DEF;
mss_ = mtu_ - IKCP_OVERHEAD;
rx_rto_ = IKCP_RTO_DEF;
rx_minrto_ = IKCP_RTO_MIN;
interval_ = IKCP_INTERVAL;
ts_flush_ = IKCP_INTERVAL;
ssthresh_ = IKCP_THRESH_INIT;
dead_link_ = IKCP_DEADLINK;
buffer_ = new byte[(mtu_ + IKCP_OVERHEAD) * 3];
snd_queue_ = new LinkedList<Segment>();
rcv_queue_ = new LinkedList<Segment>();
snd_buf_ = new LinkedList<Segment>();
rcv_buf_ = new LinkedList<Segment>();
}
// release kcp control object
public void Release()
{
snd_buf_.Clear();
rcv_buf_.Clear();
snd_queue_.Clear();
rcv_queue_.Clear();
nrcv_buf_ = 0;
nsnd_buf_ = 0;
nrcv_que_ = 0;
nsnd_que_ = 0;
ackblock_ = 0;
ackcount_ = 0;
buffer_ = null;
acklist_ = null;
}
// set output callback, which will be invoked by kcp
public void SetOutput(OutputDelegate output)
{
output_ = output;
}
// user/upper level recv: returns size, returns below zero for EAGAIN
public int Recv(byte[] buffer, int offset, int len)
{
int ispeek = (len < 0 ? 1 : 0);
int recover = 0;
if (rcv_queue_.Count == 0)
return -1;
if (len < 0)
len = -len;
int peeksize = PeekSize();
if (peeksize < 0)
return -2;
if (peeksize > len)
return -3;
if (nrcv_que_ >= rcv_wnd_)
recover = 1;
// merge fragment
len = 0;
LinkedListNode<Segment> next = null;
for (var node = rcv_queue_.First; node != null; node = next)
{
int fragment = 0;
var seg = node.Value;
next = node.Next;
if (buffer != null)
{
Buffer.BlockCopy(seg.data, 0, buffer, offset, seg.data.Length);
offset += seg.data.Length;
}
len += seg.data.Length;
fragment = (int)seg.frg;
Log(IKCP_LOG_RECV, "recv sn={0}", seg.sn);
if (ispeek == 0)
{
rcv_queue_.Remove(node);
nrcv_que_--;
}
if (fragment == 0)
break;
}
Debug.Assert(len == peeksize);
// move available data from rcv_buf -> rcv_queue
while (rcv_buf_.Count > 0)
{
var node = rcv_buf_.First;
var seg = node.Value;
if (seg.sn == rcv_nxt_ && nrcv_que_ < rcv_wnd_)
{
rcv_buf_.Remove(node);
nrcv_buf_--;
rcv_queue_.AddLast(node);
nrcv_que_++;
rcv_nxt_++;
}
else
{
break;
}
}
// fast recover
if (nrcv_que_ < rcv_wnd_ && recover != 0)
{
// ready to send back IKCP_CMD_WINS in ikcp_flush
// tell remote my window size
probe_ |= IKCP_ASK_TELL;
}
return len;
}
// check the size of next message in the recv queue
public int PeekSize()
{
if (rcv_queue_.Count == 0)
return -1;
var node = rcv_queue_.First;
var seg = node.Value;
if (seg.frg == 0)
return seg.data.Length;
if (nrcv_que_ < seg.frg + 1)
return -1;
int length = 0;
for (node = rcv_queue_.First; node != null; node = node.Next)
{
seg = node.Value;
length += seg.data.Length;
if (seg.frg == 0)
break;
}
return length;
}
// user/upper level send, returns below zero for error
public int Send(byte[] buffer, int offset, int len)
{
Debug.Assert(mss_ > 0);
if (len < 0)
return -1;
//
// not implement streaming mode here as ikcp.c
//
int count = 0;
if (len <= (int)mss_)
count = 1;
else
count = (len + (int)mss_ - 1) / (int)mss_;
if (count > 255) // maximum value `frg` can present
return -2;
if (count == 0)
count = 1;
// fragment
for (int i = 0; i < count; i++)
{
int size = len > (int)mss_ ? (int)mss_ : len;
var seg = new Segment(size);
if (buffer != null && len > 0)
{
Buffer.BlockCopy(buffer, offset, seg.data, 0, size);
offset += size;
}
seg.frg = (UInt32)(count - i - 1);
snd_queue_.AddLast(seg);
nsnd_que_++;
len -= size;
}
return 0;
}
// parse ack
void UpdateACK(Int32 rtt)
{
if (rx_srtt_ == 0)
{
rx_srtt_ = rtt;
rx_rttval_ = rtt / 2;
}
else
{
Int32 delta = rtt - rx_srtt_;
if (delta < 0)
delta = -delta;
rx_rttval_ = (3 * rx_rttval_ + delta) / 4;
rx_srtt_ = (7 * rx_srtt_ + rtt) / 8;
if (rx_srtt_ < 1)
rx_srtt_ = 1;
}
var rto = rx_srtt_ + _imax_(interval_, (UInt32)(4 * rx_rttval_));
rx_rto_ = (Int32)_ibound_((UInt32)rx_minrto_, (UInt32)rto, IKCP_RTO_MAX);
}
void ShrinkBuf()
{
var node = snd_buf_.First;
if (node != null)
{
var seg = node.Value;
snd_una_ = seg.sn;
}
else
{
snd_una_ = snd_nxt_;
}
}
void ParseACK(UInt32 sn)
{
if (_itimediff(sn, snd_una_) < 0 || _itimediff(sn, snd_nxt_) >= 0)
return;
LinkedListNode<Segment> next = null;
for (var node = snd_buf_.First; node != null; node = next)
{
var seg = node.Value;
next = node.Next;
if (sn == seg.sn)
{
snd_buf_.Remove(node);
nsnd_buf_--;
break;
}
if (_itimediff(sn, seg.sn) < 0)
break;
}
}
void ParseUNA(UInt32 una)
{
LinkedListNode<Segment> next = null;
for (var node = snd_buf_.First; node != null; node = next)
{
var seg = node.Value;
next = node.Next;
if (_itimediff(una, seg.sn) > 0)
{
snd_buf_.Remove(node);
nsnd_buf_--;
}
else
{
break;
}
}
}
void ParseFastACK(UInt32 sn)
{
if (_itimediff(sn, snd_una_) < 0 || _itimediff(sn, snd_nxt_) >= 0)
return;
LinkedListNode<Segment> next = null;
for (var node = snd_buf_.First; node != null; node = next)
{
var seg = node.Value;
next = node.Next;
if (_itimediff(sn, seg.sn) < 0)
{
break;
}
else if (sn != seg.sn)
{
seg.faskack++;
}
}
}
// ack append
void ACKPush(UInt32 sn, UInt32 ts)
{
var newsize = ackcount_ + 1;
if (newsize > ackblock_)
{
UInt32 newblock = 8;
for (; newblock < newsize; newblock <<= 1)
;
var acklist = new UInt32[newblock * 2];
if (acklist_ != null)
{
for (var i = 0; i < ackcount_; i++)
{
acklist[i * 2] = acklist_[i * 2];
acklist[i * 2 + 1] = acklist_[i * 2 + 1];
}
}
acklist_ = acklist;
ackblock_ = newblock;
}
acklist_[ackcount_ * 2] = sn;
acklist_[ackcount_ * 2 + 1] = ts;
ackcount_++;
}
void ACKGet(int pos, ref UInt32 sn, ref UInt32 ts)
{
sn = acklist_[pos * 2];
ts = acklist_[pos * 2 + 1];
}
// parse data
void ParseData(Segment newseg)
{
UInt32 sn = newseg.sn;
int repeat = 0;
if (_itimediff(sn, rcv_nxt_ + rcv_wnd_) >= 0 ||
_itimediff(sn, rcv_nxt_) < 0)
{
return;
}
LinkedListNode<Segment> node = null;
LinkedListNode<Segment> prev = null;
for (node = rcv_buf_.Last; node != null; node = prev)
{
var seg = node.Value;
prev = node.Previous;
if (seg.sn == sn)
{
repeat = 1;
break;
}
if (_itimediff(sn, seg.sn) > 0)
{
break;
}
}
if (repeat == 0)
{
if (node != null)
{
rcv_buf_.AddAfter(node, newseg);
}
else
{
rcv_buf_.AddFirst(newseg);
}
nrcv_buf_++;
}
// move available data from rcv_buf -> rcv_queue
while (rcv_buf_.Count > 0)
{
node = rcv_buf_.First;
var seg = node.Value;
if (seg.sn == rcv_nxt_ && nrcv_que_ < rcv_wnd_)
{
rcv_buf_.Remove(node);
nrcv_buf_--;
rcv_queue_.AddLast(node);
nrcv_que_++;
rcv_nxt_++;
}
else
{
break;
}
}
}
// when you received a low level packet (eg. UDP packet), call it
public int Input(byte[] data, int offset, int size)
{
UInt32 maxack = 0;
int flag = 0;
Log(IKCP_LOG_INPUT, "[RI] {0} bytes", size);
if (data == null || size < IKCP_OVERHEAD)
return -1;
while (true)
{
if (size < IKCP_OVERHEAD)
break;
UInt32 conv = ikcp_decode32u(data, ref offset);
if (conv_ != conv)
return -1;
UInt32 cmd = ikcp_decode8u(data, ref offset);
UInt32 frg = ikcp_decode8u(data, ref offset);
UInt32 wnd = ikcp_decode16u(data, ref offset);
UInt32 ts = ikcp_decode32u(data, ref offset);
UInt32 sn = ikcp_decode32u(data, ref offset);
UInt32 una = ikcp_decode32u(data, ref offset);
UInt32 len = ikcp_decode32u(data, ref offset);
size -= IKCP_OVERHEAD;
if (size < len)
return -2;
if (cmd != IKCP_CMD_PUSH && cmd != IKCP_CMD_ACK &&
cmd != IKCP_CMD_WASK && cmd != IKCP_CMD_WINS)
return -3;
rmt_wnd_ = wnd;
ParseUNA(una);
ShrinkBuf();
if (cmd == IKCP_CMD_ACK)
{
if (_itimediff(current_, ts) >= 0)
{
UpdateACK(_itimediff(current_, ts));
}
ParseACK(sn);
ShrinkBuf();
if (flag == 0)
{
flag = 1;
maxack = sn;
}
else
{
if (_itimediff(sn, maxack) > 0)
{
maxack = sn;
}
}
Log(IKCP_LOG_IN_DATA, "input ack: sn={0} rtt={1} rto={2}",
sn, _itimediff(current_, ts), rx_rto_);
}
else if (cmd == IKCP_CMD_PUSH)
{
Log(IKCP_LOG_IN_DATA, "input psh: sn={0} ts={1}", sn, ts);
if (_itimediff(sn, rcv_nxt_ + rcv_wnd_) < 0)
{
ACKPush(sn, ts);
if (_itimediff(sn, rcv_nxt_) >= 0)
{
var seg = new Segment((int)len);
seg.conv = conv;
seg.cmd = cmd;
seg.frg = frg;
seg.wnd = wnd;
seg.ts = ts;
seg.sn = sn;
seg.una = una;
if (len > 0)
{
Buffer.BlockCopy(data, offset, seg.data, 0, (int)len);
}
ParseData(seg);
}
}
}
else if (cmd == IKCP_CMD_WASK)
{
// ready to send back IKCP_CMD_WINS in ikcp_flush
// tell remote my window size
probe_ |= IKCP_ASK_TELL;
Log(IKCP_LOG_IN_PROBE, "input probe");
}
else if (cmd == IKCP_CMD_WINS)
{
// do nothing
Log(IKCP_LOG_IN_WINS, "input wins: {0}", wnd);
}
else
{
return -3;
}
offset += (int)len;
size -= (int)len;
}
if (flag != 0)
{
ParseFastACK(maxack);
}
UInt32 unack = snd_una_;
if (_itimediff(snd_una_, unack) > 0)
{
if (cwnd_ < rmt_wnd_)
{
if (cwnd_ < ssthresh_)
{
cwnd_++;
incr_ += mss_;
}
else
{
if (incr_ < mss_)
incr_ = mss_;
incr_ += (mss_ * mss_) / incr_ + (mss_ / 16);
if ((cwnd_ + 1) * mss_ <= incr_)
cwnd_++;
}
if (cwnd_ > rmt_wnd_)
{
cwnd_ = rmt_wnd_;
incr_ = rmt_wnd_ * mss_;
}
}
}
return 0;
}
int WndUnused()
{
if (nrcv_que_ < rcv_wnd_)
return (int)(rcv_wnd_ - nrcv_que_);
return 0;
}
// flush pending data
void Flush()
{
int change = 0;
int lost = 0;
int offset = 0;
// 'ikcp_update' haven't been called.
if (updated_ == 0)
return;
var seg = new Segment
{
conv = conv_,
cmd = IKCP_CMD_ACK,
wnd = (UInt32)WndUnused(),
una = rcv_nxt_,
};
// flush acknowledges
int count = (int)ackcount_;
for (int i = 0; i < count; i++)
{
if ((offset + IKCP_OVERHEAD) > mtu_)
{
output_(buffer_, offset, user_);
offset = 0;
}
ACKGet(i, ref seg.sn, ref seg.ts);
seg.Encode(buffer_, ref offset);
}
ackcount_ = 0;
// probe window size (if remote window size equals zero)
if (rmt_wnd_ == 0)
{
if (probe_wait_ == 0)
{
probe_wait_ = IKCP_PROBE_INIT;
ts_probe_ = current_ + probe_wait_;
}
else
{
if (_itimediff(current_, ts_probe_) >= 0)
{
if (probe_wait_ < IKCP_PROBE_INIT)
probe_wait_ = IKCP_PROBE_INIT;
probe_wait_ += probe_wait_ / 2;
if (probe_wait_ > IKCP_PROBE_LIMIT)
probe_wait_ = IKCP_PROBE_LIMIT;
ts_probe_ = current_ + probe_wait_;
probe_ |= IKCP_ASK_SEND;
}
}
}
else
{
ts_probe_ = 0;
probe_wait_ = 0;
}
// flush window probing commands
if ((probe_ & IKCP_ASK_SEND) > 0)
{
seg.cmd = IKCP_CMD_WASK;
if ((offset + IKCP_OVERHEAD) > mtu_)
{
output_(buffer_, offset, user_);
offset = 0;
}
seg.Encode(buffer_, ref offset);
}
// flush window probing commands
if ((probe_ & IKCP_ASK_TELL) > 0)
{
seg.cmd = IKCP_CMD_WINS;
if ((offset + IKCP_OVERHEAD) > mtu_)
{
output_(buffer_, offset, user_);
offset = 0;
}
seg.Encode(buffer_, ref offset);
}
probe_ = 0;
// calculate window size
UInt32 cwnd = _imin_(snd_wnd_, rmt_wnd_);
if (nocwnd_ == 0)
cwnd = _imin_(cwnd_, cwnd);
// move data from snd_queue to snd_buf
while (_itimediff(snd_nxt_, snd_una_ + cwnd) < 0)
{
if (snd_queue_.Count == 0)
break;
var node = snd_queue_.First;
var newseg = node.Value;
snd_queue_.Remove(node);
snd_buf_.AddLast(node);
nsnd_que_--;
nsnd_buf_++;
newseg.conv = conv_;
newseg.cmd = IKCP_CMD_PUSH;
newseg.wnd = seg.wnd;
newseg.ts = current_;
newseg.sn = snd_nxt_++;
newseg.una = rcv_nxt_;
newseg.resendts = current_;
newseg.rto = (UInt32)rx_rto_;
newseg.faskack = 0;
newseg.xmit = 0;
}
// calculate resent
UInt32 resent = (fastresend_ > 0 ? (UInt32)fastresend_ : 0xffffffff);
UInt32 rtomin = (nodelay_ == 0 ? (UInt32)(rx_rto_ >> 3) : 0);
// flush data segments
for (var node = snd_buf_.First; node != null; node = node.Next)
{
var segment = node.Value;
int needsend = 0;
if (segment.xmit == 0)
{
needsend = 1;
segment.xmit++;
segment.rto = (UInt32)rx_rto_;
segment.resendts = current_ + segment.rto + rtomin;
}
else if (_itimediff(current_, segment.resendts) >= 0)
{
needsend = 1;
segment.xmit++;
xmit_++;
if (nodelay_ == 0)
segment.rto += (UInt32)rx_rto_;
else
segment.rto += (UInt32)rx_rto_ / 2;
segment.resendts = current_ + segment.rto;
lost = 1;
}
else if (segment.faskack >= resent)
{
needsend = 1;
segment.xmit++;
segment.faskack = 0;
segment.resendts = current_ + segment.rto;
change++;
}
if (needsend > 0)
{
segment.ts = current_;
segment.wnd = seg.wnd;
segment.una = rcv_nxt_;
int need = IKCP_OVERHEAD;
if (segment.data != null)
need += segment.data.Length;
if (offset + need > mtu_)
{
output_(buffer_, offset, user_);
offset = 0;
}
segment.Encode(buffer_, ref offset);
if (segment.data.Length > 0)
{
Buffer.BlockCopy(segment.data, 0, buffer_, offset, segment.data.Length);
offset += segment.data.Length;
}
if (segment.xmit >= dead_link_)
state_ = 0xffffffff;
}
}
// flush remain segments
if (offset > 0)
{
output_(buffer_, offset, user_);
offset = 0;
}
// update ssthresh
if (change > 0)
{
UInt32 inflight = snd_nxt_ - snd_una_;
ssthresh_ = inflight / 2;
if (ssthresh_ < IKCP_THRESH_MIN)
ssthresh_ = IKCP_THRESH_MIN;
cwnd_ = ssthresh_ + resent;
incr_ = cwnd_ * mss_;
}
if (lost > 0)
{
ssthresh_ = cwnd / 2;
if (ssthresh_ < IKCP_THRESH_MIN)
ssthresh_ = IKCP_THRESH_MIN;
cwnd_ = 1;
incr_ = mss_;
}
if (cwnd_ < 1)
{
cwnd_ = 1;
incr_ = mss_;
}
}
// update state (call it repeatedly, every 10ms-100ms), or you can ask
// ikcp_check when to call it again (without ikcp_input/_send calling).
// 'current' - current timestamp in millisec.
public void Update(UInt32 current)
{
current_ = current;
if (updated_ == 0)
{
updated_ = 1;
ts_flush_ = current;
}
Int32 slap = _itimediff(current_, ts_flush_);
if (slap >= 10000 || slap < -10000)
{
ts_flush_ = current;
slap = 0;
}
if (slap >= 0)
{
ts_flush_ += interval_;
if (_itimediff(current_, ts_flush_) >= 0)
ts_flush_ = current_ + interval_;
Flush();
}
}
// Determine when should you invoke ikcp_update:
// returns when you should invoke ikcp_update in millisec, if there
// is no ikcp_input/_send calling. you can call ikcp_update in that
// time, instead of call update repeatly.
// Important to reduce unnacessary ikcp_update invoking. use it to
// schedule ikcp_update (eg. implementing an epoll-like mechanism,
// or optimize ikcp_update when handling massive kcp connections)
public UInt32 Check(UInt32 current)
{
UInt32 ts_flush = ts_flush_;
Int32 tm_flush = 0x7fffffff;
Int32 tm_packet = 0x7fffffff;
if (updated_ == 0)
return current;
if (_itimediff(current, ts_flush) >= 10000 ||
_itimediff(current, ts_flush) < -10000)
{
ts_flush = current;
}
if (_itimediff(current, ts_flush) >= 0)
return current;
tm_flush = _itimediff(ts_flush, current);
for (var node = snd_buf_.First; node != null; node = node.Next)
{
var seg = node.Value;
Int32 diff = _itimediff(seg.resendts, current);
if (diff <= 0)
return current;
if (diff < tm_packet)
tm_packet = diff;
}
UInt32 minimal = (UInt32)(tm_packet < tm_flush ? tm_packet : tm_flush);
if (minimal >= interval_)
minimal = interval_;
return current + minimal;
}
// change MTU size, default is 1400
public int SetMTU(int mtu)
{
if (mtu < 50 || mtu < IKCP_OVERHEAD)
return -1;
var buffer = new byte[(mtu + IKCP_OVERHEAD) * 3];
mtu_ = (UInt32)mtu;
mss_ = mtu_ - IKCP_OVERHEAD;
buffer_ = buffer;
return 0;
}
public int Interval(int interval)
{
if (interval > 5000)
interval = 5000;
else if (interval < 10)
interval = 10;
interval_ = (UInt32)interval;
return 0;
}
// fastest: ikcp_nodelay(kcp, 1, 20, 2, 1)
// nodelay: 0:disable(default), 1:enable
// interval: internal update timer interval in millisec, default is 100ms
// resend: 0:disable fast resend(default), 1:enable fast resend
// nc: 0:normal congestion control(default), 1:disable congestion control
public int NoDelay(int nodelay, int interval, int resend, int nc)
{
if (nodelay >= 0)
{
nodelay_ = (UInt32)nodelay;
if (nodelay > 0)
{
rx_minrto_ = IKCP_RTO_NDL;
}
else
{
rx_minrto_ = IKCP_RTO_MIN;
}
}
if (interval >= 0)
{
if (interval > 5000)
interval = 5000;
else if (interval < 10)
interval = 10;
interval_ = (UInt32)interval;
}
if (resend >= 0)
fastresend_ = resend;
if (nc >= 0)
nocwnd_ = nc;
return 0;
}
// set maximum window size: sndwnd=32, rcvwnd=32 by default
public int WndSize(int sndwnd, int rcvwnd)
{
if (sndwnd > 0)
snd_wnd_ = (UInt32)sndwnd;
if (rcvwnd > 0)
rcv_wnd_ = (UInt32)rcvwnd;
return 0;
}
// get how many packet is waiting to be sent
public int WaitSnd()
{
return (int)(nsnd_buf_ + nsnd_que_);
}
// read conv
public UInt32 GetConv()
{
return conv_;
}
public UInt32 GetState()
{
return state_;
}
public void SetMinRTO(int minrto)
{
rx_minrto_ = minrto;
}
public void SetFastResend(int resend)
{
fastresend_ = resend;
}
void Log(int mask, string format, params object[] args)
{
// Console.WriteLine(mask + String.Format(format, args));
}
}
}
================================================
FILE: Assets/Scripts/Network/Core/KCP/KCP.cs.meta
================================================
fileFormatVersion: 2
guid: 20f9afa1793f2d54f811abe0972ada7c
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
================================================
FILE: Assets/Scripts/Network/Core/KCP/KChannel.cs
================================================
using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Net.Sockets;
using UnityEngine;
#if dynamic_kcp
using System.Runtime.InteropServices;
#endif
namespace UNetwork
{
public struct WaitSendBuffer
{
public byte[] Bytes;
public int Length;
public WaitSendBuffer(byte[] bytes, int length)
{
this.Bytes = bytes;
this.Length = length;
}
}
#if dynamic_kcp
public class KChannel : AChannel
{
private Socket socket;
private IntPtr kcp;
private readonly Queue<WaitSendBuffer> sendBuffer = new Queue<WaitSendBuffer>();
private bool isConnected;
private readonly IPEndPoint remoteEndPoint;
private uint lastRecvTime;
private readonly uint createTime;
public uint LocalConn { get; private set; }
public uint RemoteConn { get; private set; }
private readonly MemoryStream memoryStream;
// connect
public KChannel(uint localConn, Socket socket, IPEndPoint remoteEndPoint, KService kService) : base(kService, ChannelType.Connect)
{
this.memoryStream = this.GetService().MemoryStreamManager.GetStream("message", ushort.MaxValue);
this.LocalConn = localConn;
this.socket = socket;
this.remoteEndPoint = remoteEndPoint;
this.lastRecvTime = kService.TimeNow;
this.createTime = kService.TimeNow;
this.HandleConnnect(localConn);
}
public void Dispose()
{
try
{
if (this.Error == ErrorCode.ERR_Success)
{
for (int i = 0; i < 4; i++)
{
this.Disconnect();
}
}
}
catch (Exception)
{
// ignored
}
if (this.kcp != IntPtr.Zero)
{
Kcp.KcpRelease(this.kcp);
this.kcp = IntPtr.Zero;
}
this.socket = null;
this.memoryStream.Dispose();
}
public override MemoryStream Stream
{
get
{
return this.memoryStream;
}
}
public void Disconnect(int error)
{
this.OnError(error);
}
private KService GetService()
{
return (KService)this.Service;
}
public void HandleConnnect(uint remoteConn)
{
if (this.isConnected)
{
return;
}
this.RemoteConn = remoteConn;
this.kcp = Kcp.KcpCreate(this.RemoteConn, new IntPtr(this.LocalConn));
SetOutput();
Kcp.KcpNodelay(this.kcp, 1, 10, 1, 1);
Kcp.KcpWndsize(this.kcp, 32, 32);
Kcp.KcpSetmtu(this.kcp, 470);
this.isConnected = true;
this.lastRecvTime = this.GetService().TimeNow;
Connect();
}
public void Accept()
{
if (this.socket == null)
{
return;
}
uint timeNow = this.GetService().TimeNow;
try
{
byte[] buffer = this.memoryStream.GetBuffer();
buffer.WriteTo(0, KcpProtocalType.ACK);
buffer.WriteTo(1, LocalConn);
buffer.WriteTo(5, RemoteConn);
this.socket.SendTo(buffer, 0, 9, SocketFlags.None, remoteEndPoint);
}
catch (Exception e)
{
Debug.LogError(e);
this.OnError(ErrorCode.ERR_SocketCantSend);
}
}
/// <summary>
/// 发送请求连接消息
/// </summary>
private void Connect()
{
try
{
uint timeNow = this.GetService().TimeNow;
this.lastRecvTime = timeNow;
byte[] buffer = this.memoryStream.GetBuffer();
buffer.WriteTo(0, KcpProtocalType.SYN);
buffer.WriteTo(1, this.LocalConn);
this.socket.SendTo(buffer, 0, 5, SocketFlags.None, remoteEndPoint);
}
catch (Exception e)
{
Debug.LogError(e);
this.OnError(ErrorCode.ERR_SocketCantSend);
}
}
/// <summary>
/// 发送请求断开消息
/// </summary>
private void Disconnect()
{
if (this.socket == null)
{
return;
}
try
{
byte[] buffer = this.memoryStream.GetBuffer();
buffer.WriteTo(0, KcpProtocalType.FIN);
buffer.WriteTo(1, this.LocalConn);
buffer.WriteTo(5, this.RemoteConn);
buffer.WriteTo(9, (uint)this.Error);
this.socket.SendTo(buffer, 0, 13, SocketFlags.None, remoteEndPoint);
}
catch (Exception e)
{
Debug.LogError(e);
this.OnError(ErrorCode.ERR_SocketCantSend);
}
}
public void Update()
{
uint timeNow = this.GetService().TimeNow;
// 如果还没连接上,发送连接请求
if (!this.isConnected)
{
// // 10秒没连接上则报错
// if (timeNow - this.createTime > 10 * 1000)
// {
// this.OnError(ErrorCode.ERR_KcpCantConnect);
// return;
// }
//
// if (timeNow - this.lastRecvTime < 500)
// {
// return;
// }
}
try
{
Kcp.KcpUpdate(this.kcp, timeNow);
}
catch (Exception e)
{
Debug.LogError(e);
this.OnError(ErrorCode.ERR_SocketError);
return;
}
if (this.kcp != IntPtr.Zero)
{
uint nextUpdateTime = Kcp.KcpCheck(this.kcp, timeNow);
}
}
private void HandleSend()
{
while (true)
{
if (this.sendBuffer.Count <= 0)
{
break;
}
WaitSendBuffer buffer = this.sendBuffer.Dequeue();
this.KcpSend(buffer.Bytes, buffer.Length);
}
}
public void HandleRecv(byte[] date, int offset, int length)
{
this.isConnected = true;
Kcp.KcpInput(this.kcp, date, offset, length);
while (true)
{
int n = Kcp.KcpPeeksize(this.kcp);
if (n < 0)
{
return;
}
if (n == 0)
{
this.OnError((int)SocketError.NetworkReset);
return;
}
byte[] buffer = this.memoryStream.GetBuffer();
this.memoryStream.SetLength(n);
this.memoryStream.Seek(0, SeekOrigin.Begin);
int count = Kcp.KcpRecv(this.kcp, buffer, ushort.MaxValue);
if (n != count)
{
return;
}
if (count <= 0)
{
return;
}
this.lastRecvTime = this.GetService().TimeNow;
this.OnRead(this.memoryStream);
}
}
public override void Start()
{
}
public void Output(IntPtr bytes, int count)
{
try
{
if (count == 0)
{
Debug.LogError($"output 0");
return;
}
byte[] buffer = this.memoryStream.GetBuffer();
Marshal.Copy(bytes, buffer, 0, count);
this.socket.SendTo(buffer, 0, count, SocketFlags.None, this.remoteEndPoint);
}
catch (Exception e)
{
Debug.LogError(e);
this.OnError(ErrorCode.ERR_SocketCantSend);
}
}
#if !ENABLE_IL2CPP
private KcpOutput kcpOutput;
#endif
public void SetOutput()
{
#if ENABLE_IL2CPP
Kcp.KcpSetoutput(this.kcp, KcpOutput);
#else
// 跟上一行一样写法,pc跟linux会出错, 保存防止被GC
kcpOutput = KcpOutput;
Kcp.KcpSetoutput(this.kcp, kcpOutput);
#endif
}
#if ENABLE_IL2CPP
[AOT.MonoPInvokeCallback(typeof(KcpOutput))]
#endif
public static int KcpOutput(IntPtr bytes, int len, IntPtr kcp, IntPtr user)
{
KService.Output(bytes, len, user);
return len;
}
private void KcpSend(byte[] buffers, int length)
{
Kcp.KcpSend(this.kcp, buffers, length);
}
private void Send(byte[] buffer, int index, int length)
{
if (isConnected)
{
this.KcpSend(buffer, length);
return;
}
this.sendBuffer.Enqueue(new WaitSendBuffer(buffer, length));
}
public override void Send(MemoryStream stream)
{
if (this.kcp != IntPtr.Zero)
{
// 检查等待发送的消息,如果超出两倍窗口大小,应该断开连接
if (Kcp.KcpWaitsnd(this.kcp) > 256 * 2)
{
this.OnError(ErrorCode.ERR_KcpWaitSendSizeTooLarge);
return;
}
}
ushort size = (ushort)(stream.Length - stream.Position);
byte[] bytes = stream.GetBuffer();
Send(bytes, 0, size);
}
}
#else
public class KChannel : AChannel
{
private Socket socket;
private KCP kcp;
private readonly Queue<WaitSendBuffer> sendBuffer = new Queue<WaitSendBuffer>();
private bool isConnected;
private readonly IPEndPoint remoteEndPoint;
private uint lastRecvTime;
private readonly uint createTime;
public uint LocalConn { get; private set; }
public uint RemoteConn { get; private set; }
// connect
public KChannel(uint localConn, Socket socket, IPEndPoint remoteEndPoint, KService kService) : base(kService, ChannelType.Connect)
{
this.memoryStream = this.GetService().MemoryStreamManager.GetStream("message", ushort.MaxValue);
this.LocalConn = localConn;
this.socket = socket;
this.remoteEndPoint = remoteEndPoint;
this.lastRecvTime = kService.TimeNow;
this.createTime = kService.TimeNow;
this.HandleConnnect(localConn);
}
public override void Dispose()
{
try
{
if (this.Error == ErrorCode.ERR_Success)
{
for (int i = 0; i < 4; i++)
{
this.Disconnect();
}
}
}
catch (Exception)
{
// ignored
}
if (this.kcp != null)
{
kcp.Release();
this.kcp = null;
}
this.socket = null;
this.memoryStream.Dispose();
}
public void Disconnect(int error)
{
this.OnError(error);
}
private KService GetService()
{
return (KService)this.Service;
}
public void HandleConnnect(uint remoteConn)
{
if (this.isConnected)
{
return;
}
this.RemoteConn = remoteConn;
this.kcp = new KCP(this.RemoteConn, new IntPtr(this.LocalConn));
SetOutput();
kcp.NoDelay(1, 10, 1, 1);
kcp.WndSize(32, 32);
kcp.SetMTU(470);
this.lastRecvTime = this.GetService().TimeNow;
Connect();
}
/// <summary>
/// 发送请求连接消息
/// </summary>
private void Connect()
{
try
{
uint timeNow = this.GetService().TimeNow;
this.lastRecvTime = timeNow;
byte[] buffer = this.memoryStream.GetBuffer();
buffer.WriteTo(0, 4);
buffer.WriteTo(4, KcpProtocalType.SYN);
Send(buffer,0,6);
HandleSend();
}
catch (Exception e)
{
Debug.LogError(e);
this.OnError(ErrorCode.ERR_SocketCantSend);
}
}
/// <summary>
/// 发送请求断开消息
/// </summary>
private void Disconnect()
{
if (this.socket == null)
{
return;
}
try
{
byte[] buffer = this.memoryStream.GetBuffer();
buffer.WriteTo(0, 4);
buffer.WriteTo(4, KcpProtocalType.FIN);
Send(buffer,0,6);
HandleSend();
}
catch (Exception e)
{
Debug.LogError(e);
this.OnError(ErrorCode.ERR_SocketCantSend);
}
}
public void Update()
{
uint timeNow = this.GetService().TimeNow;
// 如果还没连接上,发送连接请求
if (!this.isConnected)
{
// 10秒没连接上则报错
if (timeNow - this.createTime > 10 * 1000)
{
this.OnError(ErrorCode.ERR_KcpCantConnect);
return;
}
//
// if (timeNow - this.lastRecvTime < 500)
// {
// return;
// }
}
try
{
kcp.Update(timeNow);
}
catch (Exception e)
{
Debug.LogError(e);
this.OnError(ErrorCode.ERR_SocketError);
return;
}
if (this.kcp != null)
{
uint nextUpdateTime = kcp.Check(timeNow);
}
}
private void HandleSend()
{
while (true)
{
if (this.sendBuffer.Count <= 0)
{
break;
}
WaitSendBuffer buffer = this.sendBuffer.Dequeue();
this.KcpSend(buffer.Bytes, buffer.Length);
}
}
public void HandleRecv(byte[] date, int offset, int length)
{
kcp.Input(date, offset, length);
while (true)
{
int n = kcp.PeekSize();
if (n < 0)
{
return;
}
if (n == 0)
{
this.OnError((int)SocketError.NetworkReset);
return;
}
byte[] buffer = this.memoryStream.GetBuffer();
this.memoryStream.SetLength(n);
this.memoryStream.Seek(0, SeekOrigin.Begin);
int count = kcp.Recv(buffer,0, ushort.MaxValue);
if (n != count)
{
return;
}
if (count <= 0)
{
return;
}
this.lastRecvTime = this.GetService().TimeNow;
if (!isConnected)
{
this.isConnected = true;
OnConnect((int)SocketError.Success);
}
else
{
this.OnRead(this.memoryStream);
}
}
}
public override void Start()
{
}
public void Output(byte[] bytes, int count)
{
try
{
if (count == 0)
{
Debug.LogError($"output 0");
return;
}
byte[] buffer = this.memoryStream.GetBuffer();
Buffer.BlockCopy(bytes, 0,buffer, 0, count);
this.socket.SendTo(buffer, 0, count, SocketFlags.None, this.remoteEndPoint);
}
catch (Exception e)
{
Debug.LogError(e);
this.OnError(ErrorCode.ERR_SocketCantSend);
}
}
private KCP.OutputDelegate kcpOutput;
public void SetOutput()
{
kcpOutput = KcpOutput;
kcp.SetOutput(kcpOutput);
}
public static void KcpOutput(byte[] bytes, int len, object user)
{
KService.Output(bytes, len, user);
}
private void KcpSend(byte[] buffers, int length)
{
kcp.Send(buffers,0, length);
}
private void Send(byte[] buffer, int index, int length)
{
if (isConnected)
{
this.KcpSend(buffer, length);
return;
}
this.sendBuffer.Enqueue(new WaitSendBuffer(buffer, length));
}
public override void Send(MemoryStream stream)
{
if (this.kcp != null)
{
// 检查等待发送的消息,如果超出两倍窗口大小,应该断开连接
if (kcp.WaitSnd() > 256 * 2)
{
this.OnError(ErrorCode.ERR_KcpWaitSendSizeTooLarge);
return;
}
}
ushort size = (ushort)(stream.Length - stream.Position);
byte[] bytes = stream.GetBuffer();
Send(bytes, 0, size);
}
}
#endif
}
================================================
FILE: Assets/Scripts/Network/Core/KCP/KChannel.cs.meta
================================================
fileFormatVersion: 2
guid: 5479891425d5a284fb4c8246e1a52d34
timeCreated: 1511491627
licenseType: Free
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
================================================
FILE: Assets/Scripts/Network/Core/KCP/KService.cs
================================================
using System;
using System.Collections.Generic;
using System.Net;
using System.Net.Sockets;
using Microsoft.IO;
using UnityEngine;
namespace UNetwork
{
public static class KcpProtocalType
{
public const short SYN = 101;
public const short ACK = 102;
public const short FIN = 103;
public const short MSG = 104;
}
public sealed class KService : AService
{
public static KService Instance { get; private set; }
// KService创建的时间
public long StartTime{ get; private set; }
// 当前时间 - KService创建的时间
public uint TimeNow { get; private set; }
private Socket socket;
private KChannel channel;
private readonly byte[] cache = new byte[8192];
public readonly RecyclableMemoryStreamManager MemoryStreamManager = new RecyclableMemoryStreamManager();
private EndPoint ipEndPoint = new IPEndPoint(IPAddress.Any, 0);
public KService()
{
this.StartTime = TimeHelper.ClientNow();
this.TimeNow = (uint)(TimeHelper.ClientNow() - this.StartTime);
this.socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
//this.socket.Blocking = false;
this.socket.Bind(new IPEndPoint(IPAddress.Any, 0));
Instance = this;
}
public override void Dispose()
{
this.channel.Dispose();
this.socket.Close();
this.socket = null;
Instance = null;
}
public void Recv()
{
if (this.socket == null)
{
return;
}
while (socket != null && this.socket.Available > 0)
{
int messageLength = 0;
try
{
// switch (flag)
// {
// case KcpProtocalType.ACK: // 连接
// this.channel.OnConnect((int)SocketError.Success);
// break;
// case KcpProtocalType.FIN: // 断开
// break;
// }
messageLength = this.socket.ReceiveFrom(this.cache, ref this.ipEndPoint);
if (messageLength < 1)
{
continue;
}
this.channel.HandleRecv(this.cache, 0, messageLength);
}
catch (Exception e)
{
Debug.LogError(e);
}
}
}
public KChannel GetKChannel()
{
return (KChannel)channel;
}
public override AChannel GetChannel()
{
return this.channel;
}
#if dynamic_kcp
public static void Output(IntPtr bytes, int count, IntPtr user)
#else
public static void Output(byte[] bytes, int count, object user)
#endif
{
if (Instance == null)
{
return;
}
KChannel kChannel = Instance.GetKChannel();
if (kChannel == null)
{
Debug.LogError($"not found kchannel, {(uint)user}");
return;
}
kChannel.Output(bytes, count);
}
public override AChannel ConnectChannel(IPEndPoint remoteEndPoint)
{
uint localConn = (uint)RandomHelper.RandomNumber(1000, int.MaxValue);
this.channel = new KChannel(localConn, this.socket, remoteEndPoint, this);
return channel;
}
public override AChannel ConnectChannel(string address)
{
IPEndPoint ipEndPoint2 = NetworkHelper.ToIPEndPoint(address);
return this.ConnectChannel(ipEndPoint2);
}
public override void Update()
{
if (Instance == null)
{
return;
}
this.TimeNow = (uint) (TimeHelper.ClientNow() - this.StartTime);
this.Recv();
this.channel.Update();
}
}
}
================================================
FILE: Assets/Scripts/Network/Core/KCP/KService.cs.meta
================================================
fileFormatVersion: 2
guid: 38037f5390cd34e41849290ca1737863
timeCreated: 1511491627
licenseType: Free
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
================================================
FILE: Assets/Scripts/Network/Core/KCP/KcpDll.cs
================================================
using System;
using System.Runtime.InteropServices;
namespace UNetwork
{
public delegate int KcpOutput(IntPtr buf, int len, IntPtr kcp, IntPtr user);
public class KcpDll
{
#if UNITY_IPHONE && !UNITY_EDITOR
const string KcpDLL = "__Internal";
#else
const string KcpDLL = "kcp";
#endif
[DllImport(KcpDLL, CallingConvention=CallingConvention.Cdecl)]
private static extern uint ikcp_check(IntPtr kcp, uint current);
[DllImport(KcpDLL, CallingConvention=CallingConvention.Cdecl)]
private static extern IntPtr ikcp_create(uint conv, IntPtr user);
[DllImport(KcpDLL, CallingConvention=CallingConvention.Cdecl)]
private static extern void ikcp_flush(IntPtr kcp);
[DllImport(KcpDLL, CallingConvention=CallingConvention.Cdecl)]
private static extern uint ikcp_getconv(IntPtr ptr);
[DllImport(KcpDLL, CallingConvention=CallingConvention.Cdecl)]
private static extern int ikcp_input(IntPtr kcp, byte[] data, int offset, int size);
[DllImport(KcpDLL, CallingConvention=CallingConvention.Cdecl)]
private static extern int ikcp_nodelay(IntPtr kcp, int nodelay, int interval, int resend, int nc);
[DllImport(KcpDLL, CallingConvention=CallingConvention.Cdecl)]
private static extern int ikcp_peeksize(IntPtr kcp);
[DllImport(KcpDLL, CallingConvention=CallingConvention.Cdecl)]
private static extern int ikcp_recv(IntPtr kcp, byte[] buffer, int len);
[DllImport(KcpDLL, CallingConvention=CallingConvention.Cdecl)]
private static extern void ikcp_release(IntPtr kcp);
[DllImport(KcpDLL, CallingConvention=CallingConvention.Cdecl)]
private static extern int ikcp_send(IntPtr kcp, byte[] buffer, int len);
[DllImport(KcpDLL, CallingConvention=CallingConvention.Cdecl)]
private static extern void ikcp_setminrto(IntPtr ptr, int minrto);
[DllImport(KcpDLL, CallingConvention=CallingConvention.Cdecl)]
private static extern int ikcp_setmtu(IntPtr kcp, int mtu);
[DllImport(KcpDLL, CallingConvention=CallingConvention.Cdecl)]
private static extern void ikcp_setoutput(IntPtr kcp, KcpOutput output);
[DllImport(KcpDLL, CallingConvention=CallingConvention.Cdecl)]
private static extern void ikcp_update(IntPtr kcp, uint current);
[DllImport(KcpDLL, CallingConvention=CallingConvention.Cdecl)]
private static extern int ikcp_waitsnd(IntPtr kcp);
[DllImport(KcpDLL, CallingConvention=CallingConvention.Cdecl)]
private static extern int ikcp_wndsize(IntPtr kcp, int sndwnd, int rcvwnd);
public static uint KcpCheck(IntPtr kcp, uint current)
{
if (kcp == IntPtr.Zero)
{
throw new Exception($"kcp error, kcp point is zero");
}
return ikcp_check(kcp, current);
}
public static IntPtr KcpCreate(uint conv, IntPtr user)
{
return ikcp_create(conv, user);
}
public static void KcpFlush(IntPtr kcp)
{
if (kcp == IntPtr.Zero)
{
throw new Exception($"kcp error, kcp point is zero");
}
ikcp_flush(kcp);
}
public static uint KcpGetconv(IntPtr ptr)
{
if (ptr == IntPtr.Zero)
{
throw new Exception($"kcp error, kcp point is zero");
}
return ikcp_getconv(ptr);
}
public static int KcpInput(IntPtr kcp, byte[] data, int offset, int size)
{
if (kcp == IntPtr.Zero)
{
throw new Exception($"kcp error, kcp point is zero");
}
return ikcp_input(kcp, data, offset, size);
}
public static int KcpNodelay(IntPtr kcp, int nodelay, int interval, int resend, int nc)
{
if (kcp == IntPtr.Zero)
{
throw new Exception($"kcp error, kcp point is zero");
}
return ikcp_nodelay(kcp, nodelay, interval, resend, nc);
}
public static int KcpPeeksize(IntPtr kcp)
{
if (kcp == IntPtr.Zero)
{
throw new Exception($"kcp error, kcp point is zero");
}
return ikcp_peeksize(kcp);
}
public static int KcpRecv(IntPtr kcp, byte[] buffer, int len)
{
if (kcp == IntPtr.Zero)
{
throw new Exception($"kcp error, kcp point is zero");
}
return ikcp_recv(kcp, buffer, len);
}
public static void KcpRelease(IntPtr kcp)
{
if (kcp == IntPtr.Zero)
{
throw new Exception($"kcp error, kcp point is zero");
}
ikcp_release(kcp);
}
public static int KcpSend(IntPtr kcp, byte[] buffer, int len)
{
if (kcp == IntPtr.Zero)
{
throw new Exception($"kcp error, kcp point is zero");
}
return ikcp_send(kcp, buffer, len);
}
public static void KcpSetminrto(IntPtr kcp, int minrto)
{
if (kcp == IntPtr.Zero)
{
throw new Exception($"kcp error, kcp point is zero");
}
ikcp_setminrto(kcp, minrto);
}
public static int KcpSetmtu(IntPtr kcp, int mtu)
{
if (kcp == IntPtr.Zero)
{
throw new Exception($"kcp error, kcp point is zero");
}
return ikcp_setmtu(kcp, mtu);
}
public static void KcpSetoutput(IntPtr kcp, KcpOutput output)
{
if (kcp == IntPtr.Zero)
{
throw new Exception($"kcp error, kcp point is zero");
}
ikcp_setoutput(kcp, output);
}
public static void KcpUpdate(IntPtr kcp, uint current)
{
if (kcp == IntPtr.Zero)
{
throw new Exception($"kcp error, kcp point is zero");
}
ikcp_update(kcp, current);
}
public static int KcpWaitsnd(IntPtr kcp)
{
if (kcp == IntPtr.Zero)
{
throw new Exception($"kcp error, kcp point is zero");
}
return ikcp_waitsnd(kcp);
}
public static int KcpWndsize(IntPtr kcp, int sndwnd, int rcvwnd)
{
if (kcp == IntPtr.Zero)
{
throw new Exception($"kcp error, kcp point is zero");
}
return ikcp_wndsize(kcp, sndwnd, rcvwnd);
}
}
}
================================================
FILE: Assets/Scripts/Network/Core/KCP/KcpDll.cs.meta
================================================
fileFormatVersion: 2
guid: 0832a74dcd3e44341bcffd3b1f182419
timeCreated: 1511491627
licenseType: Free
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
================================================
FILE: Assets/Scripts/Network/Core/KCP.meta
================================================
fileFormatVersion: 2
guid: 80771ba2b140e0f47b8df6dfe75d5c68
folderAsset: yes
timeCreated: 1511491627
licenseType: Free
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:
================================================
FILE: Assets/Scripts/Network/Core/TCP/PacketParser.cs
================================================
using System;
using System.IO;
namespace UNetwork
{
public enum ParserState
{
PacketSize,
PacketBody
}
public static class Packet
{
public const int PacketSizeLength2 = 2;
public const int PacketSizeLength4 = 4;
public const int MinPacketSize = 2;
public const int OpcodeIndex = 0;
public const int MessageIndex = 2;
}
public class PacketParser
{
private readonly CircularBuffer buffer;
private int packetSize;
private ParserState state;
public MemoryStream memoryStream;
private bool isOK;
private readonly int packetSizeLength;
public PacketParser(int packetSizeLength, CircularBuffer buffer, MemoryStream memoryStream)
{
this.packetSizeLength = packetSizeLength;
this.buffer = buffer;
this.memoryStream = memoryStream;
}
public bool Parse()
{
if (this.isOK)
{
return true;
}
bool finish = false;
while (!finish)
{
switch (this.state)
{
case ParserState.PacketSize:
if (this.buffer.Length < this.packetSizeLength)
{
finish = true;
}
else
{
this.buffer.Read(this.memoryStream.GetBuffer(), 0, this.packetSizeLength);
switch (this.packetSizeLength)
{
case Packet.PacketSizeLength4:
this.packetSize = BitConverter.ToInt32(this.memoryStream.GetBuffer(), 0);
if (this.packetSize > ushort.MaxValue * 16 || this.packetSize < Packet.MinPacketSize)
{
throw new Exception($"recv packet size error, 可能是外网探测端口: {this.packetSize}");
}
break;
case Packet.PacketSizeLength2:
this.packetSize = BitConverter.ToUInt16(this.memoryStream.GetBuffer(), 0);
if (this.packetSize > ushort.MaxValue || this.packetSize < Packet.MinPacketSize)
{
throw new Exception($"recv packet size error:, 可能是外网探测端口: {this.packetSize}");
}
break;
default:
throw new Exception("packet size byte count must be 2 or 4!");
}
this.state = ParserState.PacketBody;
}
break;
case ParserState.PacketBody:
if (this.buffer.Length < this.packetSize)
{
finish = true;
}
else
{
this.memoryStream.Seek(0, SeekOrigin.Begin);
this.memoryStream.SetLength(this.packetSize);
byte[] bytes = this.memoryStream.GetBuffer();
this.buffer.Read(bytes, 0, this.packetSize);
this.isOK = true;
this.state = ParserState.PacketSize;
finish = true;
}
break;
}
}
return this.isOK;
}
public MemoryStream GetPacket()
{
this.isOK = false;
return this.memoryStream;
}
}
}
================================================
FILE: Assets/Scripts/Network/Core/TCP/PacketParser.cs.meta
================================================
fileFormatVersion: 2
guid: 8b71d12882faac44992e531533491a5f
timeCreated: 1503986857
licenseType: Free
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
================================================
FILE: Assets/Scripts/Network/Core/TCP/TChannel.cs
================================================
using System;
using System.IO;
using System.Net;
using System.Net.Sockets;
using UnityEngine;
namespace UNetwork
{
/// <summary>
/// 封装Socket,将回调push到主线程处理
/// </summary>
public sealed class TChannel: AChannel
{
private Socket socket;
private SocketAsyncEventArgs innArgs = new SocketAsyncEventArgs();
private SocketAsyncEventArgs outArgs = new SocketAsyncEventArgs();
private readonly CircularBuffer recvBuffer = new CircularBuffer();
private readonly CircularBuffer sendBuffer = new CircularBuffer();
private bool isSending;
private bool isRecving;
private bool isConnected;
private readonly PacketParser parser;
private readonly byte[] packetSizeCache;
public TChannel(IPEndPoint ipEndPoint, TService service): base(service, ChannelType.Connect)
{
int packetSize = service.PacketSizeLength;
this.packetSizeCache = new byte[packetSize];
this.memoryStream = service.MemoryStreamManager.GetStream("message", ushort.MaxValue);
this.socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
this.socket.NoDelay = true;
this.parser = new PacketParser(packetSize, this.recvBuffer, this.memoryStream);
this.innArgs.Completed += this.OnComplete;
this.outArgs.Completed += this.OnComplete;
this.RemoteAddress = ipEndPoint;
this.isConnected = false;
this.isSending = false;
}
public override void Dispose()
{
this.socket.Close();
this.innArgs.Dispose();
this.outArgs.Dispose();
this.innArgs = null;
this.outArgs = null;
this.socket = null;
this.memoryStream.Dispose();
}
private TService GetService()
{
return (TService)this.Service;
}
public override void Start()
{
if (!this.isConnected)
{
this.ConnectAsync(this.RemoteAddress);
return;
}
if (!this.isRecving)
{
this.isRecving = true;
this.StartRecv();
}
}
public override void Send(MemoryStream stream)
{
switch (this.GetService().PacketSizeLength)
{
case Packet.PacketSizeLength4:
if (stream.Length > ushort.MaxValue * 16)
{
throw new Exception($"send packet too large: {stream.Length}");
}
this.packetSizeCache.WriteTo(0, (int) stream.Length);
break;
case Packet.PacketSizeLength2:
if (stream.Length > ushort.MaxValue)
{
throw new Exception($"send packet too large: {stream.Length}");
}
this.packetSizeCache.WriteTo(0, (ushort) stream.Length);
break;
default:
throw new Exception("packet size must be 2 or 4!");
}
this.sendBuffer.Write(this.packetSizeCache, 0, this.packetSizeCache.Length);
this.sendBuffer.Write(stream);
}
private void OnComplete(object sender, SocketAsyncEventArgs e)
{
switch (e.LastOperation)
{
case SocketAsyncOperation.Connect:
OneThreadSynchronizationContext.Instance.Post(this.OnConnectComplete, e);
break;
case SocketAsyncOperation.Receive:
OneThreadSynchronizationContext.Instance.Post(this.OnRecvComplete, e);
break;
case SocketAsyncOperation.Send:
OneThreadSynchronizationContext.Instance.Post(this.OnSendComplete, e);
break;
case SocketAsyncOperation.Disconnect:
OneThreadSynchronizationContext.Instance.Post(this.OnDisconnectComplete, e);
break;
default:
throw new Exception($"socket error: {e.LastOperation}");
}
}
public void ConnectAsync(IPEndPoint ipEndPoint)
{
this.outArgs.RemoteEndPoint = ipEndPoint;
if (this.socket.ConnectAsync(this.outArgs))
{
return;
}
OnConnectComplete(this.outArgs);
}
private void OnConnectComplete(object o)
{
if (this.socket == null)
{
return;
}
SocketAsyncEventArgs e = (SocketAsyncEventArgs) o;
if (e.SocketError != SocketError.Success)
{
this.OnError((int)e.SocketError);
return;
}
e.RemoteEndPoint = null;
this.isConnected = true;
this.OnConnect((int)SocketError.Success);
this.Start();
}
private void OnDisconnectComplete(object o)
{
SocketAsyncEventArgs e = (SocketAsyncEventArgs)o;
this.OnError((int)e.SocketError);
}
private void StartRecv()
{
int size = this.recvBuffer.ChunkSize - this.recvBuffer.LastIndex;
this.RecvAsync(this.recvBuffer.Last, this.recvBuffer.LastIndex, size);
}
public void RecvAsync(byte[] buffer, int offset, int count)
{
try
{
this.innArgs.SetBuffer(buffer, offset, count);
}
catch (Exception e)
{
throw new Exception($"socket set buffer error: {buffer.Length}, {offset}, {count}", e);
}
if (this.socket.ReceiveAsync(this.innArgs))
{
return;
}
OnRecvComplete(this.innArgs);
}
private void OnRecvComplete(object o)
{
if (this.socket == null)
{
return;
}
SocketAsyncEventArgs e = (SocketAsyncEventArgs) o;
if (e.SocketError != SocketError.Success)
{
this.OnError((int)e.SocketError);
return;
}
if (e.BytesTransferred == 0)
{
this.OnError(ErrorCode.ERR_PeerDisconnect);
return;
}
this.recvBuffer.LastIndex += e.BytesTransferred;
if (this.recvBuffer.LastIndex == this.recvBuffer.ChunkSize)
{
this.recvBuffer.AddLast();
this.recvBuffer.LastIndex = 0;
}
// 收到消息回调
while (true)
{
try
{
if (!this.parser.Parse())
{
break;
}
}
catch (Exception ee)
{
Debug.LogError($"ip: {this.RemoteAddress} {ee}");
this.OnError(ErrorCode.ERR_SocketError);
return;
}
try
{
this.OnRead(this.parser.GetPacket());
}
catch (Exception ee)
{
Debug.LogError(ee);
}
}
if (this.socket == null)
{
return;
}
this.StartRecv();
}
public bool IsSending => this.isSending;
public void StartSend()
{
if(!this.isConnected)
{
return;
}
// 没有数据需要发送
if (this.sendBuffer.Length == 0)
{
this.isSending = false;
return;
}
this.isSending = true;
int sendSize = this.sendBuffer.ChunkSize - this.sendBuffer.FirstIndex;
if (sendSize > this.sendBuffer.Length)
{
sendSize = (int)this.sendBuffer.Length;
}
this.SendAsync(this.sendBuffer.First, this.sendBuffer.FirstIndex, sendSize);
}
public void SendAsync(byte[] buffer, int offset, int count)
{
try
{
this.outArgs.SetBuffer(buffer, offset, count);
}
catch (Exception e)
{
throw new Exception($"socket set buffer error: {buffer.Length}, {offset}, {count}", e);
}
if (this.socket.SendAsync(this.outArgs))
{
return;
}
OnSendComplete(this.outArgs);
}
private void OnSendComplete(object o)
{
if (this.socket == null)
{
return;
}
SocketAsyncEventArgs e = (SocketAsyncEventArgs) o;
if (e.SocketError != SocketError.Success)
{
this.OnError((int)e.SocketError);
return;
}
if (e.BytesTransferred == 0)
{
this.OnError(ErrorCode.ERR_PeerDisconnect);
return;
}
this.sendBuffer.FirstIndex += e.BytesTransferred;
if (this.sendBuffer.FirstIndex == this.sendBuffer.ChunkSize)
{
this.sendBuffer.FirstIndex = 0;
this.sendBuffer.RemoveFirst();
}
this.StartSend();
}
}
}
================================================
FILE: Assets/Scripts/Network/Core/TCP/TChannel.cs.meta
================================================
fileFormatVersion: 2
guid: 4cacc90d7e561c64a8ea0e9079163bb9
timeCreated: 1503986857
licenseType: Free
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
================================================
FILE: Assets/Scripts/Network/Core/TCP/TChannelConnector.cs
================================================
using System;
using System.IO;
using System.Net.Sockets;
using System.Text;
using UnityEngine;
using UnityEngine.Events;
namespace UNetwork
{
/// <summary>
/// 管理客户端连接的类
/// </summary>
public sealed class TClientConnection : AChannel
{
private int PacketSizeLength;
private readonly Socket clientSocket;
private readonly SocketAsyncEventArgs innArgs = new SocketAsyncEventArgs();
private readonly SocketAsyncEventArgs outArgs = new SocketAsyncEventArgs();
private readonly CircularBuffer recvBuffer = new CircularBuffer();
private readonly CircularBuffer sendBuffer = new CircularBuffer();
private readonly PacketParser parser;
private readonly byte[] packetSizeCache;
private bool isConnected;
private bool isSending;
private bool isRecving;
private readonly SessionConnector session;
public UnityAction<TClientConnection> OnDisposeCallback;
public TClientConnection(Socket clientSocket, TServiceServer service) : base(service, ChannelType.Connect)
{
this.session = new SessionConnector(this);
this.clientSocket = clientSocket;
this.memoryStream = service.MemoryStreamManager.GetStream("client", ushort.MaxValue);
int packetSize = service.PacketSizeLength;
this.PacketSizeLength = packetSize;
this.packetSizeCache = new byte[packetSize];
this.parser = new PacketParser(packetSize, this.recvBuffer, this.memoryStream);
this.innArgs.Completed += this.OnComplete;
this.outArgs.Completed += this.OnComplete;
isConnected = false;
}
public override void Dispose()
{
OnDisposeCallback?.Invoke(this);
this.clientSocket.Close();
this.innArgs.Dispose();
this.outArgs.Dispose();
this.memoryStream.Dispose();
}
public override void Start()
{
if (!this.isRecving)
{
this.isRecving = true;
this.StartRecv();
this.isConnected = true;
}
}
public void Update()
{
if (isSending)
{
return;
}
try
{
StartSend();
}
catch (Exception e)
{
Debug.LogError(e);
}
}
private void OnComplete(object sender, SocketAsyncEventArgs e)
{
switch (e.LastOperation)
{
case SocketAsyncOperation.Receive:
OneThreadSynchronizationContext.Instance.Post(this.OnRecvComplete, e);
break;
case SocketAsyncOperation.Send:
OneThreadSynchronizationContext.Instance.Post(this.OnSendComplete, e);
break;
case SocketAsyncOperation.Disconnect:
OneThreadSynchronizationContext.Instance.Post(this.OnDisconnectComplete, e);
break;
default:
throw new Exception($"socket error: {e.LastOperation}");
}
}
private void OnDisconnectComplete(object o)
{
SocketAsyncEventArgs e = (SocketAsyncEventArgs)o;
this.OnError((int)e.SocketError);
}
private void StartRecv()
{
int size = this.recvBuffer.ChunkSize - this.recvBuffer.LastIndex;
this.RecvAsync(this.recvBuffer.Last, this.recvBuffer.LastIndex, size);
}
public void RecvAsync(byte[] buffer, int offset, int count)
{
try
{
this.innArgs.SetBuffer(buffer, offset, count);
}
catch (Exception e)
{
throw new Exception($"socket set buffer error: {buffer.Length}, {offset}, {count}", e);
}
if (this.clientSocket.ReceiveAsync(this.innArgs))
{
return;
}
OnRecvComplete(this.innArgs);
}
private void OnRecvComplete(object o)
{
if (this.clientSocket == null)
{
return;
}
SocketAsyncEventArgs e = (SocketAsyncEventArgs)o;
if (e.SocketError != SocketError.Success)
{
this.OnError((int)e.SocketError);
return;
}
if (e.BytesTransferred == 0)
{
this.OnError(ErrorCode.ERR_PeerDisconnect);
return;
}
this.recvBuffer.LastIndex += e.BytesTransferred;
if (this.recvBuffer.LastIndex == this.recvBuffer.ChunkSize)
{
this.recvBuffer.AddLast();
this.recvBuffer.LastIndex = 0;
}
// 收到消息回调
while (true)
{
try
{
if (!this.parser.Parse())
{
break;
}
}
catch (Exception ee)
{
Debug.LogError($"Client {clientSocket.RemoteEndPoint} {ee}");
this.OnError(ErrorCode.ERR_SocketError);
return;
}
try
{
this.OnRead(this.parser.GetPacket());
}
catch (Exception ee)
{
Debug.LogError(ee);
}
}
this.StartRecv();
}
public override void Send(MemoryStream stream)
{
switch (PacketSizeLength)
{
case Packet.PacketSizeLength4:
if (stream.Length > ushort.MaxValue * 16)
{
throw new Exception($"send packet too large: {stream.Length}");
}
this.packetSizeCache.WriteTo(0, (int)stream.Length);
break;
case Packet.PacketSizeLength2:
if (stream.Length > ushort.MaxValue)
{
throw new Exception($"send packet too large: {stream.Length}");
}
this.packetSizeCache.WriteTo(0, (ushort)stream.Length);
break;
default:
throw new Exception("packet size must be 2 or 4!");
}
this.sendBuffer.Write(this.packetSizeCache, 0, this.packetSizeCache.Length);
this.sendBuffer.Write(stream);
}
public void StartSend()
{
if (!this.isConnected)
{
return;
}
// 没有数据需要发送
if (this.sendBuffer.Length == 0)
{
this.isSending = false;
return;
}
if (!this.isSending)
{
this.isSending = true;
}
int sendSize = this.sendBuffer.ChunkSize - this.sendBuffer.FirstIndex;
if (sendSize > this.sendBuffer.Length)
{
sendSize = (int)this.sendBuffer.Length;
}
this.SendAsync(this.sendBuffer.First, this.sendBuffer.FirstIndex, sendSize);
}
public void SendAsync(byte[] buffer, int offset, int count)
{
try
{
this.outArgs.SetBuffer(buffer, offset, count);
}
catch (Exception e)
{
throw new Exception($"socket set buffer error: {buffer.Length}, {offset}, {count}", e);
}
if (this.clientSocket.SendAsync(this.outArgs))
{
return;
}
OnSendComplete(this.outArgs);
}
private void OnSendComplete(object o)
{
SocketAsyncEventArgs e = (SocketAsyncEventArgs)o;
if (e.SocketError != SocketError.Success)
{
this.OnError((int)e.SocketError);
return;
}
if (e.BytesTransferred == 0)
{
this.OnError(ErrorCode.ERR_PeerDisconnect);
return;
}
this.sendBuffer.FirstIndex += e.BytesTransferred;
if (this.sendBuffer.FirstIndex == this.sendBuffer.ChunkSize)
{
this.sendBuffer.FirstIndex = 0;
this.sendBuffer.RemoveFirst();
}
this.StartSend();
}
private new void OnError(int error)
{
Debug.LogError($"Socket error: {error}");
this.Dispose();
}
private void OnMessage(byte[] obj)
{
var msg = Encoding.UTF8.GetString(obj);
Debug.Log($"Receive{obj.Length}" + msg);
}
}
}
================================================
FILE: Assets/Scripts/Network/Core/TCP/TChannelConnector.cs.meta
================================================
fileFormatVersion: 2
guid: 1740169c35694ff9aa464756e50c4646
timeCreated: 1719314153
================================================
FILE: Assets/Scripts/Network/Core/TCP/TChannelServer.cs
================================================
using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Net.Sockets;
using UnityEngine;
namespace UNetwork
{
/// <summary>
/// 封装 Server 端Socket监听
/// </summary>
public sealed class TChannelServer : AChannel
{
private Socket listener;
private List<TClientConnection> clientConnections = new List<TClientConnection>();
private SocketAsyncEventArgs acceptArgs = new SocketAsyncEventArgs();
private readonly PacketParser parser;
private readonly TServiceServer service;
private bool isSending;
private bool isRecving;
public TChannelServer(IPEndPoint ipEndPoint, TServiceServer service) : base(service, ChannelType.Accept)
{
this.service = service;
this.memoryStream = service.MemoryStreamManager.GetStream("server", ushort.MaxValue);
this.listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
listener.Bind(ipEndPoint);
listener.Listen(10); // 最大挂起连接队列的长度
this.listener.NoDelay = true;
Debug.Log("开启监听:" + ipEndPoint);
this.acceptArgs.Completed += this.OnAcceptComplete;
}
public void Update()
{
foreach (var connection in clientConnections)
{
connection.Update();
}
}
public override void Send(MemoryStream stream)
{
foreach (var connection in clientConnections)
{
connection.Send(stream);
}
}
public override void Dispose()
{
this.listener.Close();
foreach (var clientConnection in this.clientConnections)
{
clientConnection.Dispose();
}
this.acceptArgs.Dispose();
this.listener = null;
}
public override void Start()
{
this.AcceptAsync();
}
private void AcceptAsync()
{
acceptArgs.AcceptSocket = null; // Reset AcceptSocket
listener.AcceptAsync(acceptArgs);
}
private void OnAcceptComplete(object sender, SocketAsyncEventArgs e)
{
if (this.listener == null)
{
return;
}
if (e.SocketError != SocketError.Success)
{
this.OnError((int)e.SocketError);
return;
}
Debug.Log("客户端连接成功:" + e.RemoteEndPoint);
Socket clientSocket = e.AcceptSocket;
TClientConnection clientConnection = new TClientConnection(clientSocket, this.service);
clientConnections.Add(clientConnection);
clientConnection.Start();
clientConnection.OnDisposeCallback=OnDisconnect;
// Start accepting next client
this.AcceptAsync();
}
public void OnDisconnect(TClientConnection connection)
{
clientConnections.Remove(connection);
}
}
}
================================================
FILE: Assets/Scripts/Network/Core/TCP/TChannelServer.cs.meta
================================================
fileFormatVersion: 2
guid: e1134ac288dc42f2892e29f9f7c754e0
timeCreated: 1719304015
================================================
FILE: Assets/Scripts/Network/Core/TCP/TService.cs
================================================
using System;
using System.Net;
using System.Net.Sockets;
using Microsoft.IO;
using UnityEngine;
namespace UNetwork
{
/// <summary>
/// TChannle的一个封装管理
/// </summary>
public sealed class TService : AService
{
private TChannel channel;
public RecyclableMemoryStreamManager MemoryStreamManager = new RecyclableMemoryStreamManager();
public int PacketSizeLength { get; }
public TService(int packetSizeLength)
{
this.PacketSizeLength = packetSizeLength;
}
public override void Dispose()
{
this.channel.Dispose();
}
public override AChannel GetChannel()
{
return channel;
}
public override AChannel ConnectChannel(IPEndPoint ipEndPoint)
{
channel = new TChannel(ipEndPoint, this);
return channel;
}
public override AChannel ConnectChannel(string address)
{
IPEndPoint ipEndPoint = NetworkHelper.ToIPEndPoint(address);
return this.ConnectChannel(ipEndPoint);
}
public override void Update()
{
if (channel.IsSending)
{
return;
}
try
{
channel.StartSend();
}
catch (Exception e)
{
Debug.LogError(e);
}
}
}
}
================================================
FILE: Assets/Scripts/Network/Core/TCP/TService.cs.meta
================================================
fileFormatVersion: 2
guid: 9c6cb526a0e4374438cbcbaa70239e4a
timeCreated: 1503986857
licenseType: Free
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
================================================
FILE: Assets/Scripts/Network/Core/TCP/TServiceServer.cs
================================================
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using Microsoft.IO;
using UnityEngine;
namespace UNetwork
{
public sealed class TServiceServer : AService
{
private TChannelServer channel;
public RecyclableMemoryStreamManager MemoryStreamManager = new RecyclableMemoryStreamManager();
public int PacketSizeLength { get; }
public TServiceServer(int packetSizeLength)
{
this.PacketSizeLength = packetSizeLength;
}
public override void Dispose()
{
this.channel.Dispose();
}
public override AChannel GetChannel()
{
return channel;
}
public override AChannel ConnectChannel(IPEndPoint ipEndPoint)
{
channel = new TChannelServer(ipEndPoint, this);
return channel;
}
public override AChannel ConnectChannel(string address)
{
IPEndPoint ipEndPoint = NetworkHelper.ToIPEndPoint(address);
return this.ConnectChannel(ipEndPoint);
}
public override void Update()
{
try
{
channel.Update();
}
catch (Exception e)
{
Debug.LogError(e);
}
}
}
}
================================================
FILE: Assets/Scripts/Network/Core/TCP/TServiceServer.cs.meta
================================================
fileFormatVersion: 2
guid: a284183e90dc44f4a26c8434514d7da0
timeCreated: 1719304034
================================================
FILE: Assets/Scripts/Network/Core/TCP.meta
================================================
fileFormatVersion: 2
guid: 2b578de151e7f46489a1326f6b38658c
folderAsset: yes
timeCreated: 1440989101
licenseType: Pro
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:
================================================
FILE: Assets/Scripts/Network/Core/WebSocket/WChannel.cs
================================================
using System;
using System.Collections.Generic;
using System.IO;
using System.Net.WebSockets;
using System.Threading;
using UnityEngine;
namespace UNetwork
{
public class WChannel: AChannel
{
public HttpListenerWebSocketContext WebSocketContext { get; }
private readonly WebSocket webSocket;
private readonly Queue<byte[]> queue = new Queue<byte[]>();
private bool isSending;
private bool isConnected;
private readonly MemoryStream recvStream;
private CancellationTokenSource cancellationTokenSource = new CancellationTokenSource();
public WChannel(HttpListenerWebSocketContext webSocketContext, AService service): base(service, ChannelType.Accept)
{
this.WebSocketContext = webSocketContext;
this.webSocket = webSocketContext.WebSocket;
this.memoryStream = this.GetService().MemoryStreamManager.GetStream("message", ushort.MaxValue);
this.recvStream = this.GetService().MemoryStreamManager.GetStream("message", ushort.MaxValue);
isConnected = true;
}
public WChannel(WebSocket webSocket, AService service): base(service, ChannelType.Connect)
{
this.webSocket = webSocket;
this.memoryStream = this.GetService().MemoryStreamManager.GetStream("message", ushort.MaxValue);
this.recvStream = this.GetService().MemoryStreamManager.GetStream("message", ushort.MaxValue);
isConnected = false;
}
public override void Dispose()
{
this.cancellationTokenSource.Cancel();
this.cancellationTokenSource.Dispose();
this.cancellationTokenSource = null;
this.webSocket.Dispose();
this.memoryStream.Dispose();
}
public override void Start()
{
if (!this.isConnected)
{
return;
}
this.StartRecv();
this.StartSend();
}
private WService GetService()
{
return (WService) this.Service;
}
public async void ConnectAsync(string url)
{
try
{
await ((ClientWebSocket) this.webSocket).ConnectAsync(new Uri(url), cancellationTokenSource.Token);
isConnected = true;
this.Start();
}
catch (Exception e)
{
Debug.LogError(e);
this.OnError(ErrorCode.ERR_WebsocketConnectError);
}
}
public override void Send(MemoryStream stream)
{
byte[] bytes = new byte[stream.Length];
Array.Copy(stream.GetBuffer(), bytes, bytes.Length);
this.queue.Enqueue(bytes);
if (this.isConnected)
{
this.StartSend();
}
}
public async void StartSend()
{
try
{
if (this.isSending)
{
return;
}
this.isSending = true;
while (true)
{
if (this.queue.Count == 0)
{
this.isSending = false;
return;
}
byte[] bytes = this.queue.Dequeue();
try
{
await this.webSocket.SendAsync(new ArraySegment<byte>(bytes, 0, bytes.Length), WebSocketMessageType.Binary, true, cancellationTokenSource.Token);
}
catch (Exception e)
{
Debug.LogError(e);
this.OnError(ErrorCode.ERR_WebsocketSendError);
return;
}
}
}
catch (Exception e)
{
Debug.LogError(e);
}
}
public async void StartRecv()
{
try
{
while (true)
{
WebSocketReceiveResult receiveResult;
int receiveCount = 0;
do
{
receiveResult = await this.webSocket.ReceiveAsync(
new ArraySegment<byte>(this.recvStream.GetBuffer(), receiveCount, this.recvStream.Capacity - receiveCount),
cancellationTokenSource.Token);
receiveCount += receiveResult.Count;
}
while (!receiveResult.EndOfMessage);
if (receiveResult.MessageType == WebSocketMessageType.Close)
{
this.OnError(ErrorCode.ERR_WebsocketPeerReset);
return;
}
if (receiveResult.Count > ushort.MaxValue)
{
await this.webSocket.CloseAsync(WebSocketCloseStatus.MessageTooBig, $"message too big: {receiveResult.Count}",
cancellationTokenSource.Token);
this.OnError(ErrorCode.ERR_WebsocketMessageTooBig);
return;
}
this.recvStream.SetLength(receiveResult.Count);
this.OnRead(this.recvStream);
}
}
catch (Exception e)
{
Debug.LogError(e);
this.OnError(ErrorCode.ERR_WebsocketRecvError);
}
}
}
}
================================================
FILE: Assets/Scripts/Network/Core/WebSocket/WChannel.cs.meta
================================================
fileFormatVersion: 2
guid: 8e9431d46e7e100479fce069d4c08079
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
================================================
FILE: Assets/Scripts/Network/Core/WebSocket/WService.cs
================================================
using System;
using System.Collections.Generic;
using System.Net;
using System.Net.WebSockets;
using Microsoft.IO;
using UnityEngine;
namespace UNetwork
{
public class WService: AService
{
private readonly HttpListener httpListener;
private WChannel channel;
public RecyclableMemoryStreamManager MemoryStreamManager = new RecyclableMemoryStreamManager();
public WService()
{
}
public override AChannel GetChannel()
{
return channel;
}
public override AChannel ConnectChannel(IPEndPoint ipEndPoint)
{
throw new NotImplementedException();
}
public override AChannel ConnectChannel(string address)
{
ClientWebSocket webSocket = new ClientWebSocket();
channel = new WChannel(webSocket, this);
channel.ConnectAsync(address);
return channel;
}
public override void Update()
{
}
public override void Dispose()
{
}
}
}
================================================
FILE: Assets/Scripts/Network/Core/WebSocket/WService.cs.meta
================================================
fileFormatVersion: 2
guid: ab08a203cf5da164c86fbc14d09e3a3b
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
================================================
FILE: Assets/Scripts/Network/Core/WebSocket.meta
================================================
fileFormatVersion: 2
guid: 02cb26b1214c31847af71b0796e90476
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
================================================
FILE: Assets/Scripts/Network/Core.meta
================================================
fileFormatVersion: 2
guid: 819d45d33f6b1124e9159ed5ef0bd490
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
================================================
FILE: Assets/Scripts/Network/INetworkManager.cs
================================================
using System;
namespace UNetwork
{
public interface INetworkManager
{
public IMessagePacker MessagePacker { get; set; }
public IMessageDispatcher MessageDispatcher { get; set; }
public Action<int> OnConnect{ get; set; }
public Action<int> OnError{ get; set; }
public Action<byte[]> OnMessage{ get; set; }
}
}
================================================
FILE: Assets/Scripts/Network/INetworkManager.cs.meta
================================================
fileFormatVersion: 2
guid: ec147b2fba3e42f1a6c41924df308bfb
timeCreated: 1719310787
================================================
FILE: Assets/Scripts/Network/Message/Circularbuffer.cs
================================================
using System;
using System.Collections.Generic;
using System.IO;
using UnityEngine;
namespace UNetwork
{
public class CircularBuffer: Stream
{
public int ChunkSize = 8192;
private readonly Queue<byte[]> bufferQueue = new Queue<byte[]>();
private readonly Queue<byte[]> bufferCache = new Queue<byte[]>();
public int LastIndex { get; set; }
public int FirstIndex { get; set; }
private byte[] lastBuffer;
public CircularBuffer()
{
this.AddLast();
}
public override long Length
{
get
{
int c = 0;
if (this.bufferQueue.Count == 0)
{
c = 0;
}
else
{
c = (this.bufferQueue.Count - 1) * ChunkSize + this.LastIndex - this.FirstIndex;
}
if (c < 0)
{
Debug.LogErrorFormat("CircularBuffer count < 0: {0}, {1}, {2}",this.bufferQueue.Count, this.LastIndex, this.FirstIndex);
}
return c;
}
}
public void AddLast()
{
byte[] buffer;
if (this.bufferCache.Count > 0)
{
buffer = this.bufferCache.Dequeue();
}
else
{
buffer = new byte[ChunkSize];
}
this.bufferQueue.Enqueue(buffer);
this.lastBuffer = buffer;
}
public void RemoveFirst()
{
this.bufferCache.Enqueue(bufferQueue.Dequeue());
}
public byte[] First
{
get
{
if (this.bufferQueue.Count == 0)
{
this.AddLast();
}
return this.bufferQueue.Peek();
}
}
public byte[] Last
{
get
{
if (this.bufferQueue.Count == 0)
{
this.AddLast();
}
return this.lastBuffer;
}
}
/// <summary>
/// 从CircularBuffer读到stream中
/// </summary>
/// <param name="stream"></param>
/// <returns></returns>
public void ReadAsync(Stream stream)
{
long buffLength = this.Length;
int sendSize = this.ChunkSize - this.FirstIndex;
if (sendSize > buffLength)
{
sendSize = (int)buffLength;
}
stream.Write(this.First, this.FirstIndex, sendSize);
this.FirstIndex += sendSize;
if (this.FirstIndex == this.ChunkSize)
{
this.FirstIndex = 0;
this.RemoveFirst();
}
}
// 从CircularBuffer读到stream
public void Read(Stream stream, int count)
{
if (count > this.Length)
{
throw new Exception($"bufferList length < count, {Length} {count}");
}
int alreadyCopyCount = 0;
while (alreadyCopyCount < count)
{
int n = count - alreadyCopyCount;
if (ChunkSize - this.FirstIndex > n)
{
stream.Write(this.First, this.FirstIndex, n);
this.FirstIndex += n;
alreadyCopyCount += n;
}
else
{
stream.Write(this.First, this.FirstIndex, ChunkSize - this.FirstIndex);
alreadyCopyCount += ChunkSize - this.FirstIndex;
this.FirstIndex = 0;
this.RemoveFirst();
}
}
}
// 从stream写入CircularBuffer
public void Write(Stream stream)
{
int count = (int)(stream.Length - stream.Position);
int alreadyCopyCount = 0;
while (alreadyCopyCount < count)
{
if (this.LastIndex == ChunkSize)
{
this.AddLast();
this.LastIndex = 0;
}
int n = count - alreadyCopyCount;
if (ChunkSize - this.LastIndex > n)
{
stream.Read(this.lastBuffer, this.LastIndex, n);
this.LastIndex += count - alreadyCopyCount;
alreadyCopyCount += n;
}
else
{
stream.Read(this.lastBuffer, this.LastIndex, ChunkSize - this.LastIndex);
alreadyCopyCount += ChunkSize - this.LastIndex;
this.LastIndex = ChunkSize;
}
}
}
/// <summary>
/// 从stream写入CircularBuffer
/// </summary>
/// <param name="stream"></param>
/// <returns></returns>
public int WriteAsync(Stream stream)
{
int size = this.ChunkSize - this.LastIndex;
int n = stream.Read(this.Last, this.LastIndex, size);
// int n = await stream.ReadAsync(this.Last, this.LastIndex, size);
if (n == 0)
{
return 0;
}
this.LastIndex += n;
if (this.LastIndex == this.ChunkSize)
{
this.AddLast();
this.LastIndex = 0;
}
return n;
}
// 把CircularBuffer中数据写入buffer
public override int Read(byte[] buffer, int offset, int count)
{
if (buffer.Length < offset + count)
{
throw new Exception($"bufferList length < coutn, buffer length: {buffer.Length} {offset} {count}");
}
long length = this.Length;
if (length < count)
{
count = (int)length;
}
int alreadyCopyCount = 0;
while (alreadyCopyCount < count)
{
int n = count - alreadyCopyCount;
if (ChunkSize - this.FirstIndex > n)
{
Array.Copy(this.First, this.FirstIndex, buffer, alreadyCopyCount + offset, n);
this.FirstIndex += n;
alreadyCopyCount += n;
}
else
{
Array.Copy(this.First, this.FirstIndex, buffer, alreadyCopyCount + offset, ChunkSize - this.FirstIndex);
alreadyCopyCount += ChunkSize - this.FirstIndex;
this.FirstIndex = 0;
this.RemoveFirst();
}
}
return count;
}
// 把buffer写入CircularBuffer中
public override void Write(byte[] buffer, int offset, int count)
{
int alreadyCopyCount = 0;
while (alreadyCopyCount < count)
{
if (this.LastIndex == ChunkSize)
{
this.AddLast();
this.LastIndex = 0;
}
int n = count - alreadyCopyCount;
if (ChunkSize - this.LastIndex > n)
{
Array.Copy(buffer, alreadyCopyCount + offset, this.lastBuffer, this.LastIndex, n);
this.LastIndex += count - alreadyCopyCount;
alreadyCopyCount += n;
}
else
{
Array.Copy(buffer, alreadyCopyCount + offset, this.lastBuffer, this.LastIndex, ChunkSize - this.LastIndex);
alreadyCopyCount += ChunkSize - this.LastIndex;
this.LastIndex = ChunkSize;
}
}
}
public override void Flush()
{
throw new NotImplementedException();
}
public override long Seek(long offset, SeekOrigin origin)
{
throw new NotImplementedException();
}
public override void SetLength(long value)
{
throw new NotImplementedException();
}
public override bool CanRead
{
get
{
return true;
}
}
public override bool CanSeek
{
get
{
return false;
}
}
public override bool CanWrite
{
get
{
return true;
}
}
public override long Position { get; set; }
}
}
================================================
FILE: Assets/Scripts/Network/Message/Circularbuffer.cs.meta
================================================
fileFormatVersion: 2
guid: ea037025225a9c74b8ddb5349b0c18a6
timeCreated: 1503986858
licenseType: Free
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
================================================
FILE: Assets/Scripts/Network/Message/ErrorCode.cs
================================================
namespace UNetwork
{
public static class ErrorCode
{
public const int ERR_Success = 0;
// 1-11004 是SocketError请看SocketError定义
//-----------------------------------
// 100000 以上,避免跟SocketError冲突
public const int ERR_MyErrorCode = 100000;
public const int ERR_NotFoundActor = 100002;
public const int ERR_ActorNoMailBoxComponent = 100003;
public const int ERR_ActorRemove = 100004;
public const int ERR_PacketParserError = 100005;
public const int ERR_ConnectGateKeyError = 100006;
public const int ERR_KcpCantConnect = 102005;
public const int ERR_KcpChannelTimeout = 102006;
public const int ERR_KcpRemoteDisconnect = 102007;
public const int ERR_PeerDisconnect = 102008;
public const int ERR_SocketCantSend = 102009;
public const int ERR_SocketError = 102010;
public const int ERR_KcpWaitSendSizeTooLarge = 102011;
public const int ERR_WebsocketPeerReset = 103001;
public const int ERR_WebsocketMessageTooBig = 103002;
public const int ERR_WebsocketError = 103003;
public const int ERR_WebsocketConnectError = 103004;
public const int ERR_WebsocketSendError = 103005;
public const int ERR_WebsocketRecvError = 103006;
public const int ERR_ReloadFail = 102003;
//-----------------------------------
// 小于这个Rpc会抛异常,大于这个异常的error需要自己判断处理,也就是说需要处理的错误应该要大于该值
public const int ERR_Exception = 200000;
public const int ERR_AccountOrPasswordError = 200102;
}
}
================================================
FILE: Assets/Scripts/Network/Message/ErrorCode.cs.meta
================================================
fileFormatVersion: 2
guid: 303bb884f0f9ad24da9b0fe1acbcedaf
timeCreated: 1501467234
licenseType: Free
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
================================================
FILE: Assets/Scripts/Network/Message/IMessage.cs
================================================
namespace UNetwork
{
public interface IMessage
{
}
public interface IRequest: IMessage
{
int RpcId { get; set; }
}
public interface IResponse : IMessage
{
int Error { get; set; }
string Message { get; set; }
int RpcId { get; set; }
}
public class ErrorResponse : IResponse
{
public int Error { get; set; }
public string Message { get; set; }
public int RpcId { get; set; }
}
}
================================================
FILE: Assets/Scripts/Network/Message/IMessage.cs.meta
================================================
fileFormatVersion: 2
guid: 7f7b01638a2ed1242a9b81b7d6f408eb
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
================================================
FILE: Assets/Scripts/Network/Message/IMessageDispatcher.cs
================================================
namespace UNetwork
{
public interface IMessageDispatcher
{
void Dispatch(Session session, byte[] buffer);
}
}
================================================
FILE: Assets/Scripts/Network/Message/IMessageDispatcher.cs.meta
================================================
fileFormatVersion: 2
guid: 69481855785b4b59834c766e4e2798e1
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
================================================
FILE: Assets/Scripts/Network/Message/IMessagePacker.cs
================================================
using System;
using System.IO;
namespace UNetwork
{
public interface IMessagePacker
{
byte[] SerializeTo(object obj);
void SerializeTo(object obj, MemoryStream stream);
object DeserializeFrom(Type type, byte[] bytes, int index, int count);
object DeserializeFrom(object instance, byte[] bytes, int index, int count);
object DeserializeFrom(Type type, MemoryStream stream);
object DeserializeFrom(object instance, MemoryStream stream);
}
}
================================================
FILE: Assets/Scripts/Network/Message/IMessagePacker.cs.meta
================================================
fileFormatVersion: 2
guid: 09fe3a4882b1b50498860b3f672d1d47
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
================================================
FILE: Assets/Scripts/Network/Message/MessageInfo.cs
================================================
namespace UNetwork
{
public struct MessageInfo
{
public ushort Opcode { get; }
public object Message { get; }
public MessageInfo(ushort opcode, object message)
{
this.Opcode = opcode;
this.Message = message;
}
}
}
================================================
FILE: Assets/Scripts/Network/Message/MessageInfo.cs.meta
================================================
fileFormatVersion: 2
guid: 0b54864d3eb34ee4b90665941ecf5b87
timeCreated: 1501467234
licenseType: Free
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
================================================
FILE: Assets/Scripts/Network/Message/MessagePool.cs
================================================
using System;
using System.Collections.Generic;
namespace UNetwork
{
// 客户端为了0GC需要消息池,服务端消息需要跨协程不需要消息池
public class MessagePool
{
public static MessagePool Instance { get; } = new MessagePool();
private readonly Dictionary<Type, Queue<object>> dictionary = new Dictionary<Type, Queue<object>>();
public object Fetch(Type type)
{
Queue<object> queue;
if (!this.dictionary.TryGetValue(type, out queue))
{
queue = new Queue<object>();
this.dictionary.Add(type, queue);
}
object obj;
if (queue.Count > 0)
{
obj = queue.Dequeue();
}
else
{
obj = Activator.CreateInstance(type);
}
return obj;
}
public T Fetch<T>() where T : class
{
T t = (T) this.Fetch(typeof (T));
return t;
}
public void Recycle(object obj)
{
Type type = obj.GetType();
Queue<object> queue;
if (!this.dictionary.TryGetValue(type, out queue))
{
queue = new Queue<object>();
this.dictionary.Add(type, queue);
}
queue.Enqueue(obj);
}
}
}
================================================
FILE: Assets/Scripts/Network/Message/MessagePool.cs.meta
================================================
fileFormatVersion: 2
guid: 1d413cb22ac106a439af32933382ce66
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
================================================
FILE: Assets/Scripts/Network/Message/Opcode.cs
================================================
namespace UNetwork
{
public static partial class Opcode
{
public const ushort ActorResponse = 1;
public const ushort FrameMessage = 2;
public const ushort OneFrameMessage = 3;
}
}
================================================
FILE: Assets/Scripts/Network/Message/Opcode.cs.meta
================================================
fileFormatVersion: 2
guid: 129811e752b0782479b48ee6a12e1f2b
timeCreated: 1517571639
licenseType: Free
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
================================================
FILE: Assets/Scripts/Network/Message/OuterMessageDispatcher.cs
================================================
using System;
using System.Text;
using UnityEngine;
namespace UNetwork
{
public class OuterMessageDispatcher: IMessageDispatcher
{
public void Dispatch(Session session, byte[] buffer)
{
// ushort opcode = BitConverter.ToUInt16(buffer, Packet.OpcodeIndex);
string opcode = Encoding.UTF8.GetString(buffer);
// object message = this.Network.MessagePacker.DeserializeFrom(null, memoryStream);
TestClient.Receive();
Debug.Log("receive msg:" + opcode);
}
}
}
================================================
FILE: Assets/Scripts/Network/Message/OuterMessageDispatcher.cs.meta
================================================
fileFormatVersion: 2
guid: 1019c6e4151c2374390b6f30c09e0e1f
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
================================================
FILE: Assets/Scripts/Network/Message/ProtobufPacker.cs
================================================
using System;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
using System.Text;
namespace UNetwork
{
public class ProtobufPacker : IMessagePacker
{
public byte[] SerializeTo(object obj)
{
BinaryFormatter formatter = new BinaryFormatter();
MemoryStream rems = new MemoryStream();
formatter.Serialize(rems, obj);
return rems.GetBuffer();
}
public void SerializeTo(object obj, MemoryStream stream)
{
BinaryFormatter formatter = new BinaryFormatter();
formatter.Serialize(stream, obj);
}
public object DeserializeFrom(Type type, byte[] bytes, int index, int count)
{
return null;
// return ProtobufHelper.FromBytes(type, bytes, index, count);
}
public object DeserializeFrom(object instance, byte[] bytes, int index, int count)
{
return null;
// return ProtobufHelper.FromBytes(instance, bytes, index, count);
}
public object DeserializeFrom(Type type, MemoryStream stream)
{
BinaryFormatter formatter = new BinaryFormatter();
return formatter.Deserialize(stream);
}
public object DeserializeFrom(object instance, MemoryStream stream)
{
// return ProtobufHelper.FromStream(instance, stream);
return null;
}
}
}
================================================
FILE: Assets/Scripts/Network/Message/ProtobufPacker.cs.meta
================================================
fileFormatVersion: 2
guid: 26802b02461a1454499ebc037e012b5f
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
================================================
FILE: Assets/Scripts/Network/Message/RecyclableMemoryStream/Events.cs
================================================
// ---------------------------------------------------------------------
// Copyright (c) 2015 Microsoft
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
// ---------------------------------------------------------------------
namespace Microsoft.IO
{
using System;
using System.Diagnostics.Tracing;
public sealed partial class RecyclableMemoryStreamManager
{
[EventSource(Name = "Microsoft-IO-RecyclableMemoryStream", Guid = "{B80CD4E4-890E-468D-9CBA-90EB7C82DFC7}")]
public sealed class Events : EventSource
{
public static Events Writer = new Events();
public enum MemoryStreamBufferType
{
Small,
Large
}
public enum MemoryStreamDiscardReason
{
TooLarge,
EnoughFree
}
[Event(1, Level = EventLevel.Verbose)]
public void MemoryStreamCreated(Guid guid, string tag, int requestedSize)
{
if (this.IsEnabled(EventLevel.Verbose, EventKeywords.None))
{
WriteEvent(1, guid, tag ?? string.Empty, requestedSize);
}
}
[Event(2, Level = EventLevel.Verbose)]
public void MemoryStreamDisposed(Guid guid, string tag)
{
if (this.IsEnabled(EventLevel.Verbose, EventKeywords.None))
{
WriteEvent(2, guid, tag ?? string.Empty);
}
}
[Event(3, Level = EventLevel.Critical)]
public void MemoryStreamDoubleDispose(Guid guid, string tag, string allocationStack, string disposeStack1,
string disposeStack2)
{
if (this.IsEnabled())
{
this.WriteEvent(3, guid, tag ?? string.Empty, allocationStack ?? string.Empty,
disposeStack1 ?? string.Empty, disposeStack2 ?? string.Empty);
}
}
[Event(4, Level = EventLevel.Error)]
public void MemoryStreamFinalized(Guid guid, string tag, string allocationStack)
{
if (this.IsEnabled())
{
WriteEvent(4, guid, tag ?? string.Empty, allocationStack ?? string.Empty);
}
}
[Event(5, Level = EventLevel.Verbose)]
public void MemoryStreamToArray(Guid guid, string tag, string stack, int size)
{
if (this.IsEnabled(EventLevel.Verbose, EventKeywords.None))
{
WriteEvent(5, guid, tag ?? string.Empty, stack ?? string.Empty, size);
}
}
[Event(6, Level = EventLevel.Informational)]
public void MemoryStreamManagerInitialized(int blockSize, int largeBufferMultiple, int maximumBufferSize)
{
if (this.IsEnabled())
{
WriteEvent(6, blockSize, largeBufferMultiple, maximumBufferSize);
}
}
[Event(7, Level = EventLevel.Verbose)]
public void MemoryStreamNewBlockCreated(long smallPoolInUseBytes)
{
if (this.IsEnabled(EventLevel.Verbose, EventKeywords.None))
{
WriteEvent(7, smallPoolInUseBytes);
}
}
[Event(8, Level = EventLevel.Verbose)]
public void MemoryStreamNewLargeBufferCreated(int requiredSize, long largePoolInUseBytes)
{
if (this.IsEnabled(EventLevel.Verbose, EventKeywords.None))
{
WriteEvent(8, requiredSize, largePoolInUseBytes);
}
}
[Event(9, Level = EventLevel.Verbose)]
public void MemoryStreamNonPooledLargeBufferCreated(int requiredSize, string tag, string allocationStack)
{
if (this.IsEnabled(EventLevel.Verbose, EventKeywords.None))
{
WriteEvent(9, requiredSize, tag ?? string.Empty, allocationStack ?? string.Empty);
}
}
[Event(10, Level = EventLevel.Warning)]
public void MemoryStreamDiscardBuffer(MemoryStreamBufferType bufferType, string tag,
MemoryStreamDiscardReason reason)
{
if (this.IsEnabled())
{
WriteEvent(10, bufferType, tag ?? string.Empty, reason);
}
}
[Event(11, Level = EventLevel.Error)]
public void MemoryStreamOverCapacity(int requestedCapacity, long maxCapacity, string tag,
string allocationStack)
{
if (this.IsEnabled())
{
WriteEvent(11, requestedCapacity, maxCapacity, tag ?? string.Empty, allocationStack ?? string.Empty);
}
}
}
}
}
// This is here for .NET frameworks which don't support EventSource. We basically shim bare functionality used above to
#if NET40
namespace System.Diagnostics.Tracing
{
public enum EventLevel
{
LogAlways = 0,
Critical,
Error,
Warning,
Informational,
Verbose,
}
public enum EventKeywords : long
{
None = 0x0,
}
[AttributeUsage(AttributeTargets.Class)]
public sealed class EventSourceAttribute : Attribute
{
public string Name { get; set; }
public string Guid { get; set; }
}
[AttributeUsage(AttributeTargets.Method)]
public sealed class EventAttribute : Attribute
{
public EventAttribute(int id) { }
public EventLevel Level { get; set; }
}
public class EventSource
{
public void WriteEvent(params object[] unused)
{
return;
}
public bool IsEnabled()
{
return false;
}
public bool IsEnabled(EventLevel level, EventKeywords keywords)
{
return false;
}
}
}
#endif
================================================
FILE: Assets/Scripts/Network/Message/RecyclableMemoryStream/Events.cs.meta
================================================
fileFormatVersion: 2
guid: 52cd395d4cf275c48b1f8690689d3869
timeCreated: 1527234045
licenseType: Pro
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
================================================
FILE: Assets/Scripts/Network/Message/RecyclableMemoryStream/OneThreadSynchronizationContext.cs
================================================
using System;
using System.Collections.Concurrent;
using System.Threading;
namespace UNetwork
{
public class OneThreadSynchronizationContext : SynchronizationContext
{
public static OneThreadSynchronizationContext Instance { get; } = new OneThreadSynchronizationContext();
private readonly int mainThreadId = Thread.CurrentThread.ManagedThreadId;
// 线程同步队列,发送接收socket回调都放到该队列,由poll线程统一执行
private readonly ConcurrentQueue<Action> queue = new ConcurrentQueue<Action>();
private Action a;
public void Update()
{
while (true)
{
if (!this.queue.TryDequeue(out a))
{
return;
}
a();
}
}
public override void Post(SendOrPostCallback callback, object state)
{
if (Thread.CurrentThread.ManagedThreadId == this.mainThreadId)
{
callback(state);
return;
}
this.queue.Enqueue(() => { callback(state); });
}
}
}
================================================
FILE: Assets/Scripts/Network/Message/RecyclableMemoryStream/OneThreadSynchronizationContext.cs.meta
================================================
fileFormatVersion: 2
guid: f9b9ed5f7ab66544eb242d9f98cf1a6b
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
================================================
FILE: Assets/Scripts/Network/Message/RecyclableMemoryStream/RecyclableMemoryStream.cs
================================================
// The MIT License (MIT)
//
// Copyright (c) 2015-2016 Microsoft
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
namespace Microsoft.IO
{
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Threading;
/// <summary>
/// MemoryStream implementation that deals with pooling and managing memory streams which use potentially large
/// buffers.
/// </summary>
/// <remarks>
/// This class works in tandem with the RecylableMemoryStreamManager to supply MemoryStream
/// objects to callers, while avoiding these specific problems:
/// 1. LOH allocations - since all large buffers are pooled, they will never incur a Gen2 GC
/// 2. Memory waste - A standard memory stream doubles its size when it runs out of room. This
/// leads to continual memory growth as each stream approaches the maximum allowed size.
/// 3. Memory copying - Each time a MemoryStream grows, all the bytes are copied into new buffers.
/// This implementation only copies the bytes when GetBuffer is called.
/// 4. Memory fragmentation - By using homogeneous buffer sizes, it ensures that blocks of memory
/// can be easily reused.
///
/// The stream is implemented on top of a series of uniformly-sized blocks. As the stream's length grows,
/// additional blocks are retrieved from the memory manager. It is these blocks that are pooled, not the stream
/// object itself.
///
/// The biggest wrinkle in this implementation is when GetBuffer() is called. This requires a single
/// contiguous buffer. If only a single block is in use, then that block is returned. If multiple blocks
/// are in use, we retrieve a larger buffer from the memory manager. These large buffers are also pooled,
/// split by size--they are multiples of a chunk size (1 MB by default).
///
/// Once a large buffer is assigned to the stream the blocks are NEVER again used for this stream. All operations take place on the
/// large buffer. The large buffer can be replaced by a larger buffer from the pool as needed. All blocks and large buffers
/// are maintained in the stream until the stream is disposed (unless AggressiveBufferReturn is enabled in the stream manager).
///
/// </remarks>
public sealed class RecyclableMemoryStream : MemoryStream
{
private const long MaxStreamLength = Int32.MaxValue;
private static readonly byte[] emptyArray = new byte[0];
/// <summary>
/// All of these blocks must be the same size
/// </summary>
private readonly List<byte[]> blocks = new List<byte[]>(1);
/// <summary>
/// This buffer exists so that WriteByte can forward all of its calls to Write
/// without creating a new byte[] buffer on every call.
/// </summary>
private readonly byte[] byteBuffer = new byte[1];
private readonly Guid id;
private readonly RecyclableMemoryStreamManager memoryManager;
private readonly string tag;
/// <summary>
/// This list is used to store buffers once they're replaced by something larger.
/// This is for the cases where you have users of this class that may hold onto the buffers longer
/// than they should and you want to prevent race conditions which could corrupt the data.
/// </summary>
private List<byte[]> dirtyBuffers;
// long to allow Interlocked.Read (for .NET Standard 1.4 compat)
private long disposedState;
/// <summary>
/// This is only set by GetBuffer() if the necessary buffer is larger than a single block size, or on
/// construction if the caller immediately requests a single large buffer.
/// </summary>
/// <remarks>If this field is non-null, it contains the concatenation of the bytes found in the individual
/// blocks. Once it is created, this (or a larger) largeBuffer will be used for the life of the stream.
/// </remarks>
private byte[] largeBuffer;
/// <summary>
/// Unique identifier for this stream across it's entire lifetime
/// </summary>
/// <exception cref="ObjectDisposedException">Object has been disposed</exception>
internal Guid Id
{
get
{
this.CheckDisposed();
return this.id;
}
}
/// <summary>
/// A temporary identifier for the current usage of this stream.
/// </summary>
/// <exception cref="ObjectDisposedException">Object has been disposed</exception>
internal string Tag
{
get
{
this.CheckDisposed();
return this.tag;
}
}
/// <summary>
/// Gets the memory manager being used by this stream.
/// </summary>
/// <exception cref="ObjectDisposedException">Object has been disposed</exception>
internal RecyclableMemoryStreamManager MemoryManager
{
get
{
this.CheckDisposed();
return this.memoryManager;
}
}
/// <summary>
/// Callstack of the constructor. It is only set if MemoryManager.GenerateCallStacks is true,
/// which should only be in debugging situations.
/// </summary>
internal string AllocationStack { get; }
/// <summary>
/// Callstack of the Dispose call. It is only set if MemoryManager.GenerateCallStacks is true,
/// which should only be in debugging situations.
/// </summary>
internal string DisposeStack { get; private set; }
#region Constructors
/// <summary>
/// Allocate a new RecyclableMemoryStream object.
/// </summary>
/// <param name="memoryManager">The memory manager</param>
public RecyclableMemoryStream(RecyclableMemoryStreamManager memoryManager)
: this(memoryManager, null, 0, null) { }
/// <summary>
/// Allocate a new RecyclableMemoryStream object
/// </summary>
/// <param name="memoryManager">The memory manager</param>
/// <param name="tag">A string identifying this stream for logging and debugging purposes</param>
public RecyclableMemoryStream(RecyclableMemoryStreamManager memoryManager, string tag)
: this(memoryManager, tag, 0, null) { }
/// <summary>
/// Allocate a new RecyclableMemoryStream object
/// </summary>
/// <param name="memoryManager">The memory manager</param>
/// <param name="tag">A string identifying this stream for logging and debugging purposes</param>
/// <param name="requestedSize">The initial requested size to prevent future allocations</param>
public RecyclableMemoryStream(RecyclableMemoryStreamManager memoryManager, string tag, int requestedSize)
: this(memoryManager, tag, requestedSize, null) { }
/// <summary>
/// Allocate a new RecyclableMemoryStream object
/// </summary>
/// <param name="memoryManager">The memory manager</param>
/// <param name="tag">A string identifying this stream for logging and debugging purposes</param>
/// <param name="requestedSize">The initial requested size to prevent future allocations</param>
/// <param name="initialLargeBuffer">An initial buffer to use. This buffer will be owned by the stream and returned to the memory manager upon Dispose.</param>
internal RecyclableMemoryStream(RecyclableMemoryStreamManager memoryManager, string tag, int requestedSize,
byte[] initialLargeBuffer)
: base(emptyArray)
{
this.memoryManager = memoryManager;
this.id = Guid.NewGuid();
this.tag = tag;
if (requestedSize < memoryManager.BlockSize)
{
requestedSize = memoryManager.BlockSize;
}
if (initialLargeBuffer == null)
{
this.EnsureCapacity(requestedSize);
}
else
{
this.largeBuffer = initialLargeBuffer;
}
if (this.memoryManager.GenerateCallStacks)
{
this.AllocationStack = Environment.StackTrace;
}
RecyclableMemoryStreamManager.Events.Writer.MemoryStreamCreated(this.id, this.tag, requestedSize);
this.memoryManager.ReportStreamCreated();
}
#endregion
#region Dispose and Finalize
~RecyclableMemoryStream()
{
this.Dispose(false);
}
/// <summary>
/// Returns the memory used by this stream back to the pool.
/// </summary>
/// <param name="disposing">Whether we're disposing (true), or being called by the finalizer (false)</param>
[SuppressMessage("Microsoft.Usage", "CA1816:CallGCSuppressFinalizeCorrectly",
Justification = "We have different disposal semantics, so SuppressFinalize is in a different spot.")]
protected override void Dispose(bool disposing)
{
if (Interlocked.CompareExchange(ref this.disposedState, 1, 0) != 0)
{
string doubleDisposeStack = null;
if (this.memoryManager.GenerateCallStacks)
{
doubleDisposeStack = Environment.StackTrace;
}
RecyclableMemoryStreamManager.Events.Writer.MemoryStreamDoubleDispose(this.id, this.tag,
this.AllocationStack,
this.DisposeStack,
doubleDisposeStack);
return;
}
RecyclableMemoryStreamManager.Events.Writer.MemoryStreamDisposed(this.id, this.tag);
if (this.memoryManager.GenerateCallStacks)
{
this.DisposeStack = Environment.StackTrace;
}
if (disposing)
{
this.memoryManager.ReportStreamDisposed();
GC.SuppressFinalize(this);
}
else
{
// We're being finalized.
RecyclableMemoryStreamManager.Events.Writer.MemoryStreamFinalized(this.id, this.tag, this.AllocationStack);
#if !NETSTANDARD1_4
if (AppDomain.CurrentDomain.IsFinalizingForUnload())
{
// If we're being finalized because of a shutdown, don't go any further.
// We have no idea what's already been cleaned up. Triggering events may cause
// a crash.
base.Dispose(disposing);
return;
}
#endif
this.memoryManager.ReportStreamFinalized();
}
this.memoryManager.ReportStreamLength(this.length);
if (this.largeBuffer != null)
{
this.memoryManager.ReturnLargeBuffer(this.largeBuffer, this.tag);
}
if (this.dirtyBuffers != null)
{
foreach (var buffer in this.dirtyBuffers)
{
this.memoryManager.ReturnLargeBuffer(buffer, this.tag);
}
}
this.memoryManager.ReturnBlocks(this.blocks, this.tag);
this.blocks.Clear();
base.Dispose(disposing);
}
/// <summary>
/// Equivalent to Dispose
/// </summary>
#if NETSTANDARD1_4
public void Close()
#else
public override void Close()
#endif
{
this.Dispose(true);
}
#endregion
#region MemoryStream overrides
/// <summary>
/// Gets or sets the capacity
/// </summary>
/// <remarks>Capacity is always in multiples of the memory manager's block size, unless
/// the large buffer is in use. Capacity never decreases during a stream's lifetime.
/// Explicitly setting the capacity to a lower value than the current value will have no effect.
/// This is because the buffers are all pooled by chunks and there's little reason to
/// allow stream truncation.
/// </remarks>
/// <exception cref="ObjectDisposedException">Object has been disposed</exception>
public override int Capacity
{
get
{
this.CheckDisposed();
if (this.largeBuffer != null)
{
return this.largeBuffer.Length;
}
long size = (long)this.blocks.Count * this.memoryManager.BlockSize;
return (int)Math.Min(int.MaxValue, size);
}
set
{
this.CheckDisposed();
this.EnsureCapacity(value);
}
}
private int length;
/// <summary>
/// Gets the number of bytes written to this stream.
/// </summary>
/// <exception cref="ObjectDisposedException">Object has been disposed</exception>
public override long Length
{
get
{
this.CheckDisposed();
return this.length;
}
}
private int position;
/// <summary>
/// Gets the current position in the stream
/// </summary>
/// <exception cref="ObjectDisposedException">Object has been disposed</exception>
public override long Position
{
get
{
this.CheckDisposed();
return this.position;
}
set
{
this.CheckDisposed();
if (value < 0)
{
throw new ArgumentOutOfRangeException("value", "value must be non-negative");
}
if (value > MaxStreamLength)
{
throw new ArgumentOutOfRangeException("value", "value cannot be more than " + MaxStreamLength);
}
this.position = (int)value;
}
}
/// <summary>
/// Whether the stream can currently read
/// </summary>
public override bool CanRead => !this.Disposed;
/// <summary>
/// Whether the stream can currently seek
/// </summary>
public override bool CanSeek => !this.Disposed;
/// <summary>
/// Always false
/// </summary>
public override bool CanTimeout => false;
/// <summary>
/// Whether the stream can currently write
/// </summary>
public override bool CanWrite => !this.Disposed;
/// <summary>
/// Returns a single buffer containing the contents of the stream.
/// The buffer may be longer than the stream length.
/// </summary>
/// <returns>A byte[] buffer</returns>
/// <remarks>IMPORTANT: Doing a Write() after calling GetBuffer() invalidates the buffer. The old buffer is held onto
/// until Dispose is called, but the next time GetBuffer() is called, a new buffer from the pool will be required.</remarks>
/// <exception cref="ObjectDisposedException">Object has been disposed</exception>
#if NETSTANDARD1_4
public byte[] GetBuffer()
#else
public override byte[] GetBuffer()
#endif
{
this.CheckDisposed();
if (this.largeBuffer != null)
{
return this.largeBuffer;
}
if (this.blocks.Count == 1)
{
return this.blocks[0];
}
// Buffer needs to reflect the capacity, not the length, because
// it's possible that people will manipulate the buffer directly
// and set the length afterward. Capacity sets the expectation
// for the size of the buffer.
var newBuffer = this.memoryManager.GetLargeBuffer(this.Capacity, this.tag);
// InternalRead will check for existence of largeBuffer, so make sure we
// don't set it until after we've copied the data.
this.InternalRead(newBuffer, 0, this.length, 0);
this.largeBuffer = newBuffer;
if (this.blocks.Count > 0 && this.memoryManager.AggressiveBufferReturn)
{
this.memoryManager.ReturnBlocks(this.blocks, this.tag);
this.blocks.Clear();
}
return this.largeBuffer;
}
/// <summary>
/// Returns a new array with a copy of the buffer's contents. You should almost certainly be using GetBuffer combined with the Length to
/// access the bytes in this stream. Calling ToArray will destroy the benefits of pooled buffers, but it is included
/// for the sake of completeness.
/// </summary>
/// <exception cref="ObjectDisposedException">Object has been disposed</exception>
#pragma warning disable CS0809
[Obsolete("This method has degraded performance vs. GetBuffer and should be avoided.")]
public override byte[] ToArray()
{
this.CheckDisposed();
var newBuffer = new byte[this.Length];
this.InternalRead(newBuffer, 0, this.length, 0);
string stack = this.memoryManager.GenerateCallStacks ? Environment.StackTrace : null;
RecyclableMemoryStreamManager.Events.Writer.MemoryStreamToArray(this.id, this.tag, stack, 0);
this.memoryManager.ReportStreamToArray();
return newBuffer;
}
#pragma warning restore CS0809
/// <summary>
/// Reads from the current position into the provided buffer
/// </summary>
/// <param name="buffer">Destination buffer</param>
/// <param name="offset">Offset into buffer at which to start placing the read bytes.</param>
/// <param name="count">Number of bytes to read.</param>
/// <returns>The number of bytes read</returns>
/// <exception cref="ArgumentNullException">buffer is null</exception>
/// <exception cref="ArgumentOutOfRangeException">offset or count is less than 0</exception>
/// <exception cref="ArgumentException">offset subtracted from the buffer length is less than count</exception>
/// <exception cref="ObjectDisposedException">Object has been disposed</exception>
public override int Read(byte[] buffer, int offset, int count)
{
return this.SafeRead(buffer, offset, count, ref this.position);
}
/// <summary>
/// Reads from the specified position into the provided buffer
/// </summary>
/// <param name="buffer">Destination buffer</param>
/// <param name="offset">Offset into buffer at which to start placing the read bytes.</param>
/// <param name="count">Number of bytes to read.</param>
/// <param name="streamPosition">Position in the stream to start reading from</param>
/// <returns>The number of bytes read</returns>
/// <exception cref="ArgumentNullException">buffer is null</exception>
/// <exception cref="ArgumentOutOfRangeException">offset or count is less than 0</exception>
/// <exception cref="ArgumentException">offset subtracted from the buffer length is less than count</exception>
/// <exception cref="ObjectDisposedException">Object has been disposed</exception>
public int SafeRead(byte[] buffer, int offset, int count, ref int streamPosition)
{
this.CheckDisposed();
if (buffer == null)
{
throw new ArgumentNullException(nameof(buffer));
}
if (offset < 0)
{
throw new ArgumentOutOfRangeException(nameof(offset), "offset cannot be negative");
}
if (count < 0)
{
throw new ArgumentOutOfRangeException(nameof(count), "count cannot be negative");
}
if (offset + count > buffer.Length)
{
throw new ArgumentException("buffer length must be at least offset + count");
}
int amountRead = this.InternalRead(buffer, offset, count, streamPosition);
streamPosition += amountRead;
return amountRead;
}
/// <summary>
/// Writes the buffer to the stream
/// </summary>
/// <param name="buffer">Source buffer</param>
/// <param name="offset">Start position</param>
/// <param name="count">Number of bytes to write</param>
/// <exception cref="ArgumentNullException">buffer is null</exception>
/// <exception cref="ArgumentOutOfRangeException">offset or count is negative</exception>
/// <exception cref="ArgumentException">buffer.Length - offset is not less than count</exception>
/// <exception cref="ObjectDisposedException">Object has been disposed</exception>
public override void Write(byte[] buffer, int offset, int count)
{
this.CheckDisposed();
if (buffer == null)
{
throw new ArgumentNullException(nameof(buffer));
}
if (offset < 0)
{
throw new ArgumentOutOfRangeException(nameof(offset), offset,
"Offset must be in the range of 0 - buffer.Length-1");
}
if (count < 0)
{
throw new ArgumentOutOfRangeException(nameof(count), count, "count must be non-negative");
}
if (count + offset > buffer.Length)
{
throw new ArgumentException("count must be greater than buffer.Length - offset");
}
int blockSize = this.memoryManager.BlockSize;
long end = (long)this.position + count;
// Check for overflow
if (end > MaxStreamLength)
{
throw new IOException("Maximum capacity exceeded");
}
long requiredBuffers = (end + blockSize - 1) / blockSize;
if (requiredBuffers * blockSize > MaxStreamLength)
{
throw new IOException("Maximum capacity exceeded");
}
this.EnsureCapacity((int)end);
if (this.largeBuffer == null)
{
int bytesRemaining = count;
int bytesWritten = 0;
var blockAndOffset = this.GetBlockAndRelativeOffset(this.position);
while (bytesRemaining > 0)
{
byte[] currentBlock = this.blocks[blockAndOffset.Block];
int remainingInBlock = blockSize - blockAndOffset.Offset;
int amountToWriteInBlock = Math.Min(remainingInBlock, bytesRemaining);
Buffer.BlockCopy(buffer, offset + bytesWritten, currentBlock, blockAndOffset.Offset,
amountToWriteInBlock);
bytesRemaining -= amountToWriteInBlock;
bytesWritten += amountToWriteInBlock;
++blockAndOffset.Block;
blockAndOffset.Offset = 0;
}
}
else
{
Buffer.BlockCopy(buffer, offset, this.largeBuffer, this.position, count);
}
this.position = (int)end;
this.length = Math.Max(this.position, this.length);
}
/// <summary>
/// Returns a useful string for debugging. This should not normally be called in actual production code.
/// </summary>
public override string ToString()
{
return $"Id = {this.Id}, Tag = {this.Tag}, Length = {this.Length:N0} bytes";
}
/// <summary>
/// Writes a single byte to the current position in the stream.
/// </summary>
/// <param name="value">byte value to write</param>
/// <exception cref="ObjectDisposedException">Object has been disposed</exception>
public override void WriteByte(byte value)
{
this.CheckDisposed();
this.byteBuffer[0] = value;
this.Write(this.byteBuffer, 0, 1);
}
/// <summary>
/// Reads a single byte from the current position in the stream.
/// </summary>
/// <returns>The byte at the current position, or -1 if the position is at the end of the stream.</returns>
/// <exception cref="ObjectDisposedException">Object has been disposed</exception>
public override int ReadByte()
{
return this.SafeReadByte(ref this.position);
}
/// <summary>
/// Reads a single byte from the specified position in the stream.
/// </summary>
/// <param name="streamPosition">The position in the stream to read from</param>
/// <returns>The byte at the current position, or -1 if the position is at the end of the stream.</returns>
/// <exception cref="ObjectDisposedException">Object has been disposed</exception>
public int SafeReadByte(ref int streamPosition)
{
this.CheckDisposed();
if (streamPosition == this.length)
{
return -1;
}
byte value;
if (this.largeBuffer == null)
{
var blockAndOffset = this.GetBlockAndRelativeOffset(streamPosition);
value = this.blocks[blockAndOffset.Block][blockAndOffset.Offset];
}
else
{
value = this.largeBuffer[streamPosition];
}
streamPosition++;
return value;
}
/// <summary>
/// Sets the length of the stream
/// </summary>
/// <exception cref="ArgumentOutOfRangeException">value is negative or larger than MaxStreamLength</exception>
/// <exception cref="ObjectDisposedException">Object has been disposed</exception>
public override void SetLength(long value)
{
this.CheckDisposed();
if (value < 0 || value > MaxStreamLength)
{
throw new ArgumentOutOfRangeException(nameof(value),
"value must be non-negative and at most " + MaxStreamLength);
}
this.EnsureCapacity((int)value);
this.length = (int)value;
if (this.position > value)
{
this.position = (int)value;
}
}
/// <summary>
/// Sets the position to the offset from the seek location
/// </summary>
/// <param name="offset">How many bytes to move</param>
/// <param name="loc">From where</param>
/// <returns>The new position</returns>
/// <exception cref="ObjectDisposedException">Object has been disposed</exception>
/// <exception cref="ArgumentOutOfRangeException">offset is larger than MaxStreamLength</exception>
/// <exception cref="ArgumentException">Invalid seek origin</exception>
/// <exception cref="IOException">Attempt to set negative position</exception>
public override long Seek(long offset, SeekOrigin loc)
{
this.CheckDisposed();
if (offset > MaxStreamLength)
{
throw new ArgumentOutOfRangeException(nameof(offset), "offset cannot be larger than " + MaxStreamLength);
}
int newPosition;
switch (loc)
{
case SeekOrigin.Begin:
newPosition = (int)offset;
break;
case SeekOrigin.Current:
newPosition = (int)offset + this.position;
break;
case SeekOrigin.End:
newPosition = (int)offset + this.length;
break;
default:
throw new ArgumentException("Invalid seek origin", nameof(loc));
}
if (newPosition < 0)
{
throw new IOException("Seek before beginning");
}
this.position = newPosition;
return this.position;
}
/// <summary>
/// Synchronously writes this stream's bytes to the parameter stream.
/// </summary>
/// <param name="stream">Destination stream</param>
/// <remarks>Important: This does a synchronous write, which may not be desired in some situations</remarks>
public override void WriteTo(Stream stream)
{
this.CheckDisposed();
if (stream == null)
{
throw new ArgumentNullException(nameof(stream));
}
if (this.largeBuffer == null)
{
int currentBlock = 0;
int bytesRemaining = this.length;
while (bytesRemaining > 0)
{
int amountToCopy = Math.Min(this.blocks[currentBlock].Length, bytesRemaining);
stream.Write(this.blocks[currentBlock], 0, amountToCopy);
bytesRemaining -= amountToCopy;
++currentBlock;
}
}
else
{
stream.Write(this.largeBuffer, 0, this.length);
}
}
#endregion
#region Helper Methods
private bool Disposed => Interlocked.Read(ref this.disposedState) != 0;
private void CheckDisposed()
{
if (this.Disposed)
{
throw new ObjectDisposedException($"The stream with Id {this.id} and Tag {this.tag} is disposed.");
}
}
private int InternalRead(byte[] buffer, int offset, int count, int fromPosition)
{
if (this.length - fromPosition <= 0)
{
return 0;
}
int amountToCopy;
if (this.largeBuffer == null)
{
var blockAndOffset = this.GetBlockAndRelativeOffset(fromPosition);
int bytesWritten = 0;
int bytesRemaining = Math.Min(count, this.length - fromPosition);
while (bytesRemaining > 0)
{
amountToCopy = Math.Min(this.blocks[blockAndOffset.Block].Length - blockAndOffset.Offset,
bytesRemaining);
Buffer.BlockCopy(this.blocks[blockAndOffset.Block], blockAndOffset.Offset, buffer,
bytesWritten + offset, amountToCopy);
bytesWritten += amountToCopy;
bytesRemaining -= amountToCopy;
++blockAndOffset.Block;
blockAndOffset.Offset = 0;
}
return bytesWritten;
}
amountToCopy = Math.Min(count, this.length - fromPosition);
Buffer.BlockCopy(this.largeBuffer, fromPosition, buffer, offset, amountToCopy);
return amountToCopy;
}
private struct BlockAndOffset
{
public int Block;
public int Offset;
public BlockAndOffset(int block, int offset)
{
this.Block = block;
this.Offset = offset;
}
}
private BlockAndOffset GetBlockAndRelativeOffset(int offset)
{
var blockSize = this.memoryManager.BlockSize;
return new BlockAndOffset(offset / blockSize, offset % blockSize);
}
private void EnsureCapacity(int newCapacity)
{
if (newCapacity > this.memoryManager.MaximumStreamCapacity && this.memoryManager.MaximumStreamCapacity > 0)
{
RecyclableMemoryStreamManager.Events.Writer.MemoryStreamOverCapacity(newCapacity,
this.memoryManager
.MaximumStreamCapacity, this.tag,
this.AllocationStack);
throw new InvalidOperationException("Requested capacity is too large: " + newCapacity + ". Limit is " +
this.memoryManager.MaximumStreamCapacity);
}
if (this.largeBuffer != null)
{
gitextract_xqrk26b3/ ├── .gitignore ├── Assets/ │ ├── Plugins/ │ │ ├── Kcp/ │ │ │ ├── Android/ │ │ │ │ ├── libs/ │ │ │ │ │ ├── armeabi-v7a/ │ │ │ │ │ │ └── libkcp.so.meta │ │ │ │ │ ├── armeabi-v7a.meta │ │ │ │ │ ├── x86/ │ │ │ │ │ │ └── libkcp.so.meta │ │ │ │ │ └── x86.meta │ │ │ │ └── libs.meta │ │ │ ├── Android.meta │ │ │ ├── MacOS/ │ │ │ │ ├── kcp.bundle/ │ │ │ │ │ ├── Contents/ │ │ │ │ │ │ ├── MacOS/ │ │ │ │ │ │ │ ├── kcp │ │ │ │ │ │ │ └── kcp.meta │ │ │ │ │ │ └── MacOS.meta │ │ │ │ │ └── Contents.meta │ │ │ │ └── kcp.bundle.meta │ │ │ ├── MacOS.meta │ │ │ ├── iOS/ │ │ │ │ ├── kcp.a │ │ │ │ └── kcp.a.meta │ │ │ ├── iOS.meta │ │ │ ├── x86/ │ │ │ │ └── kcp.dll.meta │ │ │ ├── x86.meta │ │ │ ├── x86_64/ │ │ │ │ └── kcp.dll.meta │ │ │ └── x86_64.meta │ │ └── Kcp.meta │ ├── Plugins.meta │ ├── Scenes/ │ │ ├── Client.unity │ │ ├── Client.unity.meta │ │ ├── Server.unity │ │ └── Server.unity.meta │ ├── Scenes.meta │ ├── Scripts/ │ │ ├── Helper/ │ │ │ ├── ByteHelper.cs │ │ │ ├── ByteHelper.cs.meta │ │ │ ├── MonoSingleton.cs │ │ │ ├── MonoSingleton.cs.meta │ │ │ ├── NetworkHelper.cs │ │ │ ├── NetworkHelper.cs.meta │ │ │ ├── RandomHelper.cs │ │ │ ├── RandomHelper.cs.meta │ │ │ ├── TimeHelper.cs │ │ │ └── TimeHelper.cs.meta │ │ ├── Helper.meta │ │ ├── Network/ │ │ │ ├── AChannel.cs │ │ │ ├── AChannel.cs.meta │ │ │ ├── AService.cs │ │ │ ├── AService.cs.meta │ │ │ ├── ClientManager.cs │ │ │ ├── ClientManager.cs.meta │ │ │ ├── Core/ │ │ │ │ ├── KCP/ │ │ │ │ │ ├── KCP.cs │ │ │ │ │ ├── KCP.cs.meta │ │ │ │ │ ├── KChannel.cs │ │ │ │ │ ├── KChannel.cs.meta │ │ │ │ │ ├── KService.cs │ │ │ │ │ ├── KService.cs.meta │ │ │ │ │ ├── KcpDll.cs │ │ │ │ │ └── KcpDll.cs.meta │ │ │ │ ├── KCP.meta │ │ │ │ ├── TCP/ │ │ │ │ │ ├── PacketParser.cs │ │ │ │ │ ├── PacketParser.cs.meta │ │ │ │ │ ├── TChannel.cs │ │ │ │ │ ├── TChannel.cs.meta │ │ │ │ │ ├── TChannelConnector.cs │ │ │ │ │ ├── TChannelConnector.cs.meta │ │ │ │ │ ├── TChannelServer.cs │ │ │ │ │ ├── TChannelServer.cs.meta │ │ │ │ │ ├── TService.cs │ │ │ │ │ ├── TService.cs.meta │ │ │ │ │ ├── TServiceServer.cs │ │ │ │ │ └── TServiceServer.cs.meta │ │ │ │ ├── TCP.meta │ │ │ │ ├── WebSocket/ │ │ │ │ │ ├── WChannel.cs │ │ │ │ │ ├── WChannel.cs.meta │ │ │ │ │ ├── WService.cs │ │ │ │ │ └── WService.cs.meta │ │ │ │ └── WebSocket.meta │ │ │ ├── Core.meta │ │ │ ├── INetworkManager.cs │ │ │ ├── INetworkManager.cs.meta │ │ │ ├── Message/ │ │ │ │ ├── Circularbuffer.cs │ │ │ │ ├── Circularbuffer.cs.meta │ │ │ │ ├── ErrorCode.cs │ │ │ │ ├── ErrorCode.cs.meta │ │ │ │ ├── IMessage.cs │ │ │ │ ├── IMessage.cs.meta │ │ │ │ ├── IMessageDispatcher.cs │ │ │ │ ├── IMessageDispatcher.cs.meta │ │ │ │ ├── IMessagePacker.cs │ │ │ │ ├── IMessagePacker.cs.meta │ │ │ │ ├── MessageInfo.cs │ │ │ │ ├── MessageInfo.cs.meta │ │ │ │ ├── MessagePool.cs │ │ │ │ ├── MessagePool.cs.meta │ │ │ │ ├── Opcode.cs │ │ │ │ ├── Opcode.cs.meta │ │ │ │ ├── OuterMessageDispatcher.cs │ │ │ │ ├── OuterMessageDispatcher.cs.meta │ │ │ │ ├── ProtobufPacker.cs │ │ │ │ ├── ProtobufPacker.cs.meta │ │ │ │ ├── RecyclableMemoryStream/ │ │ │ │ │ ├── Events.cs │ │ │ │ │ ├── Events.cs.meta │ │ │ │ │ ├── OneThreadSynchronizationContext.cs │ │ │ │ │ ├── OneThreadSynchronizationContext.cs.meta │ │ │ │ │ ├── RecyclableMemoryStream.cs │ │ │ │ │ ├── RecyclableMemoryStream.cs.meta │ │ │ │ │ ├── RecyclableMemoryStreamManager.cs │ │ │ │ │ └── RecyclableMemoryStreamManager.cs.meta │ │ │ │ ├── RecyclableMemoryStream.meta │ │ │ │ ├── Session.cs │ │ │ │ ├── Session.cs.meta │ │ │ │ ├── SessionConnector.cs │ │ │ │ ├── SessionConnector.cs.meta │ │ │ │ ├── SessionServer.cs │ │ │ │ └── SessionServer.cs.meta │ │ │ ├── Message.meta │ │ │ ├── ServerManager.cs │ │ │ └── ServerManager.cs.meta │ │ ├── Network.meta │ │ ├── TestClient.cs │ │ ├── TestClient.cs.meta │ │ ├── TestServer.cs │ │ └── TestServer.cs.meta │ └── Scripts.meta ├── ProjectSettings/ │ ├── AudioManager.asset │ ├── AutoStreamingSettings.asset │ ├── ClusterInputManager.asset │ ├── DynamicsManager.asset │ ├── EditorBuildSettings.asset │ ├── EditorSettings.asset │ ├── GraphicsSettings.asset │ ├── InputManager.asset │ ├── MemorySettings.asset │ ├── NavMeshAreas.asset │ ├── NetworkManager.asset │ ├── PackageManagerSettings.asset │ ├── Physics2DSettings.asset │ ├── PresetManager.asset │ ├── ProjectSettings.asset │ ├── ProjectVersion.txt │ ├── QualitySettings.asset │ ├── SceneTemplateSettings.json │ ├── TagManager.asset │ ├── TimeManager.asset │ ├── UnityConnectSettings.asset │ ├── VFXManager.asset │ ├── VersionControlSettings.asset │ └── boot.config └── README.md
SYMBOL INDEX (437 symbols across 41 files)
FILE: Assets/Scripts/Helper/ByteHelper.cs
class ByteHelper (line 5) | public static class ByteHelper
method ToHex (line 7) | public static string ToHex(this byte b)
method ToHex (line 12) | public static string ToHex(this byte[] bytes)
method ToHex (line 22) | public static string ToHex(this byte[] bytes, string format)
method ToHex (line 32) | public static string ToHex(this byte[] bytes, int offset, int count)
method ToStr (line 42) | public static string ToStr(this byte[] bytes)
method ToStr (line 47) | public static string ToStr(this byte[] bytes, int index, int count)
method Utf8ToStr (line 52) | public static string Utf8ToStr(this byte[] bytes)
method Utf8ToStr (line 57) | public static string Utf8ToStr(this byte[] bytes, int index, int count)
method WriteTo (line 62) | public static void WriteTo(this byte[] bytes, int offset, uint num)
method WriteTo (line 70) | public static void WriteTo(this byte[] bytes, int offset, int num)
method WriteTo (line 78) | public static void WriteTo(this byte[] bytes, int offset, byte num)
method WriteTo (line 83) | public static void WriteTo(this byte[] bytes, int offset, short num)
method WriteTo (line 89) | public static void WriteTo(this byte[] bytes, int offset, ushort num)
FILE: Assets/Scripts/Helper/MonoSingleton.cs
class MonoSingleton (line 3) | public abstract class MonoSingleton<T> : MonoBehaviour where T : MonoSin...
method Startup (line 34) | public void Startup()
method Awake (line 39) | private void Awake()
method Init (line 50) | public virtual void Init()
method DestroySelf (line 55) | public void DestroySelf()
method Dispose (line 62) | public virtual void Dispose()
FILE: Assets/Scripts/Helper/NetworkHelper.cs
class NetworkHelper (line 5) | public static class NetworkHelper
method ToIPEndPoint (line 7) | public static IPEndPoint ToIPEndPoint(string host, int port)
method ToIPEndPoint (line 12) | public static IPEndPoint ToIPEndPoint(string address)
FILE: Assets/Scripts/Helper/RandomHelper.cs
class RandomHelper (line 5) | public static class RandomHelper
method RandUInt64 (line 9) | public static UInt64 RandUInt64()
method RandInt64 (line 16) | public static Int64 RandInt64()
method RandomNumber (line 29) | public static int RandomNumber(int lower, int upper)
FILE: Assets/Scripts/Helper/TimeHelper.cs
class TimeHelper (line 5) | public static class TimeHelper
method ClientNow (line 12) | public static long ClientNow()
method ClientNowSeconds (line 17) | public static long ClientNowSeconds()
method Now (line 22) | public static long Now()
FILE: Assets/Scripts/Network/AChannel.cs
type ChannelType (line 8) | public enum ChannelType
class AChannel (line 14) | public class AChannel
method OnConnect (line 53) | public void OnConnect(int code)
method OnRead (line 59) | protected void OnRead(MemoryStream memoryStream)
method OnError (line 64) | protected void OnError(int e)
method AChannel (line 70) | protected AChannel(AService service, ChannelType channelType)
method Start (line 76) | public virtual void Start()
method Send (line 80) | public virtual void Send(MemoryStream stream)
method Dispose (line 84) | public virtual void Dispose()
FILE: Assets/Scripts/Network/AService.cs
type NetworkProtocol (line 6) | public enum NetworkProtocol
class AService (line 13) | public abstract class AService
method GetChannel (line 15) | public abstract AChannel GetChannel();
method ConnectChannel (line 17) | public abstract AChannel ConnectChannel(IPEndPoint ipEndPoint);
method ConnectChannel (line 19) | public abstract AChannel ConnectChannel(string address);
method Update (line 21) | public abstract void Update();
method Dispose (line 23) | public abstract void Dispose();
FILE: Assets/Scripts/Network/ClientManager.cs
class ClientManager (line 10) | public class ClientManager : MonoSingleton<ClientManager>, INetworkManager
method Init (line 23) | public override void Init()
method InitService (line 29) | public void InitService(NetworkProtocol protocol, int packetSize = Pac...
method Connect (line 48) | public void Connect(IPEndPoint ipEndPoint)
method Connect (line 58) | public void Connect(string address)
method Connect (line 65) | public void Connect(string ip, int port)
method Update (line 72) | public void Update()
method Send (line 84) | public void Send(byte[] data)
method Dispose (line 89) | public override void Dispose()
FILE: Assets/Scripts/Network/Core/KCP/KCP.cs
class KCP (line 11) | public class KCP
method ikcp_encode8u (line 50) | public static void ikcp_encode8u(byte[] p, int offset, byte c)
method ikcp_decode8u (line 56) | public static byte ikcp_decode8u(byte[] p, ref int offset)
method ikcp_encode16u (line 62) | public static void ikcp_encode16u(byte[] p, int offset, UInt16 v)
method ikcp_decode16u (line 69) | public static UInt16 ikcp_decode16u(byte[] p, ref int offset)
method ikcp_encode32u (line 77) | public static void ikcp_encode32u(byte[] p, int offset, UInt32 l)
method ikcp_decode32u (line 86) | public static UInt32 ikcp_decode32u(byte[] p, ref int offset)
method _imin_ (line 94) | public static UInt32 _imin_(UInt32 a, UInt32 b)
method _imax_ (line 99) | public static UInt32 _imax_(UInt32 a, UInt32 b)
method _ibound_ (line 104) | public static UInt32 _ibound_(UInt32 lower, UInt32 middle, UInt32 upper)
method _itimediff (line 109) | public static Int32 _itimediff(UInt32 later, UInt32 earlier)
class Segment (line 114) | internal class Segment
method Segment (line 129) | internal Segment(int size = 0)
method Encode (line 134) | internal void Encode(byte[] ptr, ref int offset)
method KCP (line 212) | public KCP(UInt32 conv, object user)
method Release (line 237) | public void Release()
method SetOutput (line 254) | public void SetOutput(OutputDelegate output)
method Recv (line 260) | public int Recv(byte[] buffer, int offset, int len)
method PeekSize (line 343) | public int PeekSize()
method Send (line 368) | public int Send(byte[] buffer, int offset, int len)
method UpdateACK (line 409) | void UpdateACK(Int32 rtt)
method ShrinkBuf (line 432) | void ShrinkBuf()
method ParseACK (line 446) | void ParseACK(UInt32 sn)
method ParseUNA (line 467) | void ParseUNA(UInt32 una)
method ParseFastACK (line 486) | void ParseFastACK(UInt32 sn)
method ACKPush (line 508) | void ACKPush(UInt32 sn, UInt32 ts)
method ACKGet (line 534) | void ACKGet(int pos, ref UInt32 sn, ref UInt32 ts)
method ParseData (line 541) | void ParseData(Segment newseg)
method Input (line 602) | public int Input(byte[] data, int offset, int size)
method WndUnused (line 742) | int WndUnused()
method Flush (line 750) | void Flush()
method Update (line 967) | public void Update(UInt32 current)
method Check (line 1000) | public UInt32 Check(UInt32 current)
method SetMTU (line 1039) | public int SetMTU(int mtu)
method Interval (line 1051) | public int Interval(int interval)
method NoDelay (line 1067) | public int NoDelay(int nodelay, int interval, int resend, int nc)
method WndSize (line 1101) | public int WndSize(int sndwnd, int rcvwnd)
method WaitSnd (line 1111) | public int WaitSnd()
method GetConv (line 1117) | public UInt32 GetConv()
method GetState (line 1122) | public UInt32 GetState()
method SetMinRTO (line 1127) | public void SetMinRTO(int minrto)
method SetFastResend (line 1132) | public void SetFastResend(int resend)
method Log (line 1137) | void Log(int mask, string format, params object[] args)
FILE: Assets/Scripts/Network/Core/KCP/KChannel.cs
type WaitSendBuffer (line 13) | public struct WaitSendBuffer
method WaitSendBuffer (line 18) | public WaitSendBuffer(byte[] bytes, int length)
class KChannel (line 26) | public class KChannel : AChannel
method KChannel (line 48) | public KChannel(uint localConn, Socket socket, IPEndPoint remoteEndPoi...
method Dispose (line 62) | public void Dispose()
method Disconnect (line 96) | public void Disconnect(int error)
method GetService (line 101) | private KService GetService()
method HandleConnnect (line 106) | public void HandleConnnect(uint remoteConn)
method Accept (line 127) | public void Accept()
method Connect (line 154) | private void Connect()
method Disconnect (line 177) | private void Disconnect()
method Update (line 199) | public void Update()
method HandleSend (line 237) | private void HandleSend()
method HandleRecv (line 251) | public void HandleRecv(byte[] date, int offset, int length)
method Start (line 289) | public override void Start()
method Output (line 293) | public void Output(IntPtr bytes, int count)
method SetOutput (line 318) | public void SetOutput()
method KcpOutput (line 330) | #if ENABLE_IL2CPP
method KcpSend (line 339) | private void KcpSend(byte[] buffers, int length)
method Send (line 344) | private void Send(byte[] buffer, int index, int length)
method Send (line 355) | public override void Send(MemoryStream stream)
method KChannel (line 393) | public KChannel(uint localConn, Socket socket, IPEndPoint remoteEndPoi...
method Dispose (line 407) | public override void Dispose()
method Disconnect (line 433) | public void Disconnect(int error)
method GetService (line 438) | private KService GetService()
method HandleConnnect (line 443) | public void HandleConnnect(uint remoteConn)
method Connect (line 466) | private void Connect()
method Disconnect (line 490) | private void Disconnect()
method Update (line 511) | public void Update()
method HandleSend (line 549) | private void HandleSend()
method HandleRecv (line 563) | public void HandleRecv(byte[] date, int offset, int length)
method Start (line 608) | public override void Start()
method Output (line 612) | public void Output(byte[] bytes, int count)
method SetOutput (line 635) | public void SetOutput()
method KcpOutput (line 642) | public static void KcpOutput(byte[] bytes, int len, object user)
method KcpSend (line 647) | private void KcpSend(byte[] buffers, int length)
method Send (line 652) | private void Send(byte[] buffer, int index, int length)
method Send (line 663) | public override void Send(MemoryStream stream)
class KChannel (line 373) | public class KChannel : AChannel
method KChannel (line 48) | public KChannel(uint localConn, Socket socket, IPEndPoint remoteEndPoi...
method Dispose (line 62) | public void Dispose()
method Disconnect (line 96) | public void Disconnect(int error)
method GetService (line 101) | private KService GetService()
method HandleConnnect (line 106) | public void HandleConnnect(uint remoteConn)
method Accept (line 127) | public void Accept()
method Connect (line 154) | private void Connect()
method Disconnect (line 177) | private void Disconnect()
method Update (line 199) | public void Update()
method HandleSend (line 237) | private void HandleSend()
method HandleRecv (line 251) | public void HandleRecv(byte[] date, int offset, int length)
method Start (line 289) | public override void Start()
method Output (line 293) | public void Output(IntPtr bytes, int count)
method SetOutput (line 318) | public void SetOutput()
method KcpOutput (line 330) | #if ENABLE_IL2CPP
method KcpSend (line 339) | private void KcpSend(byte[] buffers, int length)
method Send (line 344) | private void Send(byte[] buffer, int index, int length)
method Send (line 355) | public override void Send(MemoryStream stream)
method KChannel (line 393) | public KChannel(uint localConn, Socket socket, IPEndPoint remoteEndPoi...
method Dispose (line 407) | public override void Dispose()
method Disconnect (line 433) | public void Disconnect(int error)
method GetService (line 438) | private KService GetService()
method HandleConnnect (line 443) | public void HandleConnnect(uint remoteConn)
method Connect (line 466) | private void Connect()
method Disconnect (line 490) | private void Disconnect()
method Update (line 511) | public void Update()
method HandleSend (line 549) | private void HandleSend()
method HandleRecv (line 563) | public void HandleRecv(byte[] date, int offset, int length)
method Start (line 608) | public override void Start()
method Output (line 612) | public void Output(byte[] bytes, int count)
method SetOutput (line 635) | public void SetOutput()
method KcpOutput (line 642) | public static void KcpOutput(byte[] bytes, int len, object user)
method KcpSend (line 647) | private void KcpSend(byte[] buffers, int length)
method Send (line 652) | private void Send(byte[] buffer, int index, int length)
method Send (line 663) | public override void Send(MemoryStream stream)
FILE: Assets/Scripts/Network/Core/KCP/KService.cs
class KcpProtocalType (line 10) | public static class KcpProtocalType
class KService (line 18) | public sealed class KService : AService
method KService (line 38) | public KService()
method Dispose (line 49) | public override void Dispose()
method Recv (line 57) | public void Recv()
method GetKChannel (line 94) | public KChannel GetKChannel()
method GetChannel (line 99) | public override AChannel GetChannel()
method Output (line 105) | public static void Output(IntPtr bytes, int count, IntPtr user)
method Output (line 107) | public static void Output(byte[] bytes, int count, object user)
method ConnectChannel (line 124) | public override AChannel ConnectChannel(IPEndPoint remoteEndPoint)
method ConnectChannel (line 131) | public override AChannel ConnectChannel(string address)
method Update (line 137) | public override void Update()
FILE: Assets/Scripts/Network/Core/KCP/KcpDll.cs
class KcpDll (line 8) | public class KcpDll
method ikcp_check (line 16) | [DllImport(KcpDLL, CallingConvention=CallingConvention.Cdecl)]
method ikcp_create (line 18) | [DllImport(KcpDLL, CallingConvention=CallingConvention.Cdecl)]
method ikcp_flush (line 20) | [DllImport(KcpDLL, CallingConvention=CallingConvention.Cdecl)]
method ikcp_getconv (line 22) | [DllImport(KcpDLL, CallingConvention=CallingConvention.Cdecl)]
method ikcp_input (line 24) | [DllImport(KcpDLL, CallingConvention=CallingConvention.Cdecl)]
method ikcp_nodelay (line 26) | [DllImport(KcpDLL, CallingConvention=CallingConvention.Cdecl)]
method ikcp_peeksize (line 28) | [DllImport(KcpDLL, CallingConvention=CallingConvention.Cdecl)]
method ikcp_recv (line 30) | [DllImport(KcpDLL, CallingConvention=CallingConvention.Cdecl)]
method ikcp_release (line 32) | [DllImport(KcpDLL, CallingConvention=CallingConvention.Cdecl)]
method ikcp_send (line 34) | [DllImport(KcpDLL, CallingConvention=CallingConvention.Cdecl)]
method ikcp_setminrto (line 36) | [DllImport(KcpDLL, CallingConvention=CallingConvention.Cdecl)]
method ikcp_setmtu (line 38) | [DllImport(KcpDLL, CallingConvention=CallingConvention.Cdecl)]
method ikcp_setoutput (line 40) | [DllImport(KcpDLL, CallingConvention=CallingConvention.Cdecl)]
method ikcp_update (line 42) | [DllImport(KcpDLL, CallingConvention=CallingConvention.Cdecl)]
method ikcp_waitsnd (line 44) | [DllImport(KcpDLL, CallingConvention=CallingConvention.Cdecl)]
method ikcp_wndsize (line 46) | [DllImport(KcpDLL, CallingConvention=CallingConvention.Cdecl)]
method KcpCheck (line 49) | public static uint KcpCheck(IntPtr kcp, uint current)
method KcpCreate (line 58) | public static IntPtr KcpCreate(uint conv, IntPtr user)
method KcpFlush (line 63) | public static void KcpFlush(IntPtr kcp)
method KcpGetconv (line 72) | public static uint KcpGetconv(IntPtr ptr)
method KcpInput (line 81) | public static int KcpInput(IntPtr kcp, byte[] data, int offset, int size)
method KcpNodelay (line 90) | public static int KcpNodelay(IntPtr kcp, int nodelay, int interval, in...
method KcpPeeksize (line 99) | public static int KcpPeeksize(IntPtr kcp)
method KcpRecv (line 108) | public static int KcpRecv(IntPtr kcp, byte[] buffer, int len)
method KcpRelease (line 117) | public static void KcpRelease(IntPtr kcp)
method KcpSend (line 126) | public static int KcpSend(IntPtr kcp, byte[] buffer, int len)
method KcpSetminrto (line 135) | public static void KcpSetminrto(IntPtr kcp, int minrto)
method KcpSetmtu (line 144) | public static int KcpSetmtu(IntPtr kcp, int mtu)
method KcpSetoutput (line 153) | public static void KcpSetoutput(IntPtr kcp, KcpOutput output)
method KcpUpdate (line 162) | public static void KcpUpdate(IntPtr kcp, uint current)
method KcpWaitsnd (line 171) | public static int KcpWaitsnd(IntPtr kcp)
method KcpWndsize (line 180) | public static int KcpWndsize(IntPtr kcp, int sndwnd, int rcvwnd)
FILE: Assets/Scripts/Network/Core/TCP/PacketParser.cs
type ParserState (line 6) | public enum ParserState
class Packet (line 12) | public static class Packet
class PacketParser (line 21) | public class PacketParser
method PacketParser (line 30) | public PacketParser(int packetSizeLength, CircularBuffer buffer, Memor...
method Parse (line 37) | public bool Parse()
method GetPacket (line 101) | public MemoryStream GetPacket()
FILE: Assets/Scripts/Network/Core/TCP/TChannel.cs
class TChannel (line 12) | public sealed class TChannel: AChannel
method TChannel (line 32) | public TChannel(IPEndPoint ipEndPoint, TService service): base(service...
method Dispose (line 51) | public override void Dispose()
method GetService (line 62) | private TService GetService()
method Start (line 67) | public override void Start()
method Send (line 82) | public override void Send(MemoryStream stream)
method OnComplete (line 108) | private void OnComplete(object sender, SocketAsyncEventArgs e)
method ConnectAsync (line 129) | public void ConnectAsync(IPEndPoint ipEndPoint)
method OnConnectComplete (line 139) | private void OnConnectComplete(object o)
method OnDisconnectComplete (line 160) | private void OnDisconnectComplete(object o)
method StartRecv (line 166) | private void StartRecv()
method RecvAsync (line 172) | public void RecvAsync(byte[] buffer, int offset, int count)
method OnRecvComplete (line 190) | private void OnRecvComplete(object o)
method StartSend (line 254) | public void StartSend()
method SendAsync (line 279) | public void SendAsync(byte[] buffer, int offset, int count)
method OnSendComplete (line 296) | private void OnSendComplete(object o)
FILE: Assets/Scripts/Network/Core/TCP/TChannelConnector.cs
class TClientConnection (line 13) | public sealed class TClientConnection : AChannel
method TClientConnection (line 34) | public TClientConnection(Socket clientSocket, TServiceServer service) ...
method Dispose (line 51) | public override void Dispose()
method Start (line 60) | public override void Start()
method Update (line 70) | public void Update()
method OnComplete (line 87) | private void OnComplete(object sender, SocketAsyncEventArgs e)
method OnDisconnectComplete (line 105) | private void OnDisconnectComplete(object o)
method StartRecv (line 111) | private void StartRecv()
method RecvAsync (line 117) | public void RecvAsync(byte[] buffer, int offset, int count)
method OnRecvComplete (line 136) | private void OnRecvComplete(object o)
method Send (line 194) | public override void Send(MemoryStream stream)
method StartSend (line 222) | public void StartSend()
method SendAsync (line 250) | public void SendAsync(byte[] buffer, int offset, int count)
method OnSendComplete (line 269) | private void OnSendComplete(object o)
method OnError (line 295) | private new void OnError(int error)
method OnMessage (line 301) | private void OnMessage(byte[] obj)
FILE: Assets/Scripts/Network/Core/TCP/TChannelServer.cs
class TChannelServer (line 13) | public sealed class TChannelServer : AChannel
method TChannelServer (line 27) | public TChannelServer(IPEndPoint ipEndPoint, TServiceServer service) :...
method Update (line 41) | public void Update()
method Send (line 49) | public override void Send(MemoryStream stream)
method Dispose (line 57) | public override void Dispose()
method Start (line 69) | public override void Start()
method AcceptAsync (line 74) | private void AcceptAsync()
method OnAcceptComplete (line 80) | private void OnAcceptComplete(object sender, SocketAsyncEventArgs e)
method OnDisconnect (line 105) | public void OnDisconnect(TClientConnection connection)
FILE: Assets/Scripts/Network/Core/TCP/TService.cs
class TService (line 12) | public sealed class TService : AService
method TService (line 20) | public TService(int packetSizeLength)
method Dispose (line 25) | public override void Dispose()
method GetChannel (line 30) | public override AChannel GetChannel()
method ConnectChannel (line 35) | public override AChannel ConnectChannel(IPEndPoint ipEndPoint)
method ConnectChannel (line 41) | public override AChannel ConnectChannel(string address)
method Update (line 47) | public override void Update()
FILE: Assets/Scripts/Network/Core/TCP/TServiceServer.cs
class TServiceServer (line 11) | public sealed class TServiceServer : AService
method TServiceServer (line 19) | public TServiceServer(int packetSizeLength)
method Dispose (line 24) | public override void Dispose()
method GetChannel (line 29) | public override AChannel GetChannel()
method ConnectChannel (line 34) | public override AChannel ConnectChannel(IPEndPoint ipEndPoint)
method ConnectChannel (line 40) | public override AChannel ConnectChannel(string address)
method Update (line 45) | public override void Update()
FILE: Assets/Scripts/Network/Core/WebSocket/WChannel.cs
class WChannel (line 10) | public class WChannel: AChannel
method WChannel (line 26) | public WChannel(HttpListenerWebSocketContext webSocketContext, AServic...
method WChannel (line 38) | public WChannel(WebSocket webSocket, AService service): base(service, ...
method Dispose (line 48) | public override void Dispose()
method Start (line 59) | public override void Start()
method GetService (line 70) | private WService GetService()
method ConnectAsync (line 75) | public async void ConnectAsync(string url)
method Send (line 90) | public override void Send(MemoryStream stream)
method StartSend (line 102) | public async void StartSend()
method StartRecv (line 140) | public async void StartRecv()
FILE: Assets/Scripts/Network/Core/WebSocket/WService.cs
class WService (line 10) | public class WService: AService
method WService (line 18) | public WService()
method GetChannel (line 22) | public override AChannel GetChannel()
method ConnectChannel (line 27) | public override AChannel ConnectChannel(IPEndPoint ipEndPoint)
method ConnectChannel (line 32) | public override AChannel ConnectChannel(string address)
method Update (line 40) | public override void Update()
method Dispose (line 45) | public override void Dispose()
FILE: Assets/Scripts/Network/INetworkManager.cs
type INetworkManager (line 5) | public interface INetworkManager
FILE: Assets/Scripts/Network/Message/Circularbuffer.cs
class CircularBuffer (line 8) | public class CircularBuffer: Stream
method CircularBuffer (line 22) | public CircularBuffer()
method AddLast (line 48) | public void AddLast()
method RemoveFirst (line 63) | public void RemoveFirst()
method ReadAsync (line 97) | public void ReadAsync(Stream stream)
method Read (line 117) | public void Read(Stream stream, int count)
method Write (line 145) | public void Write(Stream stream)
method WriteAsync (line 180) | public int WriteAsync(Stream stream)
method Read (line 204) | public override int Read(byte[] buffer, int offset, int count)
method Write (line 240) | public override void Write(byte[] buffer, int offset, int count)
method Flush (line 267) | public override void Flush()
method Seek (line 272) | public override long Seek(long offset, SeekOrigin origin)
method SetLength (line 277) | public override void SetLength(long value)
FILE: Assets/Scripts/Network/Message/ErrorCode.cs
class ErrorCode (line 3) | public static class ErrorCode
FILE: Assets/Scripts/Network/Message/IMessage.cs
type IMessage (line 3) | public interface IMessage
type IRequest (line 7) | public interface IRequest: IMessage
type IResponse (line 12) | public interface IResponse : IMessage
class ErrorResponse (line 19) | public class ErrorResponse : IResponse
FILE: Assets/Scripts/Network/Message/IMessageDispatcher.cs
type IMessageDispatcher (line 3) | public interface IMessageDispatcher
method Dispatch (line 5) | void Dispatch(Session session, byte[] buffer);
FILE: Assets/Scripts/Network/Message/IMessagePacker.cs
type IMessagePacker (line 6) | public interface IMessagePacker
method SerializeTo (line 8) | byte[] SerializeTo(object obj);
method SerializeTo (line 9) | void SerializeTo(object obj, MemoryStream stream);
method DeserializeFrom (line 10) | object DeserializeFrom(Type type, byte[] bytes, int index, int count);
method DeserializeFrom (line 11) | object DeserializeFrom(object instance, byte[] bytes, int index, int c...
method DeserializeFrom (line 12) | object DeserializeFrom(Type type, MemoryStream stream);
method DeserializeFrom (line 13) | object DeserializeFrom(object instance, MemoryStream stream);
FILE: Assets/Scripts/Network/Message/MessageInfo.cs
type MessageInfo (line 3) | public struct MessageInfo
method MessageInfo (line 8) | public MessageInfo(ushort opcode, object message)
FILE: Assets/Scripts/Network/Message/MessagePool.cs
class MessagePool (line 7) | public class MessagePool
method Fetch (line 13) | public object Fetch(Type type)
method Fetch (line 36) | public T Fetch<T>() where T : class
method Recycle (line 42) | public void Recycle(object obj)
FILE: Assets/Scripts/Network/Message/Opcode.cs
class Opcode (line 3) | public static partial class Opcode
FILE: Assets/Scripts/Network/Message/OuterMessageDispatcher.cs
class OuterMessageDispatcher (line 7) | public class OuterMessageDispatcher: IMessageDispatcher
method Dispatch (line 9) | public void Dispatch(Session session, byte[] buffer)
FILE: Assets/Scripts/Network/Message/ProtobufPacker.cs
class ProtobufPacker (line 8) | public class ProtobufPacker : IMessagePacker
method SerializeTo (line 10) | public byte[] SerializeTo(object obj)
method SerializeTo (line 18) | public void SerializeTo(object obj, MemoryStream stream)
method DeserializeFrom (line 24) | public object DeserializeFrom(Type type, byte[] bytes, int index, int ...
method DeserializeFrom (line 30) | public object DeserializeFrom(object instance, byte[] bytes, int index...
method DeserializeFrom (line 36) | public object DeserializeFrom(Type type, MemoryStream stream)
method DeserializeFrom (line 42) | public object DeserializeFrom(object instance, MemoryStream stream)
FILE: Assets/Scripts/Network/Message/RecyclableMemoryStream/Events.cs
class RecyclableMemoryStreamManager (line 28) | public sealed partial class RecyclableMemoryStreamManager
class Events (line 30) | [EventSource(Name = "Microsoft-IO-RecyclableMemoryStream", Guid = "{B8...
type MemoryStreamBufferType (line 35) | public enum MemoryStreamBufferType
type MemoryStreamDiscardReason (line 41) | public enum MemoryStreamDiscardReason
method MemoryStreamCreated (line 47) | [Event(1, Level = EventLevel.Verbose)]
method MemoryStreamDisposed (line 56) | [Event(2, Level = EventLevel.Verbose)]
method MemoryStreamDoubleDispose (line 65) | [Event(3, Level = EventLevel.Critical)]
method MemoryStreamFinalized (line 76) | [Event(4, Level = EventLevel.Error)]
method MemoryStreamToArray (line 85) | [Event(5, Level = EventLevel.Verbose)]
method MemoryStreamManagerInitialized (line 94) | [Event(6, Level = EventLevel.Informational)]
method MemoryStreamNewBlockCreated (line 103) | [Event(7, Level = EventLevel.Verbose)]
method MemoryStreamNewLargeBufferCreated (line 112) | [Event(8, Level = EventLevel.Verbose)]
method MemoryStreamNonPooledLargeBufferCreated (line 121) | [Event(9, Level = EventLevel.Verbose)]
method MemoryStreamDiscardBuffer (line 130) | [Event(10, Level = EventLevel.Warning)]
method MemoryStreamOverCapacity (line 140) | [Event(11, Level = EventLevel.Error)]
type EventLevel (line 157) | public enum EventLevel
type EventKeywords (line 167) | public enum EventKeywords : long
class EventSourceAttribute (line 172) | [AttributeUsage(AttributeTargets.Class)]
class EventAttribute (line 179) | [AttributeUsage(AttributeTargets.Method)]
method EventAttribute (line 182) | public EventAttribute(int id) { }
class EventSource (line 187) | public class EventSource
method WriteEvent (line 189) | public void WriteEvent(params object[] unused)
method IsEnabled (line 194) | public bool IsEnabled()
method IsEnabled (line 199) | public bool IsEnabled(EventLevel level, EventKeywords keywords)
FILE: Assets/Scripts/Network/Message/RecyclableMemoryStream/OneThreadSynchronizationContext.cs
class OneThreadSynchronizationContext (line 7) | public class OneThreadSynchronizationContext : SynchronizationContext
method Update (line 18) | public void Update()
method Post (line 30) | public override void Post(SendOrPostCallback callback, object state)
FILE: Assets/Scripts/Network/Message/RecyclableMemoryStream/RecyclableMemoryStream.cs
class RecyclableMemoryStream (line 60) | public sealed class RecyclableMemoryStream : MemoryStream
method RecyclableMemoryStream (line 158) | public RecyclableMemoryStream(RecyclableMemoryStreamManager memoryMana...
method RecyclableMemoryStream (line 166) | public RecyclableMemoryStream(RecyclableMemoryStreamManager memoryMana...
method RecyclableMemoryStream (line 175) | public RecyclableMemoryStream(RecyclableMemoryStreamManager memoryMana...
method RecyclableMemoryStream (line 185) | internal RecyclableMemoryStream(RecyclableMemoryStreamManager memoryMa...
method Dispose (line 227) | [SuppressMessage("Microsoft.Usage", "CA1816:CallGCSuppressFinalizeCorr...
method Close (line 304) | public void Close()
method Close (line 306) | public override void Close()
method GetBuffer (line 418) | public byte[] GetBuffer()
method GetBuffer (line 420) | public override byte[] GetBuffer()
method ToArray (line 462) | [Obsolete("This method has degraded performance vs. GetBuffer and shou...
method Read (line 488) | public override int Read(byte[] buffer, int offset, int count)
method SafeRead (line 505) | public int SafeRead(byte[] buffer, int offset, int count, ref int stre...
method Write (line 543) | public override void Write(byte[] buffer, int offset, int count)
method ToString (line 617) | public override string ToString()
method WriteByte (line 627) | public override void WriteByte(byte value)
method ReadByte (line 639) | public override int ReadByte()
method SafeReadByte (line 650) | public int SafeReadByte(ref int streamPosition)
method SetLength (line 676) | public override void SetLength(long value)
method Seek (line 704) | public override long Seek(long offset, SeekOrigin loc)
method WriteTo (line 740) | public override void WriteTo(Stream stream)
method CheckDisposed (line 773) | private void CheckDisposed()
method InternalRead (line 781) | private int InternalRead(byte[] buffer, int offset, int count, int fro...
type BlockAndOffset (line 816) | private struct BlockAndOffset
method BlockAndOffset (line 821) | public BlockAndOffset(int block, int offset)
method GetBlockAndRelativeOffset (line 828) | private BlockAndOffset GetBlockAndRelativeOffset(int offset)
method EnsureCapacity (line 834) | private void EnsureCapacity(int newCapacity)
method ReleaseLargeBuffer (line 868) | private void ReleaseLargeBuffer()
FILE: Assets/Scripts/Network/Message/RecyclableMemoryStream/RecyclableMemoryStreamManager.cs
class RecyclableMemoryStreamManager (line 44) | public partial class RecyclableMemoryStreamManager
method RecyclableMemoryStreamManager (line 99) | public RecyclableMemoryStreamManager()
method RecyclableMemoryStreamManager (line 110) | public RecyclableMemoryStreamManager(int blockSize, int largeBufferMul...
method GetBlock (line 253) | internal byte[] GetBlock()
method GetLargeBuffer (line 280) | internal byte[] GetLargeBuffer(int requiredSize, string tag)
method RoundToLargeBufferMultiple (line 326) | private int RoundToLargeBufferMultiple(int requiredSize)
method IsLargeBufferMultiple (line 331) | private bool IsLargeBufferMultiple(int value)
method ReturnLargeBuffer (line 343) | internal void ReturnLargeBuffer(byte[] buffer, string tag)
method ReturnBlocks (line 398) | internal void ReturnBlocks(ICollection<byte[]> blocks, string tag)
method ReportBlockCreated (line 436) | internal void ReportBlockCreated()
method ReportBlockDiscarded (line 441) | internal void ReportBlockDiscarded()
method ReportLargeBufferCreated (line 446) | internal void ReportLargeBufferCreated()
method ReportLargeBufferDiscarded (line 451) | internal void ReportLargeBufferDiscarded(Events.MemoryStreamDiscardRea...
method ReportStreamCreated (line 456) | internal void ReportStreamCreated()
method ReportStreamDisposed (line 461) | internal void ReportStreamDisposed()
method ReportStreamFinalized (line 466) | internal void ReportStreamFinalized()
method ReportStreamLength (line 471) | internal void ReportStreamLength(long bytes)
method ReportStreamToArray (line 476) | internal void ReportStreamToArray()
method ReportUsageReport (line 481) | internal void ReportUsageReport(
method GetStream (line 491) | public MemoryStream GetStream()
method GetStream (line 501) | public MemoryStream GetStream(string tag)
method GetStream (line 512) | public MemoryStream GetStream(string tag, int requiredSize)
method GetStream (line 529) | public MemoryStream GetStream(string tag, int requiredSize, bool asCon...
method GetStream (line 549) | [SuppressMessage("Microsoft.Reliability", "CA2000:Dispose objects befo...
FILE: Assets/Scripts/Network/Message/Session.cs
class Session (line 8) | public sealed class Session
method Session (line 22) | public Session(AChannel aChannel)
method OnConnect (line 31) | private void OnConnect(AChannel channel, int code)
method OnError (line 41) | private void OnError(AChannel channel, int code)
method Dispose (line 52) | public void Dispose()
method Start (line 63) | public void Start(INetworkManager manager)
method Run (line 84) | private void Run(MemoryStream memoryStream)
method OnRead (line 94) | public void OnRead(MemoryStream memoryStream)
method Send (line 106) | public void Send(ushort opcode)
method Send (line 118) | public void Send(byte[] buffers)
method Send (line 128) | public void Send(MemoryStream stream)
FILE: Assets/Scripts/Network/Message/SessionConnector.cs
class SessionConnector (line 8) | public sealed class SessionConnector
method SessionConnector (line 12) | public SessionConnector(AChannel aChannel)
method OnConnect (line 21) | private void OnConnect(AChannel channel, int code)
method OnError (line 26) | private void OnError(AChannel channel, int code)
method Run (line 31) | private void Run(MemoryStream memoryStream)
method OnRead (line 40) | public void OnRead(MemoryStream memoryStream)
FILE: Assets/Scripts/Network/Message/SessionServer.cs
class SessionServer (line 8) | public sealed class SessionServer
method SessionServer (line 22) | public SessionServer(AChannel aChannel)
method OnConnect (line 31) | private void OnConnect(AChannel channel, int code)
method OnError (line 41) | private void OnError(AChannel channel, int code)
method Dispose (line 52) | public void Dispose()
method Start (line 63) | public void Start(INetworkManager manager)
method Run (line 85) | private void Run(MemoryStream memoryStream)
method OnRead (line 95) | public void OnRead(MemoryStream memoryStream)
method Send (line 107) | public void Send(ushort opcode)
method Send (line 119) | public void Send(byte[] buffers)
method Send (line 129) | public void Send(MemoryStream stream)
FILE: Assets/Scripts/Network/ServerManager.cs
class ServerManager (line 10) | public class ServerManager : MonoSingleton<ServerManager>, INetworkManager
method Init (line 23) | public override void Init()
method InitService (line 29) | public void InitService(NetworkProtocol protocol, int packetSize = Pac...
method Connect (line 42) | public void Connect(IPEndPoint ipEndPoint)
method Connect (line 52) | public void Connect(string address)
method Connect (line 59) | public void Connect(string ip, int port)
method Update (line 66) | public void Update()
method Send (line 78) | public void Send(byte[] data)
method Dispose (line 83) | public override void Dispose()
FILE: Assets/Scripts/TestClient.cs
class TestClient (line 6) | public class TestClient : MonoBehaviour
method Start (line 15) | void Start()
method OnMessage (line 28) | private void OnMessage(byte[] obj)
method OnError (line 34) | private void OnError(int e)
method OnConnect (line 39) | private void OnConnect(int c)
method Update (line 44) | private void Update()
method GetTimeStamp (line 60) | public static long GetTimeStamp()
method Receive (line 65) | public static void Receive()
FILE: Assets/Scripts/TestServer.cs
class TestServer (line 6) | public class TestServer : MonoBehaviour
method Start (line 14) | void Start()
method OnMessage (line 27) | private void OnMessage(byte[] obj)
method OnError (line 33) | private void OnError(int e)
method OnConnect (line 38) | private void OnConnect(int c)
method Update (line 43) | private void Update()
method GetTimeStamp (line 59) | public static long GetTimeStamp()
method Receive (line 64) | public static void Receive()
Condensed preview — 143 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (306K chars).
[
{
"path": ".gitignore",
"chars": 555,
"preview": "# =============== #\n# Unity generated #\n# =============== #\n[Tt]emp/\n[Oo]bj/\n[Bb]uild\n[Ll]ibrary/\n[Gg]oogle/\n[Ll]ogs/\n[P"
},
{
"path": "Assets/Plugins/Kcp/Android/libs/armeabi-v7a/libkcp.so.meta",
"chars": 631,
"preview": "fileFormatVersion: 2\nguid: 8e03e31ef66b1d340bfd9de539878633\ntimeCreated: 1530266293\nlicenseType: Pro\nPluginImporter:\n s"
},
{
"path": "Assets/Plugins/Kcp/Android/libs/armeabi-v7a.meta",
"chars": 191,
"preview": "fileFormatVersion: 2\nguid: 4b9de99f882e1334f88d3fffa436fe26\nfolderAsset: yes\ntimeCreated: 1529980199\nlicenseType: Pro\nDe"
},
{
"path": "Assets/Plugins/Kcp/Android/libs/x86/libkcp.so.meta",
"chars": 629,
"preview": "fileFormatVersion: 2\nguid: 3869fe202d9b7494cbf94cbd4c9ae4c5\ntimeCreated: 1530266298\nlicenseType: Pro\nPluginImporter:\n s"
},
{
"path": "Assets/Plugins/Kcp/Android/libs/x86.meta",
"chars": 191,
"preview": "fileFormatVersion: 2\nguid: af440bcca3a80614185db5d493411e3e\nfolderAsset: yes\ntimeCreated: 1529980199\nlicenseType: Pro\nDe"
},
{
"path": "Assets/Plugins/Kcp/Android/libs.meta",
"chars": 191,
"preview": "fileFormatVersion: 2\nguid: e683bde7d2130ef4e9cd605a119c319e\nfolderAsset: yes\ntimeCreated: 1529980199\nlicenseType: Pro\nDe"
},
{
"path": "Assets/Plugins/Kcp/Android.meta",
"chars": 172,
"preview": "fileFormatVersion: 2\nguid: 89f91d9886713c242b08fc47677c6cd6\nfolderAsset: yes\nDefaultImporter:\n externalObjects: {}\n us"
},
{
"path": "Assets/Plugins/Kcp/MacOS/kcp.bundle/Contents/MacOS/kcp.meta",
"chars": 155,
"preview": "fileFormatVersion: 2\nguid: ca685b77470a94b838156da4c499b38a\nDefaultImporter:\n externalObjects: {}\n userData: \n assetB"
},
{
"path": "Assets/Plugins/Kcp/MacOS/kcp.bundle/Contents/MacOS.meta",
"chars": 172,
"preview": "fileFormatVersion: 2\nguid: 957c90d60724445898ad398879db8b83\nfolderAsset: yes\nDefaultImporter:\n externalObjects: {}\n us"
},
{
"path": "Assets/Plugins/Kcp/MacOS/kcp.bundle/Contents.meta",
"chars": 172,
"preview": "fileFormatVersion: 2\nguid: 19bc16a76b8ac49e6bafebcacef13384\nfolderAsset: yes\nDefaultImporter:\n externalObjects: {}\n us"
},
{
"path": "Assets/Plugins/Kcp/MacOS/kcp.bundle.meta",
"chars": 715,
"preview": "fileFormatVersion: 2\nguid: eb0cef4b32a23b24688b70b0d9b607e6\nfolderAsset: yes\nPluginImporter:\n externalObjects: {}\n ser"
},
{
"path": "Assets/Plugins/Kcp/MacOS.meta",
"chars": 172,
"preview": "fileFormatVersion: 2\nguid: 747c6b8c8af2e794da1e88402d7cc394\nfolderAsset: yes\nDefaultImporter:\n externalObjects: {}\n us"
},
{
"path": "Assets/Plugins/Kcp/iOS/kcp.a.meta",
"chars": 527,
"preview": "fileFormatVersion: 2\nguid: 81c5e3645249f404986889388c75e6de\nPluginImporter:\n externalObjects: {}\n serializedVersion: 2"
},
{
"path": "Assets/Plugins/Kcp/iOS.meta",
"chars": 172,
"preview": "fileFormatVersion: 2\nguid: fd0f4e125884b09478cd65e157e73225\nfolderAsset: yes\nDefaultImporter:\n externalObjects: {}\n us"
},
{
"path": "Assets/Plugins/Kcp/x86/kcp.dll.meta",
"chars": 2284,
"preview": "fileFormatVersion: 2\nguid: 5163e0119c1604a43adbc28ec6fb277e\ntimeCreated: 1530266315\nlicenseType: Pro\nPluginImporter:\n s"
},
{
"path": "Assets/Plugins/Kcp/x86.meta",
"chars": 172,
"preview": "fileFormatVersion: 2\nguid: 93e339b4ca47c8f4b81c2d9742800ec5\nfolderAsset: yes\nDefaultImporter:\n externalObjects: {}\n us"
},
{
"path": "Assets/Plugins/Kcp/x86_64/kcp.dll.meta",
"chars": 1943,
"preview": "fileFormatVersion: 2\nguid: 803f7857fdb47b34fbe04eda49b8aa85\nPluginImporter:\n externalObjects: {}\n serializedVersion: 2"
},
{
"path": "Assets/Plugins/Kcp/x86_64.meta",
"chars": 172,
"preview": "fileFormatVersion: 2\nguid: 06020764b763c6647b21f6933162724f\nfolderAsset: yes\nDefaultImporter:\n externalObjects: {}\n us"
},
{
"path": "Assets/Plugins/Kcp.meta",
"chars": 172,
"preview": "fileFormatVersion: 2\nguid: 3c6e92a7004dbcd45bed3397705d35bd\nfolderAsset: yes\nDefaultImporter:\n externalObjects: {}\n us"
},
{
"path": "Assets/Plugins.meta",
"chars": 172,
"preview": "fileFormatVersion: 2\nguid: a20cd3483a2a77b4bb8d9638ea3dde5f\nfolderAsset: yes\nDefaultImporter:\n externalObjects: {}\n us"
},
{
"path": "Assets/Scenes/Client.unity",
"chars": 5944,
"preview": "%YAML 1.1\n%TAG !u! tag:unity3d.com,2011:\n--- !u!29 &1\nOcclusionCullingSettings:\n m_ObjectHideFlags: 0\n serializedVersi"
},
{
"path": "Assets/Scenes/Client.unity.meta",
"chars": 155,
"preview": "fileFormatVersion: 2\nguid: 53e18807e282965479d061608139b64b\nDefaultImporter:\n externalObjects: {}\n userData: \n assetB"
},
{
"path": "Assets/Scenes/Server.unity",
"chars": 5096,
"preview": "%YAML 1.1\n%TAG !u! tag:unity3d.com,2011:\n--- !u!29 &1\nOcclusionCullingSettings:\n m_ObjectHideFlags: 0\n serializedVersi"
},
{
"path": "Assets/Scenes/Server.unity.meta",
"chars": 155,
"preview": "fileFormatVersion: 2\nguid: 7a58935d2e567f043835f59be74400f6\nDefaultImporter:\n externalObjects: {}\n userData: \n assetB"
},
{
"path": "Assets/Scenes.meta",
"chars": 172,
"preview": "fileFormatVersion: 2\nguid: e865c368c8aa84b4783f03af294abb01\nfolderAsset: yes\nDefaultImporter:\n externalObjects: {}\n us"
},
{
"path": "Assets/Scripts/Helper/ByteHelper.cs",
"chars": 2415,
"preview": "using System.Text;\n\nnamespace UNetwork\n{\n\tpublic static class ByteHelper\n\t{\n\t\tpublic static string ToHex(this byte b)\n\t"
},
{
"path": "Assets/Scripts/Helper/ByteHelper.cs.meta",
"chars": 243,
"preview": "fileFormatVersion: 2\nguid: c31f9c17b9d7c0e45b3b3f77811cb795\nMonoImporter:\n externalObjects: {}\n serializedVersion: 2\n "
},
{
"path": "Assets/Scripts/Helper/MonoSingleton.cs",
"chars": 1286,
"preview": "using UnityEngine;\n\npublic abstract class MonoSingleton<T> : MonoBehaviour where T : MonoSingleton<T>\n{\n\tprivate static "
},
{
"path": "Assets/Scripts/Helper/MonoSingleton.cs.meta",
"chars": 243,
"preview": "fileFormatVersion: 2\nguid: bbde26f5f28b63743b17d086fd52d70a\nMonoImporter:\n externalObjects: {}\n serializedVersion: 2\n "
},
{
"path": "Assets/Scripts/Helper/NetworkHelper.cs",
"chars": 470,
"preview": "using System.Net;\n\nnamespace UNetwork\n{\n\tpublic static class NetworkHelper\n\t{\n\t\tpublic static IPEndPoint ToIPEndPoint(s"
},
{
"path": "Assets/Scripts/Helper/NetworkHelper.cs.meta",
"chars": 263,
"preview": "fileFormatVersion: 2\nguid: 5f24e42ac059909498f35805b76f9102\ntimeCreated: 1511941046\nlicenseType: Free\nMonoImporter:\n se"
},
{
"path": "Assets/Scripts/Helper/RandomHelper.cs",
"chars": 697,
"preview": "using System;\n\nnamespace UNetwork\n{\n\tpublic static class RandomHelper\n\t{\n\t\tprivate static readonly Random random = new "
},
{
"path": "Assets/Scripts/Helper/RandomHelper.cs.meta",
"chars": 243,
"preview": "fileFormatVersion: 2\nguid: ec912a7512f681b43bb4cc56873631af\nMonoImporter:\n externalObjects: {}\n serializedVersion: 2\n "
},
{
"path": "Assets/Scripts/Helper/TimeHelper.cs",
"chars": 502,
"preview": "using System;\n\nnamespace UNetwork\n{\n\tpublic static class TimeHelper\n\t{\n\t\tprivate static readonly long epoch = new DateT"
},
{
"path": "Assets/Scripts/Helper/TimeHelper.cs.meta",
"chars": 243,
"preview": "fileFormatVersion: 2\nguid: 53e39d24f06688d4d961473c5a977410\nMonoImporter:\n externalObjects: {}\n serializedVersion: 2\n "
},
{
"path": "Assets/Scripts/Helper.meta",
"chars": 172,
"preview": "fileFormatVersion: 2\nguid: 3a479f7d4b18e0f439a7ba86124bebe4\nfolderAsset: yes\nDefaultImporter:\n externalObjects: {}\n us"
},
{
"path": "Assets/Scripts/Network/AChannel.cs",
"chars": 2025,
"preview": "using System;\nusing System.IO;\nusing System.Net;\nusing UnityEngine;\n\nnamespace UNetwork\n{\n public enum ChannelType\n "
},
{
"path": "Assets/Scripts/Network/AChannel.cs.meta",
"chars": 263,
"preview": "fileFormatVersion: 2\nguid: 05a074f965a8c214f8f1f1af1ecf4dcc\ntimeCreated: 1503986857\nlicenseType: Free\nMonoImporter:\n se"
},
{
"path": "Assets/Scripts/Network/AService.cs",
"chars": 396,
"preview": "using System;\nusing System.Net;\n\nnamespace UNetwork\n{\n\tpublic enum NetworkProtocol\n\t{\n\t\tKCP,\n\t\tTCP,\n\t\tWebSocket,\n\t}\n\n\tp"
},
{
"path": "Assets/Scripts/Network/AService.cs.meta",
"chars": 263,
"preview": "fileFormatVersion: 2\nguid: b5af0de1c471e6c43989dc0349cc2bba\ntimeCreated: 1503986858\nlicenseType: Free\nMonoImporter:\n se"
},
{
"path": "Assets/Scripts/Network/ClientManager.cs",
"chars": 2603,
"preview": "using System;\nusing System.Net;\nusing System.Threading;\n\nnamespace UNetwork\n{\n /// <summary>\n /// 客户端的 业务逻辑 管理类\n "
},
{
"path": "Assets/Scripts/Network/ClientManager.cs.meta",
"chars": 263,
"preview": "fileFormatVersion: 2\nguid: 151d2db7aab5bc8438bc039443ba0e3b\ntimeCreated: 1498117616\nlicenseType: Free\nMonoImporter:\n se"
},
{
"path": "Assets/Scripts/Network/Core/KCP/KCP.cs",
"chars": 35468,
"preview": "// Copyright (C) 2017 prototyped.cn All rights reserved.\n// Distributed under the terms and conditions of the MIT Licens"
},
{
"path": "Assets/Scripts/Network/Core/KCP/KCP.cs.meta",
"chars": 243,
"preview": "fileFormatVersion: 2\nguid: 20f9afa1793f2d54f811abe0972ada7c\nMonoImporter:\n externalObjects: {}\n serializedVersion: 2\n "
},
{
"path": "Assets/Scripts/Network/Core/KCP/KChannel.cs",
"chars": 12915,
"preview": "using System;\nusing System.Collections.Generic;\nusing System.IO;\nusing System.Net;\nusing System.Net.Sockets;\nusing Unit"
},
{
"path": "Assets/Scripts/Network/Core/KCP/KChannel.cs.meta",
"chars": 263,
"preview": "fileFormatVersion: 2\nguid: 5479891425d5a284fb4c8246e1a52d34\ntimeCreated: 1511491627\nlicenseType: Free\nMonoImporter:\n se"
},
{
"path": "Assets/Scripts/Network/Core/KCP/KService.cs",
"chars": 3181,
"preview": "using System;\nusing System.Collections.Generic;\nusing System.Net;\nusing System.Net.Sockets;\nusing Microsoft.IO;\nusing U"
},
{
"path": "Assets/Scripts/Network/Core/KCP/KService.cs.meta",
"chars": 263,
"preview": "fileFormatVersion: 2\nguid: 38037f5390cd34e41849290ca1737863\ntimeCreated: 1511491627\nlicenseType: Free\nMonoImporter:\n se"
},
{
"path": "Assets/Scripts/Network/Core/KCP/KcpDll.cs",
"chars": 6735,
"preview": "using System;\nusing System.Runtime.InteropServices;\n\nnamespace UNetwork\n{\n public delegate int KcpOutput(IntPtr buf,"
},
{
"path": "Assets/Scripts/Network/Core/KCP/KcpDll.cs.meta",
"chars": 263,
"preview": "fileFormatVersion: 2\nguid: 0832a74dcd3e44341bcffd3b1f182419\ntimeCreated: 1511491627\nlicenseType: Free\nMonoImporter:\n se"
},
{
"path": "Assets/Scripts/Network/Core/KCP.meta",
"chars": 192,
"preview": "fileFormatVersion: 2\nguid: 80771ba2b140e0f47b8df6dfe75d5c68\nfolderAsset: yes\ntimeCreated: 1511491627\nlicenseType: Free\nD"
},
{
"path": "Assets/Scripts/Network/Core/TCP/PacketParser.cs",
"chars": 2653,
"preview": "using System;\nusing System.IO;\n\nnamespace UNetwork\n{\n\tpublic enum ParserState\n\t{\n\t\tPacketSize,\n\t\tPacketBody\n\t}\n\t\n\tpubli"
},
{
"path": "Assets/Scripts/Network/Core/TCP/PacketParser.cs.meta",
"chars": 263,
"preview": "fileFormatVersion: 2\nguid: 8b71d12882faac44992e531533491a5f\ntimeCreated: 1503986857\nlicenseType: Free\nMonoImporter:\n se"
},
{
"path": "Assets/Scripts/Network/Core/TCP/TChannel.cs",
"chars": 7160,
"preview": "using System;\nusing System.IO;\nusing System.Net;\nusing System.Net.Sockets;\nusing UnityEngine;\n\nnamespace UNetwork\n{\n\t//"
},
{
"path": "Assets/Scripts/Network/Core/TCP/TChannel.cs.meta",
"chars": 263,
"preview": "fileFormatVersion: 2\nguid: 4cacc90d7e561c64a8ea0e9079163bb9\ntimeCreated: 1503986857\nlicenseType: Free\nMonoImporter:\n se"
},
{
"path": "Assets/Scripts/Network/Core/TCP/TChannelConnector.cs",
"chars": 9059,
"preview": "using System;\nusing System.IO;\nusing System.Net.Sockets;\nusing System.Text;\nusing UnityEngine;\nusing UnityEngine.Events"
},
{
"path": "Assets/Scripts/Network/Core/TCP/TChannelConnector.cs.meta",
"chars": 83,
"preview": "fileFormatVersion: 2\nguid: 1740169c35694ff9aa464756e50c4646\ntimeCreated: 1719314153"
},
{
"path": "Assets/Scripts/Network/Core/TCP/TChannelServer.cs",
"chars": 3146,
"preview": "using System;\nusing System.Collections.Generic;\nusing System.IO;\nusing System.Net;\nusing System.Net.Sockets;\nusing Unit"
},
{
"path": "Assets/Scripts/Network/Core/TCP/TChannelServer.cs.meta",
"chars": 84,
"preview": "fileFormatVersion: 2\nguid: e1134ac288dc42f2892e29f9f7c754e0\ntimeCreated: 1719304015"
},
{
"path": "Assets/Scripts/Network/Core/TCP/TService.cs",
"chars": 1129,
"preview": "using System;\nusing System.Net;\nusing System.Net.Sockets;\nusing Microsoft.IO;\nusing UnityEngine;\n\nnamespace UNetwork\n{\n"
},
{
"path": "Assets/Scripts/Network/Core/TCP/TService.cs.meta",
"chars": 263,
"preview": "fileFormatVersion: 2\nguid: 9c6cb526a0e4374438cbcbaa70239e4a\ntimeCreated: 1503986857\nlicenseType: Free\nMonoImporter:\n se"
},
{
"path": "Assets/Scripts/Network/Core/TCP/TServiceServer.cs",
"chars": 1096,
"preview": "using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Net;\nusing System.Net.Sockets;\nusing Mi"
},
{
"path": "Assets/Scripts/Network/Core/TCP/TServiceServer.cs.meta",
"chars": 84,
"preview": "fileFormatVersion: 2\nguid: a284183e90dc44f4a26c8434514d7da0\ntimeCreated: 1719304034"
},
{
"path": "Assets/Scripts/Network/Core/TCP.meta",
"chars": 191,
"preview": "fileFormatVersion: 2\nguid: 2b578de151e7f46489a1326f6b38658c\nfolderAsset: yes\ntimeCreated: 1440989101\nlicenseType: Pro\nDe"
},
{
"path": "Assets/Scripts/Network/Core/WebSocket/WChannel.cs",
"chars": 5667,
"preview": "using System;\nusing System.Collections.Generic;\nusing System.IO;\nusing System.Net.WebSockets;\nusing System.Threading;\nus"
},
{
"path": "Assets/Scripts/Network/Core/WebSocket/WChannel.cs.meta",
"chars": 243,
"preview": "fileFormatVersion: 2\nguid: 8e9431d46e7e100479fce069d4c08079\nMonoImporter:\n externalObjects: {}\n serializedVersion: 2\n "
},
{
"path": "Assets/Scripts/Network/Core/WebSocket/WService.cs",
"chars": 1113,
"preview": "using System;\nusing System.Collections.Generic;\nusing System.Net;\nusing System.Net.WebSockets;\nusing Microsoft.IO;\nusing"
},
{
"path": "Assets/Scripts/Network/Core/WebSocket/WService.cs.meta",
"chars": 243,
"preview": "fileFormatVersion: 2\nguid: ab08a203cf5da164c86fbc14d09e3a3b\nMonoImporter:\n externalObjects: {}\n serializedVersion: 2\n "
},
{
"path": "Assets/Scripts/Network/Core/WebSocket.meta",
"chars": 172,
"preview": "fileFormatVersion: 2\nguid: 02cb26b1214c31847af71b0796e90476\nfolderAsset: yes\nDefaultImporter:\n externalObjects: {}\n us"
},
{
"path": "Assets/Scripts/Network/Core.meta",
"chars": 172,
"preview": "fileFormatVersion: 2\nguid: 819d45d33f6b1124e9159ed5ef0bd490\nfolderAsset: yes\nDefaultImporter:\n externalObjects: {}\n us"
},
{
"path": "Assets/Scripts/Network/INetworkManager.cs",
"chars": 364,
"preview": "using System;\n\nnamespace UNetwork\n{\n public interface INetworkManager\n {\n public IMessagePacker MessagePac"
},
{
"path": "Assets/Scripts/Network/INetworkManager.cs.meta",
"chars": 84,
"preview": "fileFormatVersion: 2\nguid: ec147b2fba3e42f1a6c41924df308bfb\ntimeCreated: 1719310787"
},
{
"path": "Assets/Scripts/Network/Message/Circularbuffer.cs",
"chars": 7696,
"preview": "using System;\nusing System.Collections.Generic;\nusing System.IO;\nusing UnityEngine;\n\nnamespace UNetwork\n{\n public cl"
},
{
"path": "Assets/Scripts/Network/Message/Circularbuffer.cs.meta",
"chars": 263,
"preview": "fileFormatVersion: 2\nguid: ea037025225a9c74b8ddb5349b0c18a6\ntimeCreated: 1503986858\nlicenseType: Free\nMonoImporter:\n se"
},
{
"path": "Assets/Scripts/Network/Message/ErrorCode.cs",
"chars": 1424,
"preview": "namespace UNetwork\n{\n\tpublic static class ErrorCode\n\t{\n\t\tpublic const int ERR_Success = 0;\n\t\t\n\t\t// 1-11004 是SocketError请"
},
{
"path": "Assets/Scripts/Network/Message/ErrorCode.cs.meta",
"chars": 263,
"preview": "fileFormatVersion: 2\nguid: 303bb884f0f9ad24da9b0fe1acbcedaf\ntimeCreated: 1501467234\nlicenseType: Free\nMonoImporter:\n se"
},
{
"path": "Assets/Scripts/Network/Message/IMessage.cs",
"chars": 407,
"preview": "namespace UNetwork\n{\n\tpublic interface IMessage\n\t{\n\t}\n\t\n\tpublic interface IRequest: IMessage\n\t{\n\t\tint RpcId { get; set;"
},
{
"path": "Assets/Scripts/Network/Message/IMessage.cs.meta",
"chars": 243,
"preview": "fileFormatVersion: 2\nguid: 7f7b01638a2ed1242a9b81b7d6f408eb\nMonoImporter:\n externalObjects: {}\n serializedVersion: 2\n "
},
{
"path": "Assets/Scripts/Network/Message/IMessageDispatcher.cs",
"chars": 116,
"preview": "namespace UNetwork\n{\n\tpublic interface IMessageDispatcher\n\t{\n\t\tvoid Dispatch(Session session, byte[] buffer);\n\t}\n}\n"
},
{
"path": "Assets/Scripts/Network/Message/IMessageDispatcher.cs.meta",
"chars": 243,
"preview": "fileFormatVersion: 2\nguid: 69481855785b4b59834c766e4e2798e1\nMonoImporter:\n externalObjects: {}\n serializedVersion: 2\n "
},
{
"path": "Assets/Scripts/Network/Message/IMessagePacker.cs",
"chars": 456,
"preview": "using System;\nusing System.IO;\n\nnamespace UNetwork\n{\n\tpublic interface IMessagePacker\n\t{\n\t\tbyte[] SerializeTo(object ob"
},
{
"path": "Assets/Scripts/Network/Message/IMessagePacker.cs.meta",
"chars": 243,
"preview": "fileFormatVersion: 2\nguid: 09fe3a4882b1b50498860b3f672d1d47\nMonoImporter:\n externalObjects: {}\n serializedVersion: 2\n "
},
{
"path": "Assets/Scripts/Network/Message/MessageInfo.cs",
"chars": 235,
"preview": "namespace UNetwork\n{\n\tpublic struct MessageInfo\n\t{\n\t\tpublic ushort Opcode { get; }\n\t\tpublic object Message { get; }\n\n\t\t"
},
{
"path": "Assets/Scripts/Network/Message/MessageInfo.cs.meta",
"chars": 263,
"preview": "fileFormatVersion: 2\nguid: 0b54864d3eb34ee4b90665941ecf5b87\ntimeCreated: 1501467234\nlicenseType: Free\nMonoImporter:\n se"
},
{
"path": "Assets/Scripts/Network/Message/MessagePool.cs",
"chars": 1020,
"preview": "using System;\nusing System.Collections.Generic;\t\t\n\nnamespace UNetwork\n{\n\t// 客户端为了0GC需要消息池,服务端消息需要跨协程不需要消息池\n\tpublic clas"
},
{
"path": "Assets/Scripts/Network/Message/MessagePool.cs.meta",
"chars": 243,
"preview": "fileFormatVersion: 2\nguid: 1d413cb22ac106a439af32933382ce66\nMonoImporter:\n externalObjects: {}\n serializedVersion: 2\n "
},
{
"path": "Assets/Scripts/Network/Message/Opcode.cs",
"chars": 189,
"preview": "namespace UNetwork\n{\n\tpublic static partial class Opcode\n\t{\n\t\tpublic const ushort ActorResponse = 1;\n\t\tpublic const usho"
},
{
"path": "Assets/Scripts/Network/Message/Opcode.cs.meta",
"chars": 263,
"preview": "fileFormatVersion: 2\nguid: 129811e752b0782479b48ee6a12e1f2b\ntimeCreated: 1517571639\nlicenseType: Free\nMonoImporter:\n se"
},
{
"path": "Assets/Scripts/Network/Message/OuterMessageDispatcher.cs",
"chars": 478,
"preview": "using System;\nusing System.Text;\nusing UnityEngine;\n\nnamespace UNetwork\n{\n\tpublic class OuterMessageDispatcher: IMessag"
},
{
"path": "Assets/Scripts/Network/Message/OuterMessageDispatcher.cs.meta",
"chars": 243,
"preview": "fileFormatVersion: 2\nguid: 1019c6e4151c2374390b6f30c09e0e1f\nMonoImporter:\n externalObjects: {}\n serializedVersion: 2\n "
},
{
"path": "Assets/Scripts/Network/Message/ProtobufPacker.cs",
"chars": 1218,
"preview": "using System;\nusing System.IO;\nusing System.Runtime.Serialization.Formatters.Binary;\nusing System.Text;\n\nnamespace UNet"
},
{
"path": "Assets/Scripts/Network/Message/ProtobufPacker.cs.meta",
"chars": 243,
"preview": "fileFormatVersion: 2\nguid: 26802b02461a1454499ebc037e012b5f\nMonoImporter:\n externalObjects: {}\n serializedVersion: 2\n "
},
{
"path": "Assets/Scripts/Network/Message/RecyclableMemoryStream/Events.cs",
"chars": 7307,
"preview": "// ---------------------------------------------------------------------\n// Copyright (c) 2015 Microsoft\n//\n// Permissi"
},
{
"path": "Assets/Scripts/Network/Message/RecyclableMemoryStream/Events.cs.meta",
"chars": 262,
"preview": "fileFormatVersion: 2\nguid: 52cd395d4cf275c48b1f8690689d3869\ntimeCreated: 1527234045\nlicenseType: Pro\nMonoImporter:\n ser"
},
{
"path": "Assets/Scripts/Network/Message/RecyclableMemoryStream/OneThreadSynchronizationContext.cs",
"chars": 883,
"preview": "using System;\nusing System.Collections.Concurrent;\nusing System.Threading;\n\nnamespace UNetwork\n{\n\tpublic class OneThrea"
},
{
"path": "Assets/Scripts/Network/Message/RecyclableMemoryStream/OneThreadSynchronizationContext.cs.meta",
"chars": 243,
"preview": "fileFormatVersion: 2\nguid: f9b9ed5f7ab66544eb242d9f98cf1a6b\nMonoImporter:\n externalObjects: {}\n serializedVersion: 2\n "
},
{
"path": "Assets/Scripts/Network/Message/RecyclableMemoryStream/RecyclableMemoryStream.cs",
"chars": 35517,
"preview": "// The MIT License (MIT)\n// \n// Copyright (c) 2015-2016 Microsoft\n// \n// Permission is hereby granted, free of charge, "
},
{
"path": "Assets/Scripts/Network/Message/RecyclableMemoryStream/RecyclableMemoryStream.cs.meta",
"chars": 262,
"preview": "fileFormatVersion: 2\nguid: 04ecc2633820de7459b8ba26a114f62f\ntimeCreated: 1527234045\nlicenseType: Pro\nMonoImporter:\n ser"
},
{
"path": "Assets/Scripts/Network/Message/RecyclableMemoryStream/RecyclableMemoryStreamManager.cs",
"chars": 25808,
"preview": "// ---------------------------------------------------------------------\n// Copyright (c) 2015-2016 Microsoft\n//\n// Per"
},
{
"path": "Assets/Scripts/Network/Message/RecyclableMemoryStream/RecyclableMemoryStreamManager.cs.meta",
"chars": 262,
"preview": "fileFormatVersion: 2\nguid: e7f5123bf8a488045a8e48c49b605cc9\ntimeCreated: 1527234045\nlicenseType: Pro\nMonoImporter:\n ser"
},
{
"path": "Assets/Scripts/Network/Message/RecyclableMemoryStream.meta",
"chars": 172,
"preview": "fileFormatVersion: 2\nguid: ab0cd2080e97f064a9283d5729684c3e\nfolderAsset: yes\nDefaultImporter:\n externalObjects: {}\n us"
},
{
"path": "Assets/Scripts/Network/Message/Session.cs",
"chars": 3361,
"preview": "using System;\nusing System.IO;\nusing System.Net;\nusing UnityEngine;\n\nnamespace UNetwork\n{\n public sealed class Sessi"
},
{
"path": "Assets/Scripts/Network/Message/Session.cs.meta",
"chars": 263,
"preview": "fileFormatVersion: 2\nguid: 73d149d0c325fa24d91a94843bd520b8\ntimeCreated: 1498117617\nlicenseType: Free\nMonoImporter:\n se"
},
{
"path": "Assets/Scripts/Network/Message/SessionConnector.cs",
"chars": 1228,
"preview": "using System;\nusing System.IO;\nusing System.Net;\nusing UnityEngine;\n\nnamespace UNetwork\n{\n public sealed class Sessi"
},
{
"path": "Assets/Scripts/Network/Message/SessionConnector.cs.meta",
"chars": 84,
"preview": "fileFormatVersion: 2\nguid: 79080751d836414388644ba4afc4410b\ntimeCreated: 1720089809"
},
{
"path": "Assets/Scripts/Network/Message/SessionServer.cs",
"chars": 3369,
"preview": "using System;\nusing System.IO;\nusing System.Net;\nusing UnityEngine;\n\nnamespace UNetwork\n{\n public sealed class Sessi"
},
{
"path": "Assets/Scripts/Network/Message/SessionServer.cs.meta",
"chars": 83,
"preview": "fileFormatVersion: 2\nguid: d72cceac0b794ac596aed9abc9e343b6\ntimeCreated: 1719307380"
},
{
"path": "Assets/Scripts/Network/Message.meta",
"chars": 172,
"preview": "fileFormatVersion: 2\nguid: 6e2fe20a3053dc440938cf6c166337b2\nfolderAsset: yes\nDefaultImporter:\n externalObjects: {}\n us"
},
{
"path": "Assets/Scripts/Network/ServerManager.cs",
"chars": 2382,
"preview": "using System;\nusing System.Net;\nusing System.Threading;\n\nnamespace UNetwork\n{\n /// <summary>\n /// Server 服务器的 业务逻"
},
{
"path": "Assets/Scripts/Network/ServerManager.cs.meta",
"chars": 84,
"preview": "fileFormatVersion: 2\nguid: 84fd225f324f42999874057579220d14\ntimeCreated: 1719302713"
},
{
"path": "Assets/Scripts/Network.meta",
"chars": 191,
"preview": "fileFormatVersion: 2\nguid: 89949efe62b53a044928bcf3075aad2f\nfolderAsset: yes\ntimeCreated: 1474943042\nlicenseType: Pro\nDe"
},
{
"path": "Assets/Scripts/TestClient.cs",
"chars": 1662,
"preview": "using System;\nusing System.Text;\nusing UNetwork;\nusing UnityEngine;\n\npublic class TestClient : MonoBehaviour\n{\n publ"
},
{
"path": "Assets/Scripts/TestClient.cs.meta",
"chars": 243,
"preview": "fileFormatVersion: 2\nguid: c47d1a2e288e53f4285b397665f9a1dc\nMonoImporter:\n externalObjects: {}\n serializedVersion: 2\n "
},
{
"path": "Assets/Scripts/TestServer.cs",
"chars": 1589,
"preview": "using System;\nusing System.Text;\nusing UNetwork;\nusing UnityEngine;\n\npublic class TestServer : MonoBehaviour\n{\n publ"
},
{
"path": "Assets/Scripts/TestServer.cs.meta",
"chars": 84,
"preview": "fileFormatVersion: 2\nguid: 8518a6a6d5ca49ecb048613cc3a03e07\ntimeCreated: 1719304719"
},
{
"path": "Assets/Scripts.meta",
"chars": 172,
"preview": "fileFormatVersion: 2\nguid: 68234a28db005584e9d209109316f50f\nfolderAsset: yes\nDefaultImporter:\n externalObjects: {}\n us"
},
{
"path": "ProjectSettings/AudioManager.asset",
"chars": 360,
"preview": "%YAML 1.1\n%TAG !u! tag:unity3d.com,2011:\n--- !u!11 &1\nAudioManager:\n m_ObjectHideFlags: 0\n m_Volume: 1\n Rolloff Scale"
},
{
"path": "ProjectSettings/AutoStreamingSettings.asset",
"chars": 379,
"preview": "%YAML 1.1\n%TAG !u! tag:unity3d.com,2011:\n--- !u!1200 &1\nAutoStreamingSettings:\n m_ObjectHideFlags: 0\n serializedVersio"
},
{
"path": "ProjectSettings/ClusterInputManager.asset",
"chars": 114,
"preview": "%YAML 1.1\n%TAG !u! tag:unity3d.com,2011:\n--- !u!236 &1\nClusterInputManager:\n m_ObjectHideFlags: 0\n m_Inputs: []\n"
},
{
"path": "ProjectSettings/DynamicsManager.asset",
"chars": 1075,
"preview": "%YAML 1.1\n%TAG !u! tag:unity3d.com,2011:\n--- !u!55 &1\nPhysicsManager:\n m_ObjectHideFlags: 0\n serializedVersion: 8\n m_"
},
{
"path": "ProjectSettings/EditorBuildSettings.asset",
"chars": 160,
"preview": "%YAML 1.1\n%TAG !u! tag:unity3d.com,2011:\n--- !u!1045 &1\nEditorBuildSettings:\n m_ObjectHideFlags: 0\n serializedVersion:"
},
{
"path": "ProjectSettings/EditorSettings.asset",
"chars": 715,
"preview": "%YAML 1.1\n%TAG !u! tag:unity3d.com,2011:\n--- !u!159 &1\nEditorSettings:\n m_ObjectHideFlags: 0\n serializedVersion: 7\n m"
},
{
"path": "ProjectSettings/GraphicsSettings.asset",
"chars": 1949,
"preview": "%YAML 1.1\n%TAG !u! tag:unity3d.com,2011:\n--- !u!30 &1\nGraphicsSettings:\n m_ObjectHideFlags: 0\n serializedVersion: 12\n "
},
{
"path": "ProjectSettings/InputManager.asset",
"chars": 5793,
"preview": "%YAML 1.1\n%TAG !u! tag:unity3d.com,2011:\n--- !u!13 &1\nInputManager:\n m_ObjectHideFlags: 0\n serializedVersion: 2\n m_Ax"
},
{
"path": "ProjectSettings/MemorySettings.asset",
"chars": 1192,
"preview": "%YAML 1.1\n%TAG !u! tag:unity3d.com,2011:\n--- !u!387306366 &1\nMemorySettings:\n m_ObjectHideFlags: 0\n m_EditorMemorySett"
},
{
"path": "ProjectSettings/NavMeshAreas.asset",
"chars": 1308,
"preview": "%YAML 1.1\n%TAG !u! tag:unity3d.com,2011:\n--- !u!126 &1\nNavMeshProjectSettings:\n m_ObjectHideFlags: 0\n serializedVersio"
},
{
"path": "ProjectSettings/NetworkManager.asset",
"chars": 151,
"preview": "%YAML 1.1\n%TAG !u! tag:unity3d.com,2011:\n--- !u!149 &1\nNetworkManager:\n m_ObjectHideFlags: 0\n m_DebugLevel: 0\n m_Send"
},
{
"path": "ProjectSettings/PackageManagerSettings.asset",
"chars": 949,
"preview": "%YAML 1.1\n%TAG !u! tag:unity3d.com,2011:\n--- !u!114 &1\nMonoBehaviour:\n m_ObjectHideFlags: 61\n m_CorrespondingSourceObj"
},
{
"path": "ProjectSettings/Physics2DSettings.asset",
"chars": 2028,
"preview": "%YAML 1.1\n%TAG !u! tag:unity3d.com,2011:\n--- !u!19 &1\nPhysics2DSettings:\n m_ObjectHideFlags: 0\n serializedVersion: 4\n "
},
{
"path": "ProjectSettings/PresetManager.asset",
"chars": 342,
"preview": "%YAML 1.1\n%TAG !u! tag:unity3d.com,2011:\n--- !u!1386491679 &1\nPresetManager:\n m_ObjectHideFlags: 0\n m_DefaultList:\n -"
},
{
"path": "ProjectSettings/ProjectSettings.asset",
"chars": 21818,
"preview": "%YAML 1.1\n%TAG !u! tag:unity3d.com,2011:\n--- !u!129 &1\nPlayerSettings:\n m_ObjectHideFlags: 0\n serializedVersion: 24\n "
},
{
"path": "ProjectSettings/ProjectVersion.txt",
"chars": 89,
"preview": "m_EditorVersion: 2021.3.36f1c1\nm_EditorVersionWithRevision: 2021.3.36f1c1 (0ec3cfe9a403)\n"
},
{
"path": "ProjectSettings/QualitySettings.asset",
"chars": 4852,
"preview": "%YAML 1.1\n%TAG !u! tag:unity3d.com,2011:\n--- !u!47 &1\nQualitySettings:\n m_ObjectHideFlags: 0\n serializedVersion: 5\n m"
},
{
"path": "ProjectSettings/SceneTemplateSettings.json",
"chars": 3534,
"preview": "{\n \"templatePinStates\": [],\n \"dependencyTypeInfos\": [\n {\n \"userAdded\": false,\n \"type\""
},
{
"path": "ProjectSettings/TagManager.asset",
"chars": 378,
"preview": "%YAML 1.1\n%TAG !u! tag:unity3d.com,2011:\n--- !u!78 &1\nTagManager:\n serializedVersion: 2\n tags: []\n layers:\n - Defaul"
},
{
"path": "ProjectSettings/TimeManager.asset",
"chars": 195,
"preview": "%YAML 1.1\n%TAG !u! tag:unity3d.com,2011:\n--- !u!5 &1\nTimeManager:\n m_ObjectHideFlags: 0\n Fixed Timestep: 0.02\n Maximu"
},
{
"path": "ProjectSettings/UnityConnectSettings.asset",
"chars": 853,
"preview": "%YAML 1.1\n%TAG !u! tag:unity3d.com,2011:\n--- !u!310 &1\nUnityConnectSettings:\n m_ObjectHideFlags: 0\n serializedVersion:"
},
{
"path": "ProjectSettings/VFXManager.asset",
"chars": 273,
"preview": "%YAML 1.1\n%TAG !u! tag:unity3d.com,2011:\n--- !u!937362698 &1\nVFXManager:\n m_ObjectHideFlags: 0\n m_IndirectShader: {fil"
},
{
"path": "ProjectSettings/VersionControlSettings.asset",
"chars": 188,
"preview": "%YAML 1.1\n%TAG !u! tag:unity3d.com,2011:\n--- !u!890905787 &1\nVersionControlSettings:\n m_ObjectHideFlags: 0\n m_Mode: Vi"
},
{
"path": "ProjectSettings/boot.config",
"chars": 0,
"preview": ""
},
{
"path": "README.md",
"chars": 1460,
"preview": "# kcp-unity\n\nKCP是一种基于UDP的上层协议,项目地址:[KCP – A Fast and Reliable ARQ Protocol](https://github.com/skywind3000/kcp)\n\nkcp就是在u"
}
]
// ... and 2 more files (download for full content)
About this extraction
This page contains the full source code of the passiony/kcp-unity GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 143 files (271.8 KB), approximately 76.7k tokens, and a symbol index with 437 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.