From 20d5bca560b7ffdf8263177dcb44a321f4f72d7d Mon Sep 17 00:00:00 2001 From: ldcsaa Date: Tue, 8 Jul 2014 10:54:05 +0800 Subject: [PATCH] 20140708 --- .../C#/HPSocket4CS/CSharpTestEcho-4C.sln | 150 ++ .../HPSocket4CS/HPSocketCS/HPSocketCS.csproj | 89 + .../HPSocketCS/Properties/AssemblyInfo.cs | 36 + .../C#/HPSocket4CS/HPSocketCS/Sdk.cs | 1914 +++++++++++++++++ .../C#/HPSocket4CS/HPSocketCS/Sdk.rar | Bin 0 -> 6723 bytes .../C#/HPSocket4CS/HPSocketCS/TcpAgent.cs | 1112 ++++++++++ .../C#/HPSocket4CS/HPSocketCS/TcpClient.cs | 843 ++++++++ .../C#/HPSocket4CS/HPSocketCS/TcpPullAgent.cs | 128 ++ .../HPSocket4CS/HPSocketCS/TcpPullClient.cs | 126 ++ .../HPSocket4CS/HPSocketCS/TcpPullServer.cs | 124 ++ .../C#/HPSocket4CS/HPSocketCS/TcpServer.cs | 1153 ++++++++++ .../C#/HPSocket4CS/TcpClient-PFM/Program.cs | 21 + .../TcpClient-PFM/Properties/AssemblyInfo.cs | 36 + .../Properties/Resources.Designer.cs | 63 + .../TcpClient-PFM/Properties/Resources.resx | 117 + .../Properties/Settings.Designer.cs | 26 + .../Properties/Settings.settings | 7 + .../TcpClient-PFM/TcpClient-PFM.csproj | 122 ++ .../TcpClient-PFM/frmClient.Designer.cs | 291 +++ .../C#/HPSocket4CS/TcpClient-PFM/frmClient.cs | 391 ++++ .../HPSocket4CS/TcpClient-PFM/frmClient.resx | 120 ++ .../C#/HPSocket4CS/TcpClient/Program.cs | 21 + .../TcpClient/Properties/AssemblyInfo.cs | 36 + .../Properties/Resources.Designer.cs | 63 + .../TcpClient/Properties/Resources.resx | 117 + .../TcpClient/Properties/Settings.Designer.cs | 26 + .../TcpClient/Properties/Settings.settings | 7 + .../C#/HPSocket4CS/TcpClient/TcpClient.csproj | 127 ++ .../TcpClient/frmClient.Designer.cs | 205 ++ .../C#/HPSocket4CS/TcpClient/frmClient.cs | 550 +++++ .../C#/HPSocket4CS/TcpClient/frmClient.resx | 120 ++ .../C#/HPSocket4CS/TcpProxyServer/Program.cs | 21 + .../TcpProxyServer/Properties/AssemblyInfo.cs | 36 + .../Properties/Resources.Designer.cs | 71 + .../TcpProxyServer/Properties/Resources.resx | 117 + .../Properties/Settings.Designer.cs | 30 + .../Properties/Settings.settings | 7 + .../HPSocket4CS/TcpProxyServer/ProxyServer.cs | 415 ++++ .../TcpProxyServer/TcpProxyServer.csproj | 122 ++ .../TcpProxyServer/frmProxyServer.Designer.cs | 198 ++ .../TcpProxyServer/frmProxyServer.cs | 183 ++ .../TcpProxyServer/frmProxyServer.resx | 120 ++ .../C#/HPSocket4CS/TcpPullClient/Program.cs | 21 + .../TcpPullClient/Properties/AssemblyInfo.cs | 36 + .../Properties/Resources.Designer.cs | 63 + .../TcpPullClient/Properties/Resources.resx | 117 + .../Properties/Settings.Designer.cs | 26 + .../Properties/Settings.settings | 7 + .../TcpPullClient/TcpPullClient.csproj | 127 ++ .../TcpPullClient/frmClient.Designer.cs | 177 ++ .../C#/HPSocket4CS/TcpPullClient/frmClient.cs | 374 ++++ .../HPSocket4CS/TcpPullClient/frmClient.resx | 120 ++ .../C#/HPSocket4CS/TcpPullServer/Program.cs | 21 + .../TcpPullServer/Properties/AssemblyInfo.cs | 36 + .../Properties/Resources.Designer.cs | 63 + .../TcpPullServer/Properties/Resources.resx | 117 + .../Properties/Settings.Designer.cs | 26 + .../Properties/Settings.settings | 7 + .../TcpPullServer/TcpPullServer.csproj | 126 ++ .../TcpPullServer/frmServer.Designer.cs | 169 ++ .../C#/HPSocket4CS/TcpPullServer/frmServer.cs | 392 ++++ .../HPSocket4CS/TcpPullServer/frmServer.resx | 120 ++ .../C#/HPSocket4CS/TcpServer-PFM/Program.cs | 21 + .../TcpServer-PFM/Properties/AssemblyInfo.cs | 36 + .../Properties/Resources.Designer.cs | 63 + .../TcpServer-PFM/Properties/Resources.resx | 117 + .../Properties/Settings.Designer.cs | 26 + .../Properties/Settings.settings | 7 + .../TcpServer-PFM/TcpServer-PFM.csproj | 122 ++ .../TcpServer-PFM/frmServer.Designer.cs | 169 ++ .../C#/HPSocket4CS/TcpServer-PFM/frmServer.cs | 378 ++++ .../HPSocket4CS/TcpServer-PFM/frmServer.resx | 120 ++ .../C#/HPSocket4CS/TcpServer/Program.cs | 21 + .../TcpServer/Properties/AssemblyInfo.cs | 36 + .../Properties/Resources.Designer.cs | 63 + .../TcpServer/Properties/Resources.resx | 117 + .../TcpServer/Properties/Settings.Designer.cs | 26 + .../TcpServer/Properties/Settings.settings | 7 + .../C#/HPSocket4CS/TcpServer/TcpServer.csproj | 122 ++ .../TcpServer/frmServer.Designer.cs | 169 ++ .../C#/HPSocket4CS/TcpServer/frmServer.cs | 318 +++ .../C#/HPSocket4CS/TcpServer/frmServer.resx | 120 ++ .../bin/x64/Release/HPSocket4C_U.dll | Bin 0 -> 216064 bytes .../bin/x64/Release/HPSocketCS.dll | Bin 0 -> 44544 bytes .../bin/x64/Release/TcpClient-PFM.exe | Bin 0 -> 17920 bytes .../HPSocket4CS/bin/x64/Release/TcpClient.exe | Bin 0 -> 19456 bytes .../bin/x64/Release/TcpProxyServer.exe | Bin 0 -> 18432 bytes .../bin/x64/Release/TcpPullClient.exe | Bin 0 -> 15360 bytes .../bin/x64/Release/TcpPullServer.exe | Bin 0 -> 16384 bytes .../bin/x64/Release/TcpServer-PFM.exe | Bin 0 -> 15360 bytes .../HPSocket4CS/bin/x64/Release/TcpServer.exe | Bin 0 -> 15360 bytes .../bin/x86/Release/HPSocket4C_U.dll | Bin 0 -> 181760 bytes .../bin/x86/Release/HPSocketCS.dll | Bin 0 -> 44544 bytes .../bin/x86/Release/TcpClient-PFM.exe | Bin 0 -> 18432 bytes .../HPSocket4CS/bin/x86/Release/TcpClient.exe | Bin 0 -> 19968 bytes .../bin/x86/Release/TcpProxyServer.exe | Bin 0 -> 18944 bytes .../bin/x86/Release/TcpPullClient.exe | Bin 0 -> 15872 bytes .../bin/x86/Release/TcpPullServer.exe | Bin 0 -> 16896 bytes .../bin/x86/Release/TcpServer-PFM.exe | Bin 0 -> 15872 bytes .../HPSocket4CS/bin/x86/Release/TcpServer.exe | Bin 0 -> 15872 bytes 100 files changed, 13664 insertions(+) create mode 100644 HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/CSharpTestEcho-4C.sln create mode 100644 HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/HPSocketCS/HPSocketCS.csproj create mode 100644 HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/HPSocketCS/Properties/AssemblyInfo.cs create mode 100644 HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/HPSocketCS/Sdk.cs create mode 100644 HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/HPSocketCS/Sdk.rar create mode 100644 HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/HPSocketCS/TcpAgent.cs create mode 100644 HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/HPSocketCS/TcpClient.cs create mode 100644 HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/HPSocketCS/TcpPullAgent.cs create mode 100644 HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/HPSocketCS/TcpPullClient.cs create mode 100644 HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/HPSocketCS/TcpPullServer.cs create mode 100644 HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/HPSocketCS/TcpServer.cs create mode 100644 HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpClient-PFM/Program.cs create mode 100644 HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpClient-PFM/Properties/AssemblyInfo.cs create mode 100644 HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpClient-PFM/Properties/Resources.Designer.cs create mode 100644 HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpClient-PFM/Properties/Resources.resx create mode 100644 HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpClient-PFM/Properties/Settings.Designer.cs create mode 100644 HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpClient-PFM/Properties/Settings.settings create mode 100644 HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpClient-PFM/TcpClient-PFM.csproj create mode 100644 HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpClient-PFM/frmClient.Designer.cs create mode 100644 HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpClient-PFM/frmClient.cs create mode 100644 HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpClient-PFM/frmClient.resx create mode 100644 HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpClient/Program.cs create mode 100644 HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpClient/Properties/AssemblyInfo.cs create mode 100644 HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpClient/Properties/Resources.Designer.cs create mode 100644 HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpClient/Properties/Resources.resx create mode 100644 HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpClient/Properties/Settings.Designer.cs create mode 100644 HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpClient/Properties/Settings.settings create mode 100644 HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpClient/TcpClient.csproj create mode 100644 HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpClient/frmClient.Designer.cs create mode 100644 HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpClient/frmClient.cs create mode 100644 HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpClient/frmClient.resx create mode 100644 HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpProxyServer/Program.cs create mode 100644 HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpProxyServer/Properties/AssemblyInfo.cs create mode 100644 HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpProxyServer/Properties/Resources.Designer.cs create mode 100644 HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpProxyServer/Properties/Resources.resx create mode 100644 HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpProxyServer/Properties/Settings.Designer.cs create mode 100644 HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpProxyServer/Properties/Settings.settings create mode 100644 HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpProxyServer/ProxyServer.cs create mode 100644 HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpProxyServer/TcpProxyServer.csproj create mode 100644 HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpProxyServer/frmProxyServer.Designer.cs create mode 100644 HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpProxyServer/frmProxyServer.cs create mode 100644 HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpProxyServer/frmProxyServer.resx create mode 100644 HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpPullClient/Program.cs create mode 100644 HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpPullClient/Properties/AssemblyInfo.cs create mode 100644 HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpPullClient/Properties/Resources.Designer.cs create mode 100644 HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpPullClient/Properties/Resources.resx create mode 100644 HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpPullClient/Properties/Settings.Designer.cs create mode 100644 HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpPullClient/Properties/Settings.settings create mode 100644 HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpPullClient/TcpPullClient.csproj create mode 100644 HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpPullClient/frmClient.Designer.cs create mode 100644 HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpPullClient/frmClient.cs create mode 100644 HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpPullClient/frmClient.resx create mode 100644 HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpPullServer/Program.cs create mode 100644 HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpPullServer/Properties/AssemblyInfo.cs create mode 100644 HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpPullServer/Properties/Resources.Designer.cs create mode 100644 HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpPullServer/Properties/Resources.resx create mode 100644 HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpPullServer/Properties/Settings.Designer.cs create mode 100644 HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpPullServer/Properties/Settings.settings create mode 100644 HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpPullServer/TcpPullServer.csproj create mode 100644 HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpPullServer/frmServer.Designer.cs create mode 100644 HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpPullServer/frmServer.cs create mode 100644 HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpPullServer/frmServer.resx create mode 100644 HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpServer-PFM/Program.cs create mode 100644 HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpServer-PFM/Properties/AssemblyInfo.cs create mode 100644 HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpServer-PFM/Properties/Resources.Designer.cs create mode 100644 HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpServer-PFM/Properties/Resources.resx create mode 100644 HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpServer-PFM/Properties/Settings.Designer.cs create mode 100644 HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpServer-PFM/Properties/Settings.settings create mode 100644 HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpServer-PFM/TcpServer-PFM.csproj create mode 100644 HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpServer-PFM/frmServer.Designer.cs create mode 100644 HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpServer-PFM/frmServer.cs create mode 100644 HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpServer-PFM/frmServer.resx create mode 100644 HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpServer/Program.cs create mode 100644 HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpServer/Properties/AssemblyInfo.cs create mode 100644 HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpServer/Properties/Resources.Designer.cs create mode 100644 HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpServer/Properties/Resources.resx create mode 100644 HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpServer/Properties/Settings.Designer.cs create mode 100644 HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpServer/Properties/Settings.settings create mode 100644 HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpServer/TcpServer.csproj create mode 100644 HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpServer/frmServer.Designer.cs create mode 100644 HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpServer/frmServer.cs create mode 100644 HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpServer/frmServer.resx create mode 100644 HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/bin/x64/Release/HPSocket4C_U.dll create mode 100644 HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/bin/x64/Release/HPSocketCS.dll create mode 100644 HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/bin/x64/Release/TcpClient-PFM.exe create mode 100644 HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/bin/x64/Release/TcpClient.exe create mode 100644 HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/bin/x64/Release/TcpProxyServer.exe create mode 100644 HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/bin/x64/Release/TcpPullClient.exe create mode 100644 HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/bin/x64/Release/TcpPullServer.exe create mode 100644 HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/bin/x64/Release/TcpServer-PFM.exe create mode 100644 HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/bin/x64/Release/TcpServer.exe create mode 100644 HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/bin/x86/Release/HPSocket4C_U.dll create mode 100644 HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/bin/x86/Release/HPSocketCS.dll create mode 100644 HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/bin/x86/Release/TcpClient-PFM.exe create mode 100644 HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/bin/x86/Release/TcpClient.exe create mode 100644 HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/bin/x86/Release/TcpProxyServer.exe create mode 100644 HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/bin/x86/Release/TcpPullClient.exe create mode 100644 HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/bin/x86/Release/TcpPullServer.exe create mode 100644 HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/bin/x86/Release/TcpServer-PFM.exe create mode 100644 HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/bin/x86/Release/TcpServer.exe diff --git a/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/CSharpTestEcho-4C.sln b/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/CSharpTestEcho-4C.sln new file mode 100644 index 000000000..c5ce7f864 --- /dev/null +++ b/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/CSharpTestEcho-4C.sln @@ -0,0 +1,150 @@ + +Microsoft Visual Studio Solution File, Format Version 11.00 +# Visual Studio 2010 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HPSocketCS", "HPSocketCS\HPSocketCS.csproj", "{DFA935E2-CF37-4E26-B697-D7F3DEE19DD8}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TcpPullClient", "TcpPullClient\TcpPullClient.csproj", "{B9965E66-853A-47CC-B0C9-197B5A29ABFC}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TcpPullServer", "TcpPullServer\TcpPullServer.csproj", "{B6654857-4C82-4F92-AD7A-21FD3ED5BBFA}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TcpClient", "TcpClient\TcpClient.csproj", "{B6E43918-236A-4EA7-84C8-ED4A98049907}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TcpServer", "TcpServer\TcpServer.csproj", "{9A3339BC-37F0-4D03-9ACE-51CC4CF75277}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TcpProxyServer", "TcpProxyServer\TcpProxyServer.csproj", "{5FEB9E6D-2526-4F4F-957C-093D7FFB9B98}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TcpServer-PFM", "TcpServer-PFM\TcpServer-PFM.csproj", "{10426A79-A3B3-4CD2-BD84-02AAEE27FB75}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TcpClient-PFM", "TcpClient-PFM\TcpClient-PFM.csproj", "{9A2CEAF1-95CF-4E7D-91D5-42DB1F3FD29A}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Debug|Mixed Platforms = Debug|Mixed Platforms + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|Any CPU = Release|Any CPU + Release|Mixed Platforms = Release|Mixed Platforms + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {DFA935E2-CF37-4E26-B697-D7F3DEE19DD8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {DFA935E2-CF37-4E26-B697-D7F3DEE19DD8}.Debug|Any CPU.Build.0 = Debug|Any CPU + {DFA935E2-CF37-4E26-B697-D7F3DEE19DD8}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {DFA935E2-CF37-4E26-B697-D7F3DEE19DD8}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {DFA935E2-CF37-4E26-B697-D7F3DEE19DD8}.Debug|x64.ActiveCfg = Debug|x64 + {DFA935E2-CF37-4E26-B697-D7F3DEE19DD8}.Debug|x64.Build.0 = Debug|x64 + {DFA935E2-CF37-4E26-B697-D7F3DEE19DD8}.Debug|x86.ActiveCfg = Debug|Any CPU + {DFA935E2-CF37-4E26-B697-D7F3DEE19DD8}.Debug|x86.Build.0 = Debug|Any CPU + {DFA935E2-CF37-4E26-B697-D7F3DEE19DD8}.Release|Any CPU.ActiveCfg = Release|Any CPU + {DFA935E2-CF37-4E26-B697-D7F3DEE19DD8}.Release|Any CPU.Build.0 = Release|Any CPU + {DFA935E2-CF37-4E26-B697-D7F3DEE19DD8}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {DFA935E2-CF37-4E26-B697-D7F3DEE19DD8}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {DFA935E2-CF37-4E26-B697-D7F3DEE19DD8}.Release|x64.ActiveCfg = Release|x64 + {DFA935E2-CF37-4E26-B697-D7F3DEE19DD8}.Release|x64.Build.0 = Release|x64 + {DFA935E2-CF37-4E26-B697-D7F3DEE19DD8}.Release|x86.ActiveCfg = Release|Any CPU + {DFA935E2-CF37-4E26-B697-D7F3DEE19DD8}.Release|x86.Build.0 = Release|Any CPU + {B9965E66-853A-47CC-B0C9-197B5A29ABFC}.Debug|Any CPU.ActiveCfg = Debug|x86 + {B9965E66-853A-47CC-B0C9-197B5A29ABFC}.Debug|Mixed Platforms.ActiveCfg = Debug|x86 + {B9965E66-853A-47CC-B0C9-197B5A29ABFC}.Debug|Mixed Platforms.Build.0 = Debug|x86 + {B9965E66-853A-47CC-B0C9-197B5A29ABFC}.Debug|x64.ActiveCfg = Debug|x64 + {B9965E66-853A-47CC-B0C9-197B5A29ABFC}.Debug|x64.Build.0 = Debug|x64 + {B9965E66-853A-47CC-B0C9-197B5A29ABFC}.Debug|x86.ActiveCfg = Debug|x86 + {B9965E66-853A-47CC-B0C9-197B5A29ABFC}.Debug|x86.Build.0 = Debug|x86 + {B9965E66-853A-47CC-B0C9-197B5A29ABFC}.Release|Any CPU.ActiveCfg = Release|x86 + {B9965E66-853A-47CC-B0C9-197B5A29ABFC}.Release|Mixed Platforms.ActiveCfg = Release|x86 + {B9965E66-853A-47CC-B0C9-197B5A29ABFC}.Release|Mixed Platforms.Build.0 = Release|x86 + {B9965E66-853A-47CC-B0C9-197B5A29ABFC}.Release|x64.ActiveCfg = Release|x64 + {B9965E66-853A-47CC-B0C9-197B5A29ABFC}.Release|x64.Build.0 = Release|x64 + {B9965E66-853A-47CC-B0C9-197B5A29ABFC}.Release|x86.ActiveCfg = Release|x86 + {B9965E66-853A-47CC-B0C9-197B5A29ABFC}.Release|x86.Build.0 = Release|x86 + {B6654857-4C82-4F92-AD7A-21FD3ED5BBFA}.Debug|Any CPU.ActiveCfg = Debug|x86 + {B6654857-4C82-4F92-AD7A-21FD3ED5BBFA}.Debug|Mixed Platforms.ActiveCfg = Debug|x86 + {B6654857-4C82-4F92-AD7A-21FD3ED5BBFA}.Debug|Mixed Platforms.Build.0 = Debug|x86 + {B6654857-4C82-4F92-AD7A-21FD3ED5BBFA}.Debug|x64.ActiveCfg = Debug|x64 + {B6654857-4C82-4F92-AD7A-21FD3ED5BBFA}.Debug|x64.Build.0 = Debug|x64 + {B6654857-4C82-4F92-AD7A-21FD3ED5BBFA}.Debug|x86.ActiveCfg = Debug|x86 + {B6654857-4C82-4F92-AD7A-21FD3ED5BBFA}.Debug|x86.Build.0 = Debug|x86 + {B6654857-4C82-4F92-AD7A-21FD3ED5BBFA}.Release|Any CPU.ActiveCfg = Release|x86 + {B6654857-4C82-4F92-AD7A-21FD3ED5BBFA}.Release|Mixed Platforms.ActiveCfg = Release|x86 + {B6654857-4C82-4F92-AD7A-21FD3ED5BBFA}.Release|Mixed Platforms.Build.0 = Release|x86 + {B6654857-4C82-4F92-AD7A-21FD3ED5BBFA}.Release|x64.ActiveCfg = Release|x64 + {B6654857-4C82-4F92-AD7A-21FD3ED5BBFA}.Release|x64.Build.0 = Release|x64 + {B6654857-4C82-4F92-AD7A-21FD3ED5BBFA}.Release|x86.ActiveCfg = Release|x86 + {B6654857-4C82-4F92-AD7A-21FD3ED5BBFA}.Release|x86.Build.0 = Release|x86 + {B6E43918-236A-4EA7-84C8-ED4A98049907}.Debug|Any CPU.ActiveCfg = Debug|x86 + {B6E43918-236A-4EA7-84C8-ED4A98049907}.Debug|Mixed Platforms.ActiveCfg = Debug|x86 + {B6E43918-236A-4EA7-84C8-ED4A98049907}.Debug|Mixed Platforms.Build.0 = Debug|x86 + {B6E43918-236A-4EA7-84C8-ED4A98049907}.Debug|x64.ActiveCfg = Debug|x64 + {B6E43918-236A-4EA7-84C8-ED4A98049907}.Debug|x64.Build.0 = Debug|x64 + {B6E43918-236A-4EA7-84C8-ED4A98049907}.Debug|x86.ActiveCfg = Debug|x86 + {B6E43918-236A-4EA7-84C8-ED4A98049907}.Debug|x86.Build.0 = Debug|x86 + {B6E43918-236A-4EA7-84C8-ED4A98049907}.Release|Any CPU.ActiveCfg = Release|x86 + {B6E43918-236A-4EA7-84C8-ED4A98049907}.Release|Mixed Platforms.ActiveCfg = Release|x86 + {B6E43918-236A-4EA7-84C8-ED4A98049907}.Release|Mixed Platforms.Build.0 = Release|x86 + {B6E43918-236A-4EA7-84C8-ED4A98049907}.Release|x64.ActiveCfg = Release|x64 + {B6E43918-236A-4EA7-84C8-ED4A98049907}.Release|x64.Build.0 = Release|x64 + {B6E43918-236A-4EA7-84C8-ED4A98049907}.Release|x86.ActiveCfg = Release|x86 + {B6E43918-236A-4EA7-84C8-ED4A98049907}.Release|x86.Build.0 = Release|x86 + {9A3339BC-37F0-4D03-9ACE-51CC4CF75277}.Debug|Any CPU.ActiveCfg = Debug|x86 + {9A3339BC-37F0-4D03-9ACE-51CC4CF75277}.Debug|Mixed Platforms.ActiveCfg = Debug|x86 + {9A3339BC-37F0-4D03-9ACE-51CC4CF75277}.Debug|Mixed Platforms.Build.0 = Debug|x86 + {9A3339BC-37F0-4D03-9ACE-51CC4CF75277}.Debug|x64.ActiveCfg = Debug|x64 + {9A3339BC-37F0-4D03-9ACE-51CC4CF75277}.Debug|x64.Build.0 = Debug|x64 + {9A3339BC-37F0-4D03-9ACE-51CC4CF75277}.Debug|x86.ActiveCfg = Debug|x86 + {9A3339BC-37F0-4D03-9ACE-51CC4CF75277}.Debug|x86.Build.0 = Debug|x86 + {9A3339BC-37F0-4D03-9ACE-51CC4CF75277}.Release|Any CPU.ActiveCfg = Release|x86 + {9A3339BC-37F0-4D03-9ACE-51CC4CF75277}.Release|Mixed Platforms.ActiveCfg = Release|x86 + {9A3339BC-37F0-4D03-9ACE-51CC4CF75277}.Release|Mixed Platforms.Build.0 = Release|x86 + {9A3339BC-37F0-4D03-9ACE-51CC4CF75277}.Release|x64.ActiveCfg = Release|x64 + {9A3339BC-37F0-4D03-9ACE-51CC4CF75277}.Release|x64.Build.0 = Release|x64 + {9A3339BC-37F0-4D03-9ACE-51CC4CF75277}.Release|x86.ActiveCfg = Release|x86 + {9A3339BC-37F0-4D03-9ACE-51CC4CF75277}.Release|x86.Build.0 = Release|x86 + {5FEB9E6D-2526-4F4F-957C-093D7FFB9B98}.Debug|Any CPU.ActiveCfg = Debug|x86 + {5FEB9E6D-2526-4F4F-957C-093D7FFB9B98}.Debug|Mixed Platforms.ActiveCfg = Debug|x86 + {5FEB9E6D-2526-4F4F-957C-093D7FFB9B98}.Debug|Mixed Platforms.Build.0 = Debug|x86 + {5FEB9E6D-2526-4F4F-957C-093D7FFB9B98}.Debug|x64.ActiveCfg = Debug|x64 + {5FEB9E6D-2526-4F4F-957C-093D7FFB9B98}.Debug|x64.Build.0 = Debug|x64 + {5FEB9E6D-2526-4F4F-957C-093D7FFB9B98}.Debug|x86.ActiveCfg = Debug|x86 + {5FEB9E6D-2526-4F4F-957C-093D7FFB9B98}.Debug|x86.Build.0 = Debug|x86 + {5FEB9E6D-2526-4F4F-957C-093D7FFB9B98}.Release|Any CPU.ActiveCfg = Release|x86 + {5FEB9E6D-2526-4F4F-957C-093D7FFB9B98}.Release|Mixed Platforms.ActiveCfg = Release|x86 + {5FEB9E6D-2526-4F4F-957C-093D7FFB9B98}.Release|Mixed Platforms.Build.0 = Release|x86 + {5FEB9E6D-2526-4F4F-957C-093D7FFB9B98}.Release|x64.ActiveCfg = Release|x64 + {5FEB9E6D-2526-4F4F-957C-093D7FFB9B98}.Release|x64.Build.0 = Release|x64 + {5FEB9E6D-2526-4F4F-957C-093D7FFB9B98}.Release|x86.ActiveCfg = Release|x86 + {5FEB9E6D-2526-4F4F-957C-093D7FFB9B98}.Release|x86.Build.0 = Release|x86 + {10426A79-A3B3-4CD2-BD84-02AAEE27FB75}.Debug|Any CPU.ActiveCfg = Debug|x86 + {10426A79-A3B3-4CD2-BD84-02AAEE27FB75}.Debug|Mixed Platforms.ActiveCfg = Debug|x86 + {10426A79-A3B3-4CD2-BD84-02AAEE27FB75}.Debug|Mixed Platforms.Build.0 = Debug|x86 + {10426A79-A3B3-4CD2-BD84-02AAEE27FB75}.Debug|x64.ActiveCfg = Debug|x64 + {10426A79-A3B3-4CD2-BD84-02AAEE27FB75}.Debug|x64.Build.0 = Debug|x64 + {10426A79-A3B3-4CD2-BD84-02AAEE27FB75}.Debug|x86.ActiveCfg = Debug|x86 + {10426A79-A3B3-4CD2-BD84-02AAEE27FB75}.Debug|x86.Build.0 = Debug|x86 + {10426A79-A3B3-4CD2-BD84-02AAEE27FB75}.Release|Any CPU.ActiveCfg = Release|x86 + {10426A79-A3B3-4CD2-BD84-02AAEE27FB75}.Release|Mixed Platforms.ActiveCfg = Release|x86 + {10426A79-A3B3-4CD2-BD84-02AAEE27FB75}.Release|Mixed Platforms.Build.0 = Release|x86 + {10426A79-A3B3-4CD2-BD84-02AAEE27FB75}.Release|x64.ActiveCfg = Release|x64 + {10426A79-A3B3-4CD2-BD84-02AAEE27FB75}.Release|x64.Build.0 = Release|x64 + {10426A79-A3B3-4CD2-BD84-02AAEE27FB75}.Release|x86.ActiveCfg = Release|x86 + {10426A79-A3B3-4CD2-BD84-02AAEE27FB75}.Release|x86.Build.0 = Release|x86 + {9A2CEAF1-95CF-4E7D-91D5-42DB1F3FD29A}.Debug|Any CPU.ActiveCfg = Debug|x86 + {9A2CEAF1-95CF-4E7D-91D5-42DB1F3FD29A}.Debug|Mixed Platforms.ActiveCfg = Debug|x86 + {9A2CEAF1-95CF-4E7D-91D5-42DB1F3FD29A}.Debug|Mixed Platforms.Build.0 = Debug|x86 + {9A2CEAF1-95CF-4E7D-91D5-42DB1F3FD29A}.Debug|x64.ActiveCfg = Debug|x64 + {9A2CEAF1-95CF-4E7D-91D5-42DB1F3FD29A}.Debug|x64.Build.0 = Debug|x64 + {9A2CEAF1-95CF-4E7D-91D5-42DB1F3FD29A}.Debug|x86.ActiveCfg = Debug|x86 + {9A2CEAF1-95CF-4E7D-91D5-42DB1F3FD29A}.Debug|x86.Build.0 = Debug|x86 + {9A2CEAF1-95CF-4E7D-91D5-42DB1F3FD29A}.Release|Any CPU.ActiveCfg = Release|x86 + {9A2CEAF1-95CF-4E7D-91D5-42DB1F3FD29A}.Release|Mixed Platforms.ActiveCfg = Release|x86 + {9A2CEAF1-95CF-4E7D-91D5-42DB1F3FD29A}.Release|Mixed Platforms.Build.0 = Release|x86 + {9A2CEAF1-95CF-4E7D-91D5-42DB1F3FD29A}.Release|x64.ActiveCfg = Release|x64 + {9A2CEAF1-95CF-4E7D-91D5-42DB1F3FD29A}.Release|x64.Build.0 = Release|x64 + {9A2CEAF1-95CF-4E7D-91D5-42DB1F3FD29A}.Release|x86.ActiveCfg = Release|x86 + {9A2CEAF1-95CF-4E7D-91D5-42DB1F3FD29A}.Release|x86.Build.0 = Release|x86 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/HPSocketCS/HPSocketCS.csproj b/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/HPSocketCS/HPSocketCS.csproj new file mode 100644 index 000000000..a7a39db25 --- /dev/null +++ b/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/HPSocketCS/HPSocketCS.csproj @@ -0,0 +1,89 @@ + + + + Debug + AnyCPU + 8.0.30703 + 2.0 + {DFA935E2-CF37-4E26-B697-D7F3DEE19DD8} + Library + Properties + HPSocketCS + HPSocketCS + v4.0 + 512 + + + true + full + false + ..\bin\x86\Debug\ + DEBUG;TRACE + prompt + 4 + true + + + pdbonly + true + ..\bin\x86\Release\ + TRACE + prompt + 4 + + + true + ..\bin\x64\Debug\ + DEBUG;TRACE + full + x64 + ..\bin\Debug\HPSocketCS.dll.CodeAnalysisLog.xml + true + GlobalSuppressions.cs + prompt + MinimumRecommendedRules.ruleset + ;D:\Program Files\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets + ;D:\Program Files\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules + + + ..\bin\x64\Release\ + TRACE + true + pdbonly + x64 + ..\bin\Release\HPSocketCS.dll.CodeAnalysisLog.xml + true + GlobalSuppressions.cs + prompt + MinimumRecommendedRules.ruleset + ;D:\Program Files\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets + ;D:\Program Files\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/HPSocketCS/Properties/AssemblyInfo.cs b/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/HPSocketCS/Properties/AssemblyInfo.cs new file mode 100644 index 000000000..0bf375ed6 --- /dev/null +++ b/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/HPSocketCS/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// 有关程序集的常规信息通过以下 +// 特性集控制。更改这些特性值可修改 +// 与程序集关联的信息。 +[assembly: AssemblyTitle("HPSocketCS")] +[assembly: AssemblyDescription("HP-Socket for C#")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("JessMA Open Source")] +[assembly: AssemblyProduct("HPSocketCS")] +[assembly: AssemblyCopyright("Copyright © 2014")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// 将 ComVisible 设置为 false 使此程序集中的类型 +// 对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型, +// 则将该类型上的 ComVisible 特性设置为 true。 +[assembly: ComVisible(false)] + +// 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID +[assembly: Guid("f54bd34d-cd0c-40dc-8c50-73c3ead0a894")] + +// 程序集的版本信息由下面四个值组成: +// +// 主版本 +// 次版本 +// 内部版本号 +// 修订号 +// +// 可以指定所有这些值,也可以使用“内部版本号”和“修订号”的默认值, +// 方法是按如下所示使用“*”: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("3.2.2")] +[assembly: AssemblyFileVersion("3.2.2")] diff --git a/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/HPSocketCS/Sdk.cs b/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/HPSocketCS/Sdk.cs new file mode 100644 index 000000000..88c80a6c0 --- /dev/null +++ b/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/HPSocketCS/Sdk.cs @@ -0,0 +1,1914 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Runtime.InteropServices; +using HPSocketCS; + + +namespace HPSocketCS +{ + + /// + /// 通信组件服务状态,用程序可以通过通信组件的 GetState() 方法获取组件当前服务状态 + /// + public enum ServiceState + { + Starting = 0, // 正在启动 + Started = 1, // 已经启动 + Stoping = 2, // 正在停止 + Stoped = 3, // 已经启动 + } + + /// + /// Socket 操作类型,应用程序的 OnErrror() 事件中通过该参数标识是哪种操作导致的错误 + /// + public enum SocketOperation + { + Unknown = 0, // Unknown + Acccept = 1, // Acccept + Connnect = 2, // Connnect + Send = 3, // Send + Receive = 4, // Receive + }; + + /// + /// 事件通知处理结果,事件通知的返回值,不同的返回值会影响通信组件的后续行为 + /// + public enum HandleResult + { + Ok = 0, // 成功 + Ignore = 1, // 忽略 + Error = 2, // 错误 + }; + + + /// + /// 名称:操作结果代码 + /// 描述:组件 Start() / Stop() 方法执行失败时,可通过 GetLastError() 获取错误代码 + /// + public enum SocketError + { + Ok = 0, // 成功 + IllegalState = 1, // 当前状态不允许操作 + InvalidParam = 2, // 非法参数 + SocketCreate = 3, // 创建 SOCKET 失败 + SocketBind = 4, // 绑定 SOCKET 失败 + SocketPrepare = 5, // 设置 SOCKET 失败 + SocketListen = 6, // 监听 SOCKET 失败 + CPCreate = 7, // 创建完成端口失败 + WorkerThreadCreate = 8, // 创建工作线程失败 + DetectThreadCreate = 9, // 创建监测线程失败 + SocketAttachToCP = 10, // 绑定完成端口失败 + ConnectServer = 11, // 连接服务器失败 + Network = 12, // 网络错误 + DataProc = 13, // 数据处理错误 + DataSend = 14, // 数据发送失败 + }; + + /// + /// 数据抓取结果,数据抓取操作的返回值 + /// + public enum FetchResult + { + Ok = 0, // 成功 + LengthTooLong = 1, // 抓取长度过大 + DataNotFound = 2, // 找不到 ConnID 对应的数据 + }; + + /// + /// 发送策略 + /// + public enum SendPolicy + { + Pack = 0, // 打包模式(默认) + Safe = 1, // 安全模式 + Direct = 2, // 直接模式 + }; + + /// + /// 接收策略 + /// + public enum RecvPolicy + { + Serial = 0, // 串行模式(默认) + Parallel = 1, // 并行模式 + }; + + /****************************************************/ + /************** sockaddr结构体,udp服务器时OnAccept最后个参数可转化 **************/ + [StructLayout(LayoutKind.Sequential)] + public struct in_addr + { + public ulong S_addr; + } + + //[StructLayout(LayoutKind.Sequential)] + //public struct in_addr + //{ + // public byte s_b1, s_b2, s_b3, s_b4; + //} + + [StructLayout(LayoutKind.Sequential)] + public struct sockaddr_in + { + public short sin_family; + public ushort sin_port; + public in_addr sin_addr; + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)] + public byte[] sLibNamesin_zero; + } + + /****************************************************/ + + [StructLayout(LayoutKind.Sequential)] + public struct WSABUF + { + public int Length; + public IntPtr Buffer; + } +} + + +namespace HPSocketCS.SDK +{ + /// + /// Unicode版本 + /// + public class HPSocketSdk + { + /// + /// HPSocket的文件路径 + /// + private const string SOCKET_DLL_PATH = "HPSocket4C_U.dll"; + + /*****************************************************************************************************/ + /******************************************** 公共类、接口 ********************************************/ + /*****************************************************************************************************/ + + + + /****************************************************/ + /************** HPSocket4C.dll 回调函数 **************/ + /* 公共回调函数 */ + public delegate HandleResult OnSend(IntPtr dwConnId, IntPtr pData, int iLength); + public delegate HandleResult OnReceive(IntPtr dwConnId, IntPtr pData, int iLength); + public delegate HandleResult OnPullReceive(IntPtr dwConnId, int iLength); + public delegate HandleResult OnClose(IntPtr dwConnId); + public delegate HandleResult OnError(IntPtr dwConnId, SocketOperation enOperation, int iErrorCode); + + /* 服务端回调函数 */ + public delegate HandleResult OnPrepareListen(IntPtr soListen); + + /// + /// OnAccept + /// + /// + /// 如果为 TCP 连接,pClient为 SOCKET 句柄;如果为 UDP 连接,pClient为 sockaddr_in 指针; + /// + public delegate HandleResult OnAccept(IntPtr dwConnId, IntPtr pClient); + public delegate HandleResult OnServerShutdown(); + + /* 客户端和 Agent 回调函数 */ + public delegate HandleResult OnPrepareConnect(IntPtr dwConnId, uint socket); + public delegate HandleResult OnConnect(IntPtr dwConnId); + + /* Agent 回调函数 */ + public delegate HandleResult OnAgentShutdown(); + + /****************************************************/ + /************** HPSocket4C.dll 导出函数 **************/ + + /// + /// 创建 TcpServer 对象 + /// + /// + /// + [DllImport(SOCKET_DLL_PATH)] + public static extern IntPtr Create_HP_TcpServer(IntPtr pListener); + + /// + /// 创建 TcpClient 对象 + /// + /// + /// + [DllImport(SOCKET_DLL_PATH)] + public static extern IntPtr Create_HP_TcpClient(IntPtr pListener); + + /// + /// 创建 TcpAgent 对象 + /// + /// + /// + [DllImport(SOCKET_DLL_PATH)] + public static extern IntPtr Create_HP_TcpAgent(IntPtr pListener); + + /// + /// 创建 TcpPullServer 对象 + /// + /// + /// + [DllImport(SOCKET_DLL_PATH)] + public static extern IntPtr Create_HP_TcpPullServer(IntPtr pListener); + + /// + /// 创建 TcpPullClient 对象 + /// + /// + /// + [DllImport(SOCKET_DLL_PATH)] + public static extern IntPtr Create_HP_TcpPullClient(IntPtr pListener); + + /// + /// 创建 TcpPullAgent 对象 + /// + /// + /// + [DllImport(SOCKET_DLL_PATH)] + public static extern IntPtr Create_HP_TcpPullAgent(IntPtr pListener); + + /// + /// 创建 UdpServer 对象 + /// + /// + /// + [DllImport(SOCKET_DLL_PATH)] + public static extern IntPtr Create_HP_UdpServer(IntPtr pListener); + + /// + /// 创建 UdpClient 对象 + /// + /// + /// + [DllImport(SOCKET_DLL_PATH)] + public static extern IntPtr Create_HP_UdpClient(IntPtr pListener); + + + /// + /// 销毁 TcpServer 对象 + /// + /// + /// + [DllImport(SOCKET_DLL_PATH)] + public static extern void Destroy_HP_TcpServer(IntPtr pServer); + + /// + /// 销毁 TcpClient 对象 + /// + /// + /// + [DllImport(SOCKET_DLL_PATH)] + public static extern void Destroy_HP_TcpClient(IntPtr pClient); + + /// + /// 销毁 TcpAgent 对象 + /// + /// + /// + [DllImport(SOCKET_DLL_PATH)] + public static extern void Destroy_HP_TcpAgent(IntPtr pAgent); + + /// + /// 销毁 TcpPullServer 对象 + /// + /// + /// + [DllImport(SOCKET_DLL_PATH)] + public static extern void Destroy_HP_TcpPullServer(IntPtr pServer); + + /// + /// 销毁 TcpPullClient 对象 + /// + /// + /// + [DllImport(SOCKET_DLL_PATH)] + public static extern void Destroy_HP_TcpPullClient(IntPtr pClient); + + /// + /// 销毁 TcpPullAgent 对象 + /// + /// + /// + [DllImport(SOCKET_DLL_PATH)] + public static extern void Destroy_HP_TcpPullAgent(IntPtr pAgent); + + /// + /// 销毁 UdpServer 对象 + /// + /// + /// + [DllImport(SOCKET_DLL_PATH)] + public static extern void Destroy_HP_UdpServer(IntPtr pServer); + + /// + /// 销毁 UdpClient 对象 + /// + /// + /// + [DllImport(SOCKET_DLL_PATH)] + public static extern void Destroy_HP_UdpClient(IntPtr pClient); + + + /// + /// 创建 TcpServerListener 对象 + /// + /// + [DllImport(SOCKET_DLL_PATH)] + public static extern IntPtr Create_HP_TcpServerListener(); + + /// + /// 创建 TcpClientListener 对象 + /// + /// + [DllImport(SOCKET_DLL_PATH)] + public static extern IntPtr Create_HP_TcpClientListener(); + + /// + /// 创建 TcpAgentListener 对象 + /// + /// + [DllImport(SOCKET_DLL_PATH)] + public static extern IntPtr Create_HP_TcpAgentListener(); + + /// + /// 创建 TcpPullServerListener 对象 + /// + /// + [DllImport(SOCKET_DLL_PATH)] + public static extern IntPtr Create_HP_TcpPullServerListener(); + + /// + /// 创建 TcpPullClientListener 对象 + /// + /// + [DllImport(SOCKET_DLL_PATH)] + public static extern IntPtr Create_HP_TcpPullClientListener(); + + /// + /// 创建 TcpPullAgentListener 对象 + /// + /// + [DllImport(SOCKET_DLL_PATH)] + public static extern IntPtr Create_HP_TcpPullAgentListener(); + + /// + /// 创建 UdpServerListener 对象 + /// + /// + [DllImport(SOCKET_DLL_PATH)] + public static extern IntPtr Create_HP_UdpServerListener(); + + /// + /// 创建 UdpClientListener 对象 + /// + /// + [DllImport(SOCKET_DLL_PATH)] + public static extern IntPtr Create_HP_UdpClientListener(); + + + /// + /// 销毁 TcpServerListener 对象 + /// + /// + /// + [DllImport(SOCKET_DLL_PATH)] + public static extern void Destroy_HP_TcpServerListener(IntPtr pListener); + + /// + /// 销毁 TcpClientListener 对象 + /// + /// + /// + [DllImport(SOCKET_DLL_PATH)] + public static extern void Destroy_HP_TcpClientListener(IntPtr pListener); + + /// + /// 销毁 TcpAgentListener 对象 + /// + /// + /// + [DllImport(SOCKET_DLL_PATH)] + public static extern void Destroy_HP_TcpAgentListener(IntPtr pListener); + + + /// + /// 销毁 TcpPullServerListener 对象 + /// + /// + /// + [DllImport(SOCKET_DLL_PATH)] + public static extern void Destroy_HP_TcpPullServerListener(IntPtr pListener); + + /// + /// 销毁 TcpPullClientListener 对象 + /// + /// + /// + [DllImport(SOCKET_DLL_PATH)] + public static extern void Destroy_HP_TcpPullClientListener(IntPtr pListener); + + /// + /// 销毁 TcpPullAgentListener 对象 + /// + /// + /// + [DllImport(SOCKET_DLL_PATH)] + public static extern void Destroy_HP_TcpPullAgentListener(IntPtr pListener); + + /// + /// 销毁 UdpServerListener 对象 + /// + /// + /// + [DllImport(SOCKET_DLL_PATH)] + public static extern void Destroy_HP_UdpServerListener(IntPtr pListener); + + /// + /// 销毁 UdpClientListener 对象 + /// + /// + /// + [DllImport(SOCKET_DLL_PATH)] + public static extern void Destroy_HP_UdpClientListener(IntPtr pListener); + + + /**********************************************************************************/ + /***************************** Server 回调函数设置方法 *****************************/ + + [DllImport(SOCKET_DLL_PATH)] + public static extern void HP_Set_FN_Server_OnPrepareListen(IntPtr pListener, OnPrepareListen fn); + [DllImport(SOCKET_DLL_PATH)] + public static extern void HP_Set_FN_Server_OnAccept(IntPtr pListener, OnAccept fn); + [DllImport(SOCKET_DLL_PATH)] + public static extern void HP_Set_FN_Server_OnSend(IntPtr pListener, OnSend fn); + [DllImport(SOCKET_DLL_PATH)] + public static extern void HP_Set_FN_Server_OnReceive(IntPtr pListener, OnReceive fn); + [DllImport(SOCKET_DLL_PATH)] + public static extern void HP_Set_FN_Server_OnPullReceive(IntPtr pListener, OnPullReceive fn); + [DllImport(SOCKET_DLL_PATH)] + public static extern void HP_Set_FN_Server_OnClose(IntPtr pListener, OnClose fn); + [DllImport(SOCKET_DLL_PATH)] + public static extern void HP_Set_FN_Server_OnError(IntPtr pListener, OnError fn); + [DllImport(SOCKET_DLL_PATH)] + public static extern void HP_Set_FN_Server_OnServerShutdown(IntPtr pListener, OnServerShutdown fn); + + /**********************************************************************************/ + /***************************** Client 回调函数设置方法 *****************************/ + + [DllImport(SOCKET_DLL_PATH)] + public static extern void HP_Set_FN_Client_OnPrepareConnect(IntPtr pListener, OnPrepareConnect fn); + [DllImport(SOCKET_DLL_PATH)] + public static extern void HP_Set_FN_Client_OnConnect(IntPtr pListener, OnConnect fn); + [DllImport(SOCKET_DLL_PATH)] + public static extern void HP_Set_FN_Client_OnSend(IntPtr pListener, OnSend fn); + [DllImport(SOCKET_DLL_PATH)] + public static extern void HP_Set_FN_Client_OnReceive(IntPtr pListener, OnReceive fn); + [DllImport(SOCKET_DLL_PATH)] + public static extern void HP_Set_FN_Client_OnPullReceive(IntPtr pListener, OnPullReceive fn); + [DllImport(SOCKET_DLL_PATH)] + public static extern void HP_Set_FN_Client_OnClose(IntPtr pListener, OnClose fn); + [DllImport(SOCKET_DLL_PATH)] + public static extern void HP_Set_FN_Client_OnError(IntPtr pListener, OnError fn); + + /**********************************************************************************/ + /****************************** Agent 回调函数设置方法 *****************************/ + + [DllImport(SOCKET_DLL_PATH)] + public static extern void HP_Set_FN_Agent_OnPrepareConnect(IntPtr pListener, OnPrepareConnect fn); + [DllImport(SOCKET_DLL_PATH)] + public static extern void HP_Set_FN_Agent_OnConnect(IntPtr pListener, OnConnect fn); + [DllImport(SOCKET_DLL_PATH)] + public static extern void HP_Set_FN_Agent_OnSend(IntPtr pListener, OnSend fn); + [DllImport(SOCKET_DLL_PATH)] + public static extern void HP_Set_FN_Agent_OnReceive(IntPtr pListener, OnReceive fn); + [DllImport(SOCKET_DLL_PATH)] + public static extern void HP_Set_FN_Agent_OnPullReceive(IntPtr pListener, OnPullReceive fn); + [DllImport(SOCKET_DLL_PATH)] + public static extern void HP_Set_FN_Agent_OnClose(IntPtr pListener, OnClose fn); + [DllImport(SOCKET_DLL_PATH)] + public static extern void HP_Set_FN_Agent_OnError(IntPtr pListener, OnError fn); + [DllImport(SOCKET_DLL_PATH)] + public static extern void HP_Set_FN_Agent_OnAgentShutdown(IntPtr pListener, OnAgentShutdown fn); + + /**************************************************************************/ + /***************************** Server 操作方法 *****************************/ + + /// + /// 名称:启动通信组件 + /// 描述:启动服务端通信组件,启动完成后可开始接收客户端连接并收发数据 + /// + /// + /// 监听地址 + /// 监听端口 + /// 失败,可通过 GetLastError() 获取错误代码 + [DllImport(SOCKET_DLL_PATH, CharSet = CharSet.Unicode)] + public static extern bool HP_Server_Start(IntPtr pServer, String pszBindAddress, ushort usPort); + + /// + /// 关闭服务端通信组件,关闭完成后断开所有客户端连接并释放所有资源 + /// + /// + /// 失败,可通过 GetLastError() 获取错误代码 + [DllImport(SOCKET_DLL_PATH)] + public static extern bool HP_Server_Stop(IntPtr pServer); + + /// + /// 用户通过该方法向指定客户端发送数据 + /// + /// + /// 连接 ID + /// 发送数据长度 + /// 发送数据长度 + /// + [DllImport(SOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern bool HP_Server_Send(IntPtr pServer, IntPtr dwConnId, byte[] pBuffer, int iLength); + + /// + /// 用户通过该方法向指定客户端发送数据 + /// + /// + /// 连接 ID + /// 发送数据长度 + /// 发送数据长度 + /// + [DllImport(SOCKET_DLL_PATH, SetLastError = true)] + public static extern bool HP_Server_Send(IntPtr pServer, IntPtr dwConnId, IntPtr pBuffer, int iLength); + + /// + /// 用户通过该方法向指定客户端发送数据 + /// + /// + /// + /// + /// + /// 针对pBuffer的偏移 + /// + [DllImport(SOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern bool HP_Server_SendPart(IntPtr pServer, IntPtr dwConnId, byte[] pBuffer, int iLength, int iOffset); + + /// + /// 用户通过该方法向指定客户端发送数据 + /// + /// + /// + /// + /// + /// 针对pBuffer的偏移 + /// + [DllImport(SOCKET_DLL_PATH, SetLastError = true)] + public static extern bool HP_Server_SendPart(IntPtr pServer, IntPtr dwConnId, IntPtr pBuffer, int iLength, int iOffset); + + + /// + /// 发送多组数据 + /// 向指定连接发送多组数据 + /// TCP - 顺序发送所有数据包 + /// UDP - 把所有数据包组合成一个数据包发送(数据包的总长度不能大于设置的 UDP 包最大长度) + /// + /// + /// 连接 ID + /// 发送缓冲区数组 + /// 发送缓冲区数目 + /// TRUE.成功,FALSE.失败,可通过 Windows API 函数 ::GetLastError() 获取 Windows 错误代码 + [DllImport(SOCKET_DLL_PATH, SetLastError = true)] + public static extern bool HP_Server_SendPackets(IntPtr pServer, IntPtr dwConnID, WSABUF[] pBuffers, int iCount); + + + /// + /// 断开与某个客户端的连接 + /// + /// + /// 连接 ID + /// 是否强制断开连接 + /// + [DllImport(SOCKET_DLL_PATH)] + public static extern bool HP_Server_Disconnect(IntPtr pServer, IntPtr dwConnId, bool bForce); + + /// + /// 断开超过指定时长的连接 + /// + /// + /// 时长(毫秒) + /// 是否强制断开连接 + /// + [DllImport(SOCKET_DLL_PATH)] + public static extern bool HP_Server_DisconnectLongConnections(IntPtr pServer, uint dwPeriod, bool bForce); + + /******************************************************************************/ + /***************************** Server 属性访问方法 *****************************/ + + /// + /// 设置数据发送策略 + /// + /// + /// + [DllImport(SOCKET_DLL_PATH)] + public static extern void HP_Server_SetSendPolicy(IntPtr pServer, SendPolicy enSendPolicy); + + /// + /// 获取数据发送策略 + /// + /// + /// + [DllImport(SOCKET_DLL_PATH)] + public static extern SendPolicy HP_Server_GetSendPolicy(IntPtr pServer); + + /// + /// 设置数据接受策略 + /// + /// + /// + [DllImport(SOCKET_DLL_PATH)] + public static extern void HP_Server_SetRecvPolicy(IntPtr pServer, RecvPolicy enSendPolicy); + + /// + /// 获取数据接收策略 + /// + [DllImport(SOCKET_DLL_PATH)] + public static extern RecvPolicy HP_Server_GetRecvPolicy(IntPtr pServer); + + /// + /// 设置连接的附加数据 + /// 是否为连接绑定附加数据或者绑定什么样的数据,均由应用程序只身决定 + /// + /// + /// 连接 ID + /// + /// 若返回 false 失败则为(无效的连接 ID) + [DllImport(SOCKET_DLL_PATH)] + public static extern bool HP_Server_SetConnectionExtra(IntPtr pServer, IntPtr dwConnId, IntPtr pExtra); + + /// + /// 获取连接的附加数据 + /// 是否为连接绑定附加数据或者绑定什么样的数据,均由应用程序只身决定 + /// + /// + /// 连接 ID + /// 数据指针 + /// 若返回 false 失败则为(无效的连接 ID) + [DllImport(SOCKET_DLL_PATH)] + public static extern bool HP_Server_GetConnectionExtra(IntPtr pServer, IntPtr dwConnId, ref IntPtr pExtra); + + /// + /// 检查通信组件是否已启动 + /// + /// + /// + [DllImport(SOCKET_DLL_PATH)] + public static extern bool HP_Server_HasStarted(IntPtr pServer); + + /// + /// 查看通信组件当前状态 + /// + /// + /// + [DllImport(SOCKET_DLL_PATH)] + public static extern ServiceState HP_Server_GetState(IntPtr pServer); + + /// + /// 获取最近一次失败操作的错误代码 + /// + /// + /// + [DllImport(SOCKET_DLL_PATH)] + public static extern SocketError HP_Server_GetLastError(IntPtr pServer); + + /// + /// 获取最近一次失败操作的错误描述 + /// + /// + /// + [DllImport(SOCKET_DLL_PATH)] + public static extern IntPtr HP_Server_GetLastErrorDesc(IntPtr pServer); + + + /// + /// 获取连接中未发出数据的长度 + /// + /// + /// + /// + /// + [DllImport(SOCKET_DLL_PATH)] + public static extern bool HP_Server_GetPendingDataLength(IntPtr pServer, IntPtr dwConnId, ref int piPending); + + /// + /// 获取客户端连接数 + /// + /// + /// + [DllImport(SOCKET_DLL_PATH)] + public static extern uint HP_Server_GetConnectionCount(IntPtr pServer); + + /// + /// 获取所有连接的 CONNID + /// + /// + /// + /// + /// + [DllImport(SOCKET_DLL_PATH)] + public static extern bool HP_Server_GetAllConnectionIDs(IntPtr pServer, IntPtr[] pIDs, ref uint pdwCount); + + /// + /// 获取某个客户端连接时长(毫秒) + /// + /// + /// + /// + /// + [DllImport(SOCKET_DLL_PATH)] + public static extern bool HP_Server_GetConnectPeriod(IntPtr pServer, IntPtr dwConnId, ref uint pdwPeriod); + + /// + /// 获取监听 Socket 的地址信息 + /// + /// + /// + /// + /// + /// + [DllImport(SOCKET_DLL_PATH)] + public static extern bool HP_Server_GetListenAddress(IntPtr pServer, [MarshalAs(UnmanagedType.LPWStr)] StringBuilder lpszAddress, ref int piAddressLen, ref ushort pusPort); + + /// + /// 获取某个客户端连接的地址信息 + /// + /// + /// + /// + /// 传入传出值,大小最好在222.222.222.222的长度以上 + /// + /// + [DllImport(SOCKET_DLL_PATH)] + public static extern bool HP_Server_GetRemoteAddress(IntPtr pServer, IntPtr dwConnId, [MarshalAs(UnmanagedType.LPWStr)] StringBuilder lpszAddress, ref int piAddressLen, ref ushort pusPort); + + + /// + /// 设置 Socket 缓存对象锁定时间(毫秒,在锁定期间该 Socket 缓存对象不能被获取使用) + /// + /// + /// + [DllImport(SOCKET_DLL_PATH)] + public static extern void HP_Server_SetFreeSocketObjLockTime(IntPtr pServer, uint dwFreeSocketObjLockTime); + + /// + /// 设置 Socket 缓存池大小(通常设置为平均并发连接数量的 1/3 - 1/2) + /// + /// + /// + [DllImport(SOCKET_DLL_PATH)] + public static extern void HP_Server_SetFreeSocketObjPool(IntPtr pServer, uint dwFreeSocketObjPool); + + /// + /// 设置内存块缓存池大小(通常设置为 Socket 缓存池大小的 2 - 3 倍) + /// + /// + /// + [DllImport(SOCKET_DLL_PATH)] + public static extern void HP_Server_SetFreeBufferObjPool(IntPtr pServer, uint dwFreeBufferObjPool); + + /// + /// 设置 Socket 缓存池回收阀值(通常设置为 Socket 缓存池大小的 3 倍) + /// + /// + /// + [DllImport(SOCKET_DLL_PATH)] + public static extern void HP_Server_SetFreeSocketObjHold(IntPtr pServer, uint dwFreeSocketObjHold); + + /// + /// 设置内存块缓存池回收阀值(通常设置为内存块缓存池大小的 3 倍) + /// + /// + /// + [DllImport(SOCKET_DLL_PATH)] + public static extern void HP_Server_SetFreeBufferObjHold(IntPtr pServer, uint dwFreeBufferObjHold); + + /// + /// 设置工作线程数量(通常设置为 2 * CPU + 2) + /// + /// + /// + [DllImport(SOCKET_DLL_PATH)] + public static extern void HP_Server_SetWorkerThreadCount(IntPtr pServer, uint dwWorkerThreadCount); + + /// + /// 设置关闭服务前等待连接关闭的最长时限(毫秒,0 则不等待) + /// + /// + /// + [DllImport(SOCKET_DLL_PATH)] + public static extern void HP_Server_SetMaxShutdownWaitTime(IntPtr pServer, uint dwMaxShutdownWaitTime); + + + /// + /// 获取 Socket 缓存对象锁定时间 + /// + /// + /// + [DllImport(SOCKET_DLL_PATH)] + public static extern uint HP_Server_GetFreeSocketObjLockTime(IntPtr pServer); + + /// + /// 获取 Socket 缓存池大小 + /// + /// + /// + [DllImport(SOCKET_DLL_PATH)] + public static extern uint HP_Server_GetFreeSocketObjPool(IntPtr pServer); + + /// + /// 获取内存块缓存池大小 + /// + /// + /// + [DllImport(SOCKET_DLL_PATH)] + public static extern uint HP_Server_GetFreeBufferObjPool(IntPtr pServer); + + /// + /// 获取 Socket 缓存池回收阀值 + /// + /// + /// + [DllImport(SOCKET_DLL_PATH)] + public static extern uint HP_Server_GetFreeSocketObjHold(IntPtr pServer); + + /// + /// 获取内存块缓存池回收阀值 + /// + /// + /// + [DllImport(SOCKET_DLL_PATH)] + public static extern uint HP_Server_GetFreeBufferObjHold(IntPtr pServer); + + /// + /// 获取工作线程数量 + /// + /// + /// + [DllImport(SOCKET_DLL_PATH)] + public static extern uint HP_Server_GetWorkerThreadCount(IntPtr pServer); + + /// + /// 获取关闭服务前等待连接关闭的最长时限 + /// + /// + /// + [DllImport(SOCKET_DLL_PATH)] + public static extern uint HP_Server_GetMaxShutdownWaitTime(IntPtr pServer); + + /**********************************************************************************/ + /***************************** TCP Server 操作方法 *****************************/ + + /// + /// 名称:发送小文件 + /// 描述:向指定连接发送 4096 KB 以下的小文件 + /// + /// + /// 连接 ID + /// 文件路径 + /// 头部附加数据 + /// 尾部附加数据 + /// TRUE.成功 FALSE -- 失败,可通过 Windows API 函数 ::GetLastError() 获取 Windows 错误代码 + [DllImport(SOCKET_DLL_PATH, CharSet = CharSet.Unicode, SetLastError = true)] + public static extern bool HP_TcpServer_SendSmallFile(IntPtr pServer, IntPtr dwConnID, string lpszFileName, ref WSABUF pHead, ref WSABUF pTail); + + /**********************************************************************************/ + /***************************** TCP Server 属性访问方法 *****************************/ + + /// + /// 设置 Accept 预投递数量(根据负载调整设置,Accept 预投递数量越大则支持的并发连接请求越多) + /// + /// + /// + [DllImport(SOCKET_DLL_PATH)] + public static extern void HP_TcpServer_SetAcceptSocketCount(IntPtr pServer, uint dwAcceptSocketCount); + + /// + /// 设置通信数据缓冲区大小(根据平均通信数据包大小调整设置,通常设置为 1024 的倍数) + /// + /// + /// + [DllImport(SOCKET_DLL_PATH)] + public static extern void HP_TcpServer_SetSocketBufferSize(IntPtr pServer, uint dwSocketBufferSize); + + /// + /// 设置监听 Socket 的等候队列大小(根据并发连接数量调整设置) + /// + /// + /// + [DllImport(SOCKET_DLL_PATH)] + public static extern void HP_TcpServer_SetSocketListenQueue(IntPtr pServer, uint dwSocketListenQueue); + + /// + /// 设置心跳包间隔(毫秒,0 则不发送心跳包) + /// + /// + /// + [DllImport(SOCKET_DLL_PATH)] + public static extern void HP_TcpServer_SetKeepAliveTime(IntPtr pServer, uint dwKeepAliveTime); + + /// + /// 设置心跳确认包检测间隔(毫秒,0 不发送心跳包,如果超过若干次 [默认:WinXP 5 次, Win7 10 次] 检测不到心跳确认包则认为已断线) + /// + /// + /// + [DllImport(SOCKET_DLL_PATH)] + public static extern void HP_TcpServer_SetKeepAliveInterval(IntPtr pServer, uint dwKeepAliveInterval); + + + /// + /// 获取 Accept 预投递数量 + /// + /// + /// + [DllImport(SOCKET_DLL_PATH)] + public static extern uint HP_TcpServer_GetAcceptSocketCount(IntPtr pServer); + + /// + /// 获取通信数据缓冲区大小 + /// + /// + /// + [DllImport(SOCKET_DLL_PATH)] + public static extern uint HP_TcpServer_GetSocketBufferSize(IntPtr pServer); + + /// + /// 获取监听 Socket 的等候队列大小 + /// + /// + /// + [DllImport(SOCKET_DLL_PATH)] + public static extern uint HP_TcpServer_GetSocketListenQueue(IntPtr pServer); + + /// + /// 获取心跳检查次数 + /// + /// + /// + [DllImport(SOCKET_DLL_PATH)] + public static extern uint HP_TcpServer_GetKeepAliveTime(IntPtr pServer); + + /// + /// 获取心跳检查间隔 + /// + /// + /// + [DllImport(SOCKET_DLL_PATH)] + public static extern uint HP_TcpServer_GetKeepAliveInterval(IntPtr pServer); + + + /**********************************************************************************/ + /***************************** UDP Server 属性访问方法 *****************************/ + + /// + /// 设置数据报文最大长度(建议在局域网环境下不超过 1472 字节,在广域网环境下不超过 548 字节) + /// + /// + /// + [DllImport(SOCKET_DLL_PATH)] + public static extern void HP_UdpServer_SetMaxDatagramSize(IntPtr pServer, uint dwMaxDatagramSize); + + /// + /// 获取数据报文最大长度 + /// + /// + /// + [DllImport(SOCKET_DLL_PATH)] + public static extern uint HP_UdpServer_GetMaxDatagramSize(IntPtr pServer); + + /// + /// 设置 Receive 预投递数量(根据负载调整设置,Receive 预投递数量越大则丢包概率越小) + /// + /// + /// + [DllImport(SOCKET_DLL_PATH)] + public static extern void HP_UdpServer_SetPostReceiveCount(IntPtr pServer, uint dwPostReceiveCount); + + /// + /// 获取 Receive 预投递数量 + /// + /// + /// + [DllImport(SOCKET_DLL_PATH)] + public static extern uint HP_UdpServer_GetPostReceiveCount(IntPtr pServer); + + /// + /// 设置监测包尝试次数(0 则不发送监测跳包,如果超过最大尝试次数则认为已断线) + /// + /// + /// + [DllImport(SOCKET_DLL_PATH)] + public static extern void HP_UdpServer_SetDetectAttempts(IntPtr pServer, uint dwMaxDatagramSize); + + /// + /// 设置监测包发送间隔(秒,0 不发送监测包) + /// + /// + /// + [DllImport(SOCKET_DLL_PATH)] + public static extern void HP_UdpServer_SetDetectInterval(IntPtr pServer, uint dwMaxDatagramSize); + + /// + /// 获取心跳检查次数 + /// + /// + /// + [DllImport(SOCKET_DLL_PATH)] + public static extern uint HP_UdpServer_GetDetectAttempts(IntPtr pServer); + + /// + /// 获取心跳检查间隔 + /// + /// + /// + [DllImport(SOCKET_DLL_PATH)] + public static extern uint HP_UdpServer_GetDetectInterval(IntPtr pServer); + /******************************************************************************/ + /***************************** Client 组件操作方法 *****************************/ + + /// + /// 启动客户端通信组件并连接服务端,启动完成后可开始收发数据 + /// + /// + /// 服务端地址 + /// 服务端端口 + /// 是否采用异步 Connnect + /// 失败,可通过 GetLastError() 获取错误代码 + [DllImport(SOCKET_DLL_PATH, CharSet = CharSet.Unicode)] + public static extern bool HP_Client_Start(IntPtr pClient, string pszRemoteAddress, ushort usPort, bool bAsyncConnect); + + /// + /// 关闭客户端通信组件,关闭完成后断开与服务端的连接并释放所有资源 + /// + /// + /// 失败,可通过 GetLastError() 获取错误代码 + [DllImport(SOCKET_DLL_PATH)] + public static extern bool HP_Client_Stop(IntPtr pClient); + + /// + /// 用户通过该方法向服务端发送数据 + /// + /// + /// 连接 ID(保留参数,目前该参数并未使用) + /// 发送数据缓冲区 + /// 发送数据长度 + /// 失败,可通过 GetLastError() 获取错误代码 + [DllImport("HPSocket4C_U.dll", CharSet = CharSet.Ansi, SetLastError = true)] + public static extern bool HP_Client_Send(IntPtr pClient, byte[] pBuffer, int iLength); + + /// + /// 用户通过该方法向服务端发送数据 + /// + /// + /// 连接 ID(保留参数,目前该参数并未使用) + /// 发送数据缓冲区 + /// 发送数据长度 + /// 失败,可通过 GetLastError() 获取错误代码 + [DllImport(SOCKET_DLL_PATH, SetLastError = true)] + public static extern bool HP_Client_Send(IntPtr pClient, IntPtr pBuffer, int iLength); + + /// + /// 用户通过该方法向服务端发送数据 + /// + /// + /// + /// + /// 针对pBuffer的偏移 + /// + [DllImport(SOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern bool HP_Client_SendPart(IntPtr pClient, byte[] pBuffer, int iLength, int iOffset); + + /// + /// 用户通过该方法向服务端发送数据 + /// + /// + /// + /// + /// 针对pBuffer的偏移 + /// + [DllImport(SOCKET_DLL_PATH, SetLastError = true)] + public static extern bool HP_Client_SendPart(IntPtr pClient, IntPtr pBuffer, int iLength, int iOffset); + + + /// + /// 发送多组数据 + /// 向服务端发送多组数据 + /// TCP - 顺序发送所有数据包 + /// UDP - 把所有数据包组合成一个数据包发送(数据包的总长度不能大于设置的 UDP 包最大长度) + /// + /// + /// 发送缓冲区数组 + /// 发送缓冲区数目 + /// TRUE.成功,FALSE.失败,可通过 Windows API 函数 ::GetLastError() 获取 Windows 错误代码 + [DllImport(SOCKET_DLL_PATH, SetLastError = true)] + public static extern bool HP_Client_SendPackets(IntPtr pClient, WSABUF[] pBuffers, int iCount); + + + /******************************************************************************/ + /***************************** Client 属性访问方法 *****************************/ + + /// + /// 检查通信组件是否已启动 + /// + /// + /// + [DllImport(SOCKET_DLL_PATH)] + public static extern bool HP_Client_HasStarted(IntPtr pClient); + + /// + /// 查看通信组件当前状态 + /// + /// + /// + [DllImport(SOCKET_DLL_PATH)] + public static extern ServiceState HP_Client_GetState(IntPtr pClient); + + /// + /// 获取最近一次失败操作的错误代码 + /// + /// + /// + [DllImport(SOCKET_DLL_PATH)] + public static extern SocketError HP_Client_GetLastError(IntPtr pClient); + + /// + /// 获取最近一次失败操作的错误描述 + /// + /// + /// + [DllImport(SOCKET_DLL_PATH)] + public static extern IntPtr HP_Client_GetLastErrorDesc(IntPtr pClient); + + /// + /// 获取该组件对象的连接 ID + /// + /// + /// + [DllImport(SOCKET_DLL_PATH)] + public static extern IntPtr HP_Client_GetConnectionID(IntPtr pClient); + + /// + /// 获取 Client Socket 的地址信息 + /// + /// + /// + /// + /// + /// + [DllImport(SOCKET_DLL_PATH)] + public static extern bool HP_Client_GetLocalAddress(IntPtr pClient, [MarshalAs(UnmanagedType.LPWStr)] StringBuilder lpszAddress, ref int piAddressLen, ref ushort pusPort); + + /// + /// 获取连接中未发出数据的长度 + /// + /// + /// + /// + [DllImport(SOCKET_DLL_PATH)] + public static extern bool HP_Client_GetPendingDataLength(IntPtr pClient, ref int piPending); + + /// + /// 设置内存块缓存池大小(通常设置为 -> PUSH 模型:5 - 10;PULL 模型:10 - 20 ) + /// + /// + /// + [DllImport(SOCKET_DLL_PATH)] + public static extern void HP_Client_SetFreeBufferPoolSize(IntPtr pClient, uint dwFreeBufferPoolSize); + + /// + /// 设置内存块缓存池回收阀值(通常设置为内存块缓存池大小的 3 倍) + /// + /// + /// + [DllImport(SOCKET_DLL_PATH)] + public static extern void HP_Client_SetFreeBufferPoolHold(IntPtr pClient, uint dwFreeBufferPoolHold); + + /// + /// 获取内存块缓存池大小 + /// + /// + [DllImport(SOCKET_DLL_PATH)] + public static extern uint HP_Client_GetFreeBufferPoolSize(IntPtr pClient); + + /// + /// 获取内存块缓存池回收阀值 + /// + /// + [DllImport(SOCKET_DLL_PATH)] + public static extern uint HP_Client_GetFreeBufferPoolHold(IntPtr pClient); + /**********************************************************************************/ + /***************************** TCP Client 操作方法 *****************************/ + + /// + /// 名称:发送小文件 + /// 描述:向指定连接发送 4096 KB 以下的小文件 + /// + /// + /// 文件路径 + /// 头部附加数据 + /// 尾部附加数据 + /// TRUE.成功 FALSE -- 失败,可通过 Windows API 函数 ::GetLastError() 获取 Windows 错误代码 + [DllImport(SOCKET_DLL_PATH, CharSet = CharSet.Unicode, SetLastError = true)] + public static extern bool HP_TcpClient_SendSmallFile(IntPtr pClient, string lpszFileName, ref WSABUF pHead, ref WSABUF pTail); + + /**********************************************************************************/ + /***************************** TCP Client 属性访问方法 *****************************/ + + /// + /// 设置通信数据缓冲区大小(根据平均通信数据包大小调整设置,通常设置为:(N * 1024) - sizeof(TBufferObj)) + /// + /// + /// + [DllImport(SOCKET_DLL_PATH)] + public static extern void HP_TcpClient_SetSocketBufferSize(IntPtr pClient, uint dwSocketBufferSize); + + /// + /// 设置心跳包间隔(毫秒,0 则不发送心跳包) + /// + /// + /// + [DllImport(SOCKET_DLL_PATH)] + public static extern void HP_TcpClient_SetKeepAliveTime(IntPtr pClient, uint dwKeepAliveTime); + + /// + /// 设置心跳确认包检测间隔(毫秒,0 不发送心跳包,如果超过若干次 [默认:WinXP 5 次, Win7 10 次] 检测不到心跳确认包则认为已断线) + /// + /// + /// + [DllImport(SOCKET_DLL_PATH)] + public static extern void HP_TcpClient_SetKeepAliveInterval(IntPtr pClient, uint dwKeepAliveInterval); + + /// + /// 获取通信数据缓冲区大小 + /// + /// + /// + [DllImport(SOCKET_DLL_PATH)] + public static extern uint HP_TcpClient_GetSocketBufferSize(IntPtr pClient); + + /// + /// 获取心跳检查次数 + /// + /// + /// + [DllImport(SOCKET_DLL_PATH)] + public static extern uint HP_TcpClient_GetKeepAliveTime(IntPtr pClient); + + /// + /// 获取心跳检查间隔 + /// + /// + /// + [DllImport(SOCKET_DLL_PATH)] + public static extern uint HP_TcpClient_GetKeepAliveInterval(IntPtr pClient); + + /**********************************************************************************/ + /***************************** UDP Client 属性访问方法 *****************************/ + + /// + /// 设置数据报文最大长度(建议在局域网环境下不超过 1472 字节,在广域网环境下不超过 548 字节) + /// + /// + /// + [DllImport(SOCKET_DLL_PATH)] + public static extern void HP_UdpClient_SetMaxDatagramSize(IntPtr pClient, uint dwMaxDatagramSize); + + /// + /// 获取数据报文最大长度 + /// + /// + /// + [DllImport(SOCKET_DLL_PATH)] + public static extern uint HP_UdpClient_GetMaxDatagramSize(IntPtr pClient); + + /// + /// 设置监测包尝试次数(0 则不发送监测跳包,如果超过最大尝试次数则认为已断线 + /// + /// + /// + [DllImport(SOCKET_DLL_PATH)] + public static extern void HP_UdpClient_SetDetectAttempts(IntPtr pClient, uint dwDetectAttempts); + + /// + /// 设置监测包发送间隔(秒,0 不发送监测包) + /// + /// + /// + [DllImport(SOCKET_DLL_PATH)] + public static extern void HP_UdpClient_SetDetectInterval(IntPtr pClient, uint dwDetectInterval); + + /// + /// 获取心跳检查次数 + /// + /// + /// + [DllImport(SOCKET_DLL_PATH)] + public static extern uint HP_UdpClient_GetDetectAttempts(IntPtr pClient); + + /// + /// 获取心跳检查间隔 + /// + /// + /// + [DllImport(SOCKET_DLL_PATH)] + public static extern uint HP_UdpClient_GetDetectInterval(IntPtr pClient); + + /**************************************************************************/ + /***************************** Agent 操作方法 *****************************/ + + /// + /// 启动通信组件 + /// 启动通信代理组件,启动完成后可开始连接远程服务器 + /// + /// + /// 监听地址 + /// 是否采用异步 Connect + /// 失败,可通过 GetLastError() 获取错误代码 + [DllImport(SOCKET_DLL_PATH, CharSet = CharSet.Unicode)] + public static extern bool HP_Agent_Start(IntPtr pAgent, String pszBindAddress, bool bAsyncConnect); + + /// + /// 关闭通信组件 + /// 关闭通信组件,关闭完成后断开所有连接并释放所有资源 + /// + /// + /// -- 失败,可通过 GetLastError() 获取错误代码 + [DllImport(SOCKET_DLL_PATH)] + public static extern bool HP_Agent_Stop(IntPtr pAgent); + + /// + /// 连接服务器 + /// 连接服务器,连接成功后 IAgentListener 会接收到 OnConnect() 事件 + /// + /// + /// 服务端地址 + /// 服务端端口 + /// 传出连接 ID + /// 失败,可通过 SYS_GetLastError() 获取 Windows 错误代码 + [DllImport(SOCKET_DLL_PATH, CharSet = CharSet.Unicode, SetLastError = true)] + public static extern bool HP_Agent_Connect(IntPtr pAgent, String pszBindAddress, ushort usPort, ref IntPtr pdwConnID); + + /// + /// 发送数据 + /// 用户通过该方法向指定连接发送数据 + /// + /// + /// 连接 ID + /// 发送数据缓冲区 + /// 发送数据长度 + /// + [DllImport(SOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern bool HP_Agent_Send(IntPtr pAgent, IntPtr dwConnId, byte[] pBuffer, int iLength); + + /// + /// 发送数据 + /// 用户通过该方法向指定连接发送数据 + /// + /// + /// 连接 ID + /// 发送数据缓冲区 + /// 发送数据长度 + /// + [DllImport(SOCKET_DLL_PATH, SetLastError = true)] + public static extern bool HP_Agent_Send(IntPtr pAgent, IntPtr dwConnId, IntPtr pBuffer, int iLength); + + /// + /// 发送数据 + /// 用户通过该方法向指定连接发送数据 + /// + /// + /// + /// + /// + /// 针对pBuffer的偏移 + /// + [DllImport(SOCKET_DLL_PATH, SetLastError = true)] + public static extern bool HP_Agent_SendPart(IntPtr pAgent, IntPtr dwConnId, byte[] pBuffer, int iLength, int iOffset); + + /// + /// 发送数据 + /// 用户通过该方法向指定连接发送数据 + /// + /// + /// + /// + /// + /// 针对pBuffer的偏移 + /// + [DllImport(SOCKET_DLL_PATH, SetLastError = true)] + public static extern bool HP_Agent_SendPart(IntPtr pAgent, IntPtr dwConnId, IntPtr pBuffer, int iLength, int iOffset); + + + /// + /// 发送多组数据 + /// 向指定连接发送多组数据 + /// TCP - 顺序发送所有数据包 + /// UDP - 把所有数据包组合成一个数据包发送(数据包的总长度不能大于设置的 UDP 包最大长度) + /// + /// + /// 连接 ID + /// 发送缓冲区数组 + /// 发送缓冲区数目 + /// TRUE.成功,FALSE .失败,可通过 Windows API 函数 ::GetLastError() 获取 Windows 错误代码 + [DllImport(SOCKET_DLL_PATH, SetLastError = true)] + public static extern bool HP_Agent_SendPackets(IntPtr pAgent, IntPtr dwConnID, WSABUF[] pBuffers, int iCount); + + /// + /// 断开某个连接 + /// + /// + /// 连接 ID + /// 是否强制断开连接 + /// + [DllImport(SOCKET_DLL_PATH)] + public static extern bool HP_Agent_Disconnect(IntPtr pAgent, IntPtr dwConnId, bool bForce); + + /// + /// 断开超过指定时长的连接 + /// + /// + /// 时长(毫秒) + /// 是否强制断开连接 + /// + [DllImport(SOCKET_DLL_PATH)] + public static extern bool HP_Agent_DisconnectLongConnections(IntPtr pAgent, uint dwPeriod, bool bForce); + + /******************************************************************************/ + /***************************** Agent 操作方法 *****************************/ + + /// + /// 名称:发送小文件 + /// 描述:向指定连接发送 4096 KB 以下的小文件 + /// + /// + /// 连接 ID + /// 文件路径 + /// 头部附加数据 + /// 尾部附加数据 + /// TRUE.成功 FALSE -- 失败,可通过 Windows API 函数 ::GetLastError() 获取 Windows 错误代码 + [DllImport(SOCKET_DLL_PATH, CharSet = CharSet.Unicode, SetLastError = true)] + public static extern bool HP_TcpAgent_SendSmallFile(IntPtr pAgent, IntPtr dwConnID, string lpszFileName, ref WSABUF pHead, ref WSABUF pTail); + + /******************************************************************************/ + /***************************** Agent 属性访问方法 *****************************/ + + /// + /// 设置数据发送策略 + /// + /// + /// + [DllImport(SOCKET_DLL_PATH)] + public static extern void HP_Agent_SetSendPolicy(IntPtr pAgent, SendPolicy enSendPolicy); + + /// + /// 获取数据发送策略 + /// + /// + /// + [DllImport(SOCKET_DLL_PATH)] + public static extern SendPolicy HP_Agent_GetSendPolicy(IntPtr pAgent); + + /// + /// 获取数据接收策略 + /// + /// + /// + [DllImport(SOCKET_DLL_PATH)] + public static extern RecvPolicy HP_Agent_GetRecvPolicy(IntPtr pAgent); + + /// + /// 设置数据接收策略 + /// + /// + /// + [DllImport(SOCKET_DLL_PATH)] + public static extern void HP_Agent_SetRecvPolicy(IntPtr pAgent, RecvPolicy enRecvPolicy); + + + /// + /// 设置连接的附加数据 + /// 是否为连接绑定附加数据或者绑定什么样的数据,均由应用程序只身决定 + /// + /// + /// 连接 ID + /// 数据 + /// FALSE -- 失败(无效的连接 ID) + [DllImport(SOCKET_DLL_PATH)] + public static extern bool HP_Agent_SetConnectionExtra(IntPtr pAgent, IntPtr dwConnId, IntPtr pExtra); + + /// + /// 获取连接的附加数据 + /// 是否为连接绑定附加数据或者绑定什么样的数据,均由应用程序只身决定 + /// + /// + /// + /// + /// + [DllImport(SOCKET_DLL_PATH)] + public static extern bool HP_Agent_GetConnectionExtra(IntPtr pAgent, IntPtr dwConnId, ref IntPtr pExtra); + + /// + /// 检查通信组件是否已启动 + /// + /// + /// + [DllImport(SOCKET_DLL_PATH)] + public static extern bool HP_Agent_HasStarted(IntPtr pAgent); + + /// + /// 查看通信组件当前状态 + /// + /// + /// + [DllImport(SOCKET_DLL_PATH)] + public static extern ServiceState HP_Agent_GetState(IntPtr pAgent); + + /// + /// 获取连接数 + /// + /// + /// + [DllImport(SOCKET_DLL_PATH)] + public static extern uint HP_Agent_GetConnectionCount(IntPtr pAgent); + + /// + /// 获取所有连接的 CONNID + /// + /// + /// + /// + /// + [DllImport(SOCKET_DLL_PATH)] + public static extern bool HP_Agent_GetAllConnectionIDs(IntPtr pAgent, IntPtr[] pIDs, ref uint pdwCount); + + /// + /// 获取某个连接时长(毫秒) + /// + /// + /// + /// + /// + [DllImport(SOCKET_DLL_PATH)] + public static extern bool HP_Agent_GetConnectPeriod(IntPtr pAgent, IntPtr dwConnId, ref uint pdwPeriod); + + /// + /// 获取监听 Socket 的地址信息 + /// + /// + /// + /// + /// + /// + /// + [DllImport(SOCKET_DLL_PATH)] + public static extern bool HP_Agent_GetLocalAddress(IntPtr pAgent, IntPtr dwConnId, [MarshalAs(UnmanagedType.LPWStr)] StringBuilder lpszAddress, ref int piAddressLen, ref ushort pusPort); + + /// + /// 获取某个连接的地址信息 + /// + /// + /// + /// + /// + /// + /// + [DllImport(SOCKET_DLL_PATH)] + public static extern bool HP_Agent_GetRemoteAddress(IntPtr pAgent, IntPtr dwConnId, [MarshalAs(UnmanagedType.LPWStr)] StringBuilder lpszAddress, ref int piAddressLen, ref ushort pusPort); + + /// + /// 获取最近一次失败操作的错误代码 + /// + /// + /// + [DllImport(SOCKET_DLL_PATH)] + public static extern SocketError HP_Agent_GetLastError(IntPtr pAgent); + + /// + /// 获取最近一次失败操作的错误描述 + /// + /// + /// + [DllImport(SOCKET_DLL_PATH)] + public static extern IntPtr HP_Agent_GetLastErrorDesc(IntPtr pAgent); + + /// + /// 获取连接中未发出数据的长度 + /// + /// + /// + /// + [DllImport(SOCKET_DLL_PATH)] + public static extern bool HP_Agent_GetPendingDataLength(IntPtr pAgent, IntPtr dwConnId, ref int piPending); + + /// + /// 设置 Socket 缓存对象锁定时间(毫秒,在锁定期间该 Socket 缓存对象不能被获取使用) + /// + /// + /// + [DllImport(SOCKET_DLL_PATH)] + public static extern void HP_Agent_SetFreeSocketObjLockTime(IntPtr pAgent, uint dwFreeSocketObjLockTime); + + /// + /// 设置 Socket 缓存池大小(通常设置为平均并发连接数量的 1/3 - 1/2) + /// + /// + /// + [DllImport(SOCKET_DLL_PATH)] + public static extern void HP_Agent_SetFreeSocketObjPool(IntPtr pAgent, uint dwFreeSocketObjPool); + + /// + /// 设置内存块缓存池大小(通常设置为 Socket 缓存池大小的 2 - 3 倍) + /// + /// + /// + [DllImport(SOCKET_DLL_PATH)] + public static extern void HP_Agent_SetFreeBufferObjPool(IntPtr pAgent, uint dwFreeBufferObjPool); + + /// + /// 设置 Socket 缓存池回收阀值(通常设置为 Socket 缓存池大小的 3 倍) + /// + /// + /// + [DllImport(SOCKET_DLL_PATH)] + public static extern void HP_Agent_SetFreeSocketObjHold(IntPtr pAgent, uint dwFreeSocketObjHold); + + /// + /// 设置内存块缓存池回收阀值(通常设置为内存块缓存池大小的 3 倍) + /// + /// + /// + [DllImport(SOCKET_DLL_PATH)] + public static extern void HP_Agent_SetFreeBufferObjHold(IntPtr pAgent, uint dwFreeBufferObjHold); + + /// + /// 设置工作线程数量(通常设置为 2 * CPU + 2) + /// + /// + /// + [DllImport(SOCKET_DLL_PATH)] + public static extern void HP_Agent_SetWorkerThreadCount(IntPtr pAgent, uint dwWorkerThreadCount); + + /// + /// 设置关闭组件前等待连接关闭的最长时限(毫秒,0 则不等待) + /// + /// + /// + [DllImport(SOCKET_DLL_PATH)] + public static extern void HP_Agent_SetMaxShutdownWaitTime(IntPtr pAgent, uint dwMaxShutdownWaitTime); + + /// + /// 获取 Socket 缓存对象锁定时间 + /// + /// + /// + [DllImport(SOCKET_DLL_PATH)] + public static extern uint HP_Agent_GetFreeSocketObjLockTime(IntPtr pAgent); + + /// + /// 获取 Socket 缓存池大小 + /// + /// + /// + [DllImport(SOCKET_DLL_PATH)] + public static extern uint HP_Agent_GetFreeSocketObjPool(IntPtr pAgent); + + /// + /// 获取内存块缓存池大小 + /// + /// + /// + [DllImport(SOCKET_DLL_PATH)] + public static extern uint HP_Agent_GetFreeBufferObjPool(IntPtr pAgent); + + /// + /// 获取 Socket 缓存池回收阀值 + /// + /// + /// + [DllImport(SOCKET_DLL_PATH)] + public static extern uint HP_Agent_GetFreeSocketObjHold(IntPtr pAgent); + + /// + /// 获取内存块缓存池回收阀值 + /// + /// + /// + [DllImport(SOCKET_DLL_PATH)] + public static extern uint HP_Agent_GetFreeBufferObjHold(IntPtr pAgent); + + /// + /// 获取工作线程数量 + /// + /// + /// + [DllImport(SOCKET_DLL_PATH)] + public static extern uint HP_Agent_GetWorkerThreadCount(IntPtr pAgent); + + /// + /// 获取关闭组件前等待连接关闭的最长时限 + /// + /// + /// + [DllImport(SOCKET_DLL_PATH)] + public static extern uint HP_Agent_GetMaxShutdownWaitTime(IntPtr pAgent); + + /**********************************************************************************/ + /***************************** TCP Agent 属性访问方法 *****************************/ + + /// + /// 置是否启用地址重用机制(默认:不启用) + /// + /// + /// + [DllImport(SOCKET_DLL_PATH)] + public static extern void HP_TcpAgent_SetReuseAddress(IntPtr pAgent, bool bReuseAddress); + + /// + /// 检测是否启用地址重用机制 + /// + /// + /// + [DllImport(SOCKET_DLL_PATH)] + public static extern bool HP_TcpAgent_IsReuseAddress(IntPtr pAgent); + + /// + /// 设置通信数据缓冲区大小(根据平均通信数据包大小调整设置,通常设置为 1024 的倍数) + /// + /// + /// + [DllImport(SOCKET_DLL_PATH)] + public static extern void HP_TcpAgent_SetSocketBufferSize(IntPtr pAgent, uint dwSocketBufferSize); + + /// + /// 设置心跳包间隔(毫秒,0 则不发送心跳包) + /// + /// + /// + [DllImport(SOCKET_DLL_PATH)] + public static extern void HP_TcpAgent_SetKeepAliveTime(IntPtr pAgent, uint dwKeepAliveTime); + + /// + /// 设置心跳确认包检测间隔(毫秒,0 不发送心跳包,如果超过若干次 [默认:WinXP 5 次, Win7 10 次] 检测不到心跳确认包则认为已断线) + /// + /// + /// + [DllImport(SOCKET_DLL_PATH)] + public static extern void HP_TcpAgent_SetKeepAliveInterval(IntPtr pAgent, uint dwKeepAliveInterval); + + /// + /// 获取通信数据缓冲区大小 + /// + /// + /// + [DllImport(SOCKET_DLL_PATH)] + public static extern uint HP_TcpAgent_GetSocketBufferSize(IntPtr pAgent); + + /// + /// 获取心跳检查次数 + /// + /// + /// + [DllImport(SOCKET_DLL_PATH)] + public static extern uint HP_TcpAgent_GetKeepAliveTime(IntPtr pAgent); + + /// + /// 获取心跳检查间隔 + /// + /// + /// + [DllImport(SOCKET_DLL_PATH)] + public static extern uint HP_TcpAgent_GetKeepAliveInterval(IntPtr pAgent); + + /***************************************************************************************/ + /***************************** TCP Pull Server 组件操作方法 *****************************/ + + /// + /// 抓取数据 + /// 用户通过该方法从 Socket 组件中抓取数据 + /// + /// + /// 连接 ID + /// 数据抓取缓冲区 + /// 抓取数据长度 + /// + [DllImport(SOCKET_DLL_PATH)] + public static extern FetchResult HP_TcpPullServer_Fetch(IntPtr pServer, IntPtr dwConnId, IntPtr pBuffer, int iLength); + + /***************************************************************************************/ + /***************************** TCP Pull Server 属性访问方法 *****************************/ + + /***************************************************************************************/ + /***************************** TCP Pull Client 组件操作方法 *****************************/ + + /// + /// 抓取数据 + /// 用户通过该方法从 Socket 组件中抓取数据 + /// + /// + /// 连接 ID + /// 数据抓取缓冲区 + /// 抓取数据长度 + /// + [DllImport(SOCKET_DLL_PATH)] + public static extern FetchResult HP_TcpPullClient_Fetch(IntPtr pClient, IntPtr dwConnId, IntPtr pBuffer, int iLength); + + /***************************************************************************************/ + /***************************** TCP Pull Client 属性访问方法 *****************************/ + + /***************************************************************************************/ + /***************************** TCP Pull Agent 组件操作方法 *****************************/ + + /// + /// 抓取数据 + /// 用户通过该方法从 Socket 组件中抓取数据 + /// + /// + /// 连接 ID + /// 数据抓取缓冲区 + /// 抓取数据长度 + /// + [DllImport(SOCKET_DLL_PATH)] + public static extern FetchResult HP_TcpPullAgent_Fetch(IntPtr pAgent, IntPtr dwConnId, IntPtr pBuffer, int iLength); + + /***************************************************************************************/ + /***************************** TCP Pull Agent 属性访问方法 *****************************/ + + /***************************************************************************************/ + /*************************************** 其它方法 ***************************************/ + + /// + /// 获取错误描述文本 + /// + /// + /// + [DllImport(SOCKET_DLL_PATH)] + public static extern IntPtr HP_GetSocketErrorDesc(SocketError enCode); + + /// + /// 调用系统的 ::GetLastError() 方法获取系统错误代码 + /// + /// + public static int SYS_GetLastError() + { + return Marshal.GetLastWin32Error(); + } + + /// + /// 调用系统的 ::WSAGetLastError() 方法获取通信错误代码 + /// + /// + [DllImport(SOCKET_DLL_PATH, SetLastError = true)] + public static extern int SYS_WSAGetLastError(); + + /// + /// 调用系统的 setsockopt() + /// + /// + /// + /// + /// + /// + /// + [DllImport(SOCKET_DLL_PATH, SetLastError = true)] + public static extern int SYS_SetSocketOption(IntPtr sock, int level, int name, IntPtr val, int len); + + /// + /// 调用系统的 getsockopt() + /// + /// + /// + /// + /// + /// + /// + [DllImport(SOCKET_DLL_PATH, SetLastError = true)] + public static extern int SYS_GetSocketOption(IntPtr sock, int level, int name, IntPtr val, ref int len); + + /// + /// 调用系统的 ioctlsocket() + /// + /// + /// + /// + /// + [DllImport(SOCKET_DLL_PATH, SetLastError = true)] + public static extern int SYS_IoctlSocket(IntPtr sock, long cmd, IntPtr arg); + + /// + /// 调用系统的 ::WSAIoctl() + /// + /// + /// + /// + /// + /// + /// + /// + /// + [DllImport(SOCKET_DLL_PATH, SetLastError = true)] + public static extern int SYS_WSAIoctl(IntPtr sock, uint dwIoControlCode, IntPtr lpvInBuffer, uint cbInBuffer, + IntPtr lpvOutBuffer, uint cbOutBuffer, uint lpcbBytesReturned); + + } +} diff --git a/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/HPSocketCS/Sdk.rar b/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/HPSocketCS/Sdk.rar new file mode 100644 index 0000000000000000000000000000000000000000..a4a7d3f6ce1e2c7c866c2bc2a64d475900d3740f GIT binary patch literal 6723 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 + /// 创建socket监听&服务组件 + /// + /// 是否使用tcpAgent类默认回调函数 + /// + protected virtual bool CreateListener() + { + if (IsCreate == true || pListener != IntPtr.Zero || pAgent != IntPtr.Zero) + { + return false; + } + + pListener = HPSocketSdk.Create_HP_TcpAgentListener(); + if (pListener == IntPtr.Zero) + { + return false; + } + + pAgent = HPSocketSdk.Create_HP_TcpAgent(pListener); + if (pAgent == IntPtr.Zero) + { + return false; + } + + IsCreate = true; + + return true; + } + + /// + /// 释放TcpAgent和TcpAgentListener + /// + public virtual void Destroy() + { + Stop(); + + if (pAgent != IntPtr.Zero) + { + HPSocketSdk.Destroy_HP_TcpAgent(pAgent); + pAgent = IntPtr.Zero; + } + if (pListener != IntPtr.Zero) + { + HPSocketSdk.Destroy_HP_TcpAgentListener(pListener); + pListener = IntPtr.Zero; + } + + IsCreate = false; + } + + /// + /// 启动通讯组件 + /// 启动完成后可开始连接远程服务器 + /// + /// + /// 是否异步 + /// + public bool Start(string address, bool async = false) + { + if (string.IsNullOrEmpty(address) == true) + { + throw new Exception("address is null"); + } + + if (IsSetCallback == false) + { + // throw new Exception("请在调用Start方法前先调用SetCallback()方法"); + } + + if (HasStarted() == true) + { + return false; + } + + return HPSocketSdk.HP_Agent_Start(pAgent, address, async); + } + + /// + /// 停止通讯组件 + /// + /// + public bool Stop() + { + if (HasStarted() == false) + { + return false; + } + return HPSocketSdk.HP_Agent_Stop(pAgent); + } + + + /// + /// 连接服务器,连接成功后 IAgentListener 会接收到 OnConnect() 事件 + /// + /// + /// + /// + /// + public bool Connect(string address, ushort port, ref IntPtr connId) + { + return HPSocketSdk.HP_Agent_Connect(pAgent, address, port, ref connId); + } + + /// + /// 发送数据 + /// + /// + /// + /// + /// + public bool Send(IntPtr connId, byte[] bytes, int size) + { + return HPSocketSdk.HP_Agent_Send(pAgent, connId, bytes, size); + } + + + /// + /// 发送数据 + /// + /// + /// + /// + /// + public bool Send(IntPtr connId,T obj) + { + byte[] buffer = StructureToByte(obj); + return Send(connId, buffer, buffer.Length); + } + + /// + /// 序列化对象后发送数据,序列化对象所属类必须标记[Serializable] + /// + /// + /// + /// + /// + public bool SendBySerializable(IntPtr connId, object obj) + { + byte[] buffer = ObjectToBytes(obj); + return Send(connId, buffer, buffer.Length); + } + + /// + /// 发送数据 + /// + /// + /// + /// + /// + public bool Send(IntPtr connId, IntPtr bufferPtr, int size) + { + return HPSocketSdk.HP_Agent_Send(pAgent, connId, bufferPtr, size); + } + + /// + /// 发送数据 + /// + /// + /// + /// 针对bytes的偏移 + /// 发多大 + /// + public bool Send(IntPtr connId, byte[] bytes, int offset, int size) + { + return HPSocketSdk.HP_Agent_SendPart(pAgent, connId, bytes, size, offset); + } + + /// + /// 发送数据 + /// + /// + /// + /// 针对bufferPtr的偏移 + /// 发多大 + /// + public bool Send(IntPtr connId, IntPtr bufferPtr, int offset, int size) + { + return HPSocketSdk.HP_Agent_SendPart(pAgent, connId, bufferPtr, size, offset); + } + + /// + /// 发送多组数据 + /// 向指定连接发送多组数据 + /// TCP - 顺序发送所有数据包 + /// + /// 连接 ID + /// 发送缓冲区数组 + /// 发送缓冲区数目 + /// TRUE.成功,FALSE.失败,可通过 SYSGetLastError() 获取 Windows 错误代码 + public bool SendPackets(IntPtr connId, WSABUF[] pBuffers, int count) + { + return HPSocketSdk.HP_Agent_SendPackets(pAgent, connId, pBuffers, count); + } + + /// + /// 发送多组数据 + /// 向指定连接发送多组数据 + /// TCP - 顺序发送所有数据包 + /// + /// 连接 ID + /// 发送缓冲区数组 + /// 发送缓冲区数目 + /// TRUE.成功,FALSE.失败,可通过 SYSGetLastError() 获取 Windows 错误代码 + public bool SendPackets(IntPtr connId, T[] objects) + { + bool ret = false; + + WSABUF[] buffer = new WSABUF[objects.Length]; + IntPtr[] ptrs = new IntPtr[buffer.Length]; + try + { + + for (int i = 0; i < objects.Length; i++) + { + buffer[i].Length = Marshal.SizeOf(typeof(T)); + + ptrs[i] = Marshal.AllocHGlobal(buffer[i].Length); + Marshal.StructureToPtr(objects[i], ptrs[i], true); + + buffer[i].Buffer = ptrs[i]; + } + ret = SendPackets(connId, buffer, buffer.Length); + } + catch (Exception ex) + { + throw ex; + } + finally + { + for (int i = 0; i < ptrs.Length; i++) + { + if (ptrs[i] != IntPtr.Zero) + { + Marshal.FreeHGlobal(ptrs[i]); + } + } + } + + return ret; + } + + /// + /// 名称:发送小文件 + /// 描述:向指定连接发送 4096 KB 以下的小文件 + /// + /// + /// 文件路径 + /// 头部附加数据 + /// 尾部附加数据 + /// TRUE.成功,FALSE.失败,可通过 SYSGetLastError() 获取 Windows 错误代码 + public bool SendSmallFile(IntPtr connId, string filePath, ref WSABUF head, ref WSABUF tail) + { + return HPSocketSdk.HP_TcpAgent_SendSmallFile(pAgent, connId, filePath, ref head, ref tail); + } + + /// + /// 名称:发送小文件 + /// 描述:向指定连接发送 4096 KB 以下的小文件 + /// + /// + /// 文件路径 + /// 头部附加数据,可以为null + /// 尾部附加数据,可以为null + /// TRUE.成功,FALSE.失败,可通过 SYSGetLastError() 获取 Windows 错误代码 + public bool SendSmallFile(IntPtr connId, string filePath, byte[] head, byte[] tail) + { + IntPtr pHead = IntPtr.Zero; + IntPtr pTail = IntPtr.Zero; + WSABUF wsaHead = new WSABUF() { Length = 0, Buffer = pHead }; + WSABUF wsatail = new WSABUF() { Length = 0, Buffer = pTail }; + if (head != null) + { + wsaHead.Length = head.Length; + wsaHead.Buffer = Marshal.UnsafeAddrOfPinnedArrayElement(head, 0); + } + + if (tail != null) + { + wsaHead.Length = tail.Length; + wsaHead.Buffer = Marshal.UnsafeAddrOfPinnedArrayElement(tail, 0); + } + + return SendSmallFile(connId, filePath, ref wsaHead, ref wsatail); + } + + /// + /// 名称:发送小文件 + /// 描述:向指定连接发送 4096 KB 以下的小文件 + /// + /// + /// 文件路径 + /// 头部附加数据,可以为null + /// 尾部附加数据,可以为null + /// TRUE.成功,FALSE.失败,可通过 SYSGetLastError() 获取 Windows 错误代码 + public bool SendSmallFile(IntPtr connId, string filePath, T1 head, T2 tail) + { + + byte[] headBuffer = null; + if (head != null) + { + headBuffer = StructureToByte(head); + } + + byte[] tailBuffer = null; + if (tail != null) + { + StructureToByte(head); + } + return SendSmallFile(connId, filePath, headBuffer, tailBuffer); + } + + /// + /// 断开某个连接 + /// + /// + /// 强制 + /// + public bool Disconnect(IntPtr connId, bool force = true) + { + return HPSocketSdk.HP_Agent_Disconnect(pAgent, connId, force); + } + + /// + /// 设置连接的附加数据 + /// + /// + /// + /// + public bool SetConnectionExtra(IntPtr connId, object obj) + { + + IntPtr ptr = IntPtr.Zero; + // 释放附加数据 + if (HPSocketSdk.HP_Agent_GetConnectionExtra(pAgent, connId, ref ptr) && ptr != IntPtr.Zero) + { + Marshal.FreeHGlobal(ptr); + ptr = IntPtr.Zero; + } + + if (obj != null) + { + // 设置附加数据 + ptr = Marshal.AllocHGlobal(Marshal.SizeOf(obj)); + Marshal.StructureToPtr(obj, ptr, false); + } + return HPSocketSdk.HP_Agent_SetConnectionExtra(pAgent, connId, ptr); + } + + /// + /// 获取附加数据 + /// 如设置的是个结构体/类对象,可以用 Type objA = (Type)Marshal.PtrToStructure(ptr, typeof(Type)) 获取 + /// 其中Type是结构体/类名,ptr是该方法的传出值,在该方法返回为true的时候可用 + /// + /// + /// + /// + public bool GetConnectionExtra(IntPtr connId, ref IntPtr ptr) + { + return HPSocketSdk.HP_Agent_GetConnectionExtra(pAgent, connId, ref ptr) && ptr != IntPtr.Zero; + } + + /// + /// 获取错误码 + /// + /// + public SocketError GetlastError() + { + return HPSocketSdk.HP_Agent_GetLastError(pAgent); + } + + /// + /// 获取错误信息 + /// + /// + public string GetLastErrorDesc() + { + IntPtr ptr = HPSocketSdk.HP_Agent_GetLastErrorDesc(pAgent); + string desc = Marshal.PtrToStringUni(ptr); + return desc; + } + + /// + /// 获取连接中未发出数据的长度 + /// + /// + /// + /// + public bool GetPendingDataLength(IntPtr connId, ref int length) + { + return HPSocketSdk.HP_Agent_GetPendingDataLength(pAgent, connId, ref length); + } + + // 是否启动 + public bool HasStarted() + { + if (pAgent == IntPtr.Zero) + { + return false; + } + return HPSocketSdk.HP_Agent_HasStarted(pAgent); + } + + /// + /// 获取状态 + /// + /// + public ServiceState GetState() + { + return HPSocketSdk.HP_Agent_GetState(pAgent); + } + + /// + /// 获取连接数 + /// + /// + public uint GetConnectionCount() + { + return HPSocketSdk.HP_Agent_GetConnectionCount(pAgent); + } + + /// + /// 获取所有连接数,未获取到连接数返回null + /// + /// + public IntPtr[] GetAllConnectionIDs() + { + IntPtr[] arr = null; + do + { + uint count = GetConnectionCount(); + if (count == 0) + { + break; + } + arr = new IntPtr[count]; + if (HPSocketSdk.HP_Agent_GetAllConnectionIDs(pAgent, arr, ref count)) + { + if (arr.Length > count) + { + IntPtr[] newArr = new IntPtr[count]; + Array.Copy(arr, newArr, count); + arr = newArr; + } + break; + } + } while (true); + + return arr; + } + + /// + /// 获取监听socket的地址信息 + /// + /// + /// + /// + public bool GetLocalAddress(IntPtr connId, ref string ip, ref ushort port) + { + int ipLength = 40; + + StringBuilder sb = new StringBuilder(ipLength); + + bool ret = HPSocketSdk.HP_Agent_GetLocalAddress(pAgent, connId, sb, ref ipLength, ref port); + if (ret == true) + { + ip = sb.ToString(); + } + return ret; + } + + /// + /// 获取该组件对象的连接Id + /// + /// + public bool GetRemoteAddress(IntPtr connId, ref string ip, ref ushort port) + { + int ipLength = 40; + + StringBuilder sb = new StringBuilder(ipLength); + + bool ret = HPSocketSdk.HP_Agent_GetRemoteAddress(pAgent, connId, sb, ref ipLength, ref port); + if (ret == true) + { + ip = sb.ToString(); + } + return ret; + } + + /////////////////////////////////////////////////////////////////////////////////////// + /// + /// 置是否启用地址重用机制(默认:不启用) + /// + /// + public void TcpAgent_SetReuseAddress(bool reuseAddress) + { + HPSocketSdk.HP_TcpAgent_SetReuseAddress(pAgent, reuseAddress); + } + + /// + /// 检测是否启用地址重用机制 + /// + /// + public bool TcpAgent_IsReuseAddress() + { + return HPSocketSdk.HP_TcpAgent_IsReuseAddress(pAgent); + } + + /// + /// 设置工作线程数量(通常设置为 2 * CPU + 2) + /// + /// + public void SetWorkerThreadCount(uint val) + { + HPSocketSdk.HP_Agent_SetWorkerThreadCount(pAgent, val); + } + + /// + /// 设置通信数据缓冲区大小(根据平均通信数据包大小调整设置,通常设置为 1024 的倍数) + /// + /// + public void SetSocketBufferSize(uint val) + { + HPSocketSdk.HP_TcpAgent_SetSocketBufferSize(pAgent, val); + } + + /// + /// 设置 Socket 缓存对象锁定时间(毫秒,在锁定期间该 Socket 缓存对象不能被获取使用) + /// + /// + public void SetFreeSocketObjLockTime(uint val) + { + HPSocketSdk.HP_Agent_SetFreeSocketObjLockTime(pAgent, val); + } + + /// + /// 设置 Socket 缓存池大小(通常设置为平均并发连接数量的 1/3 - 1/2) + /// + /// + public void SetFreeSocketObjPool(uint val) + { + HPSocketSdk.HP_Agent_SetFreeSocketObjPool(pAgent, val); + } + + /// + /// 设置内存块缓存池大小(通常设置为 Socket 缓存池大小的 2 - 3 倍) + /// + /// + public void SetFreeBufferObjPool(uint val) + { + HPSocketSdk.HP_Agent_SetFreeBufferObjPool(pAgent, val); + } + + /// + /// 设置 Socket 缓存池回收阀值(通常设置为 Socket 缓存池大小的 3 倍) + /// + /// + public void SetFreeSocketObjHold(uint val) + { + HPSocketSdk.HP_Agent_SetFreeSocketObjHold(pAgent, val); + } + + /// + /// 设置内存块缓存池回收阀值(通常设置为内存块缓存池大小的 3 倍) + /// + /// + public void SetFreeBufferObjHold(uint val) + { + HPSocketSdk.HP_Agent_SetFreeBufferObjHold(pAgent, val); + } + + /// + /// 设置心跳包间隔(毫秒,0 则不发送心跳包) + /// + /// + public void SetKeepAliveTime(uint val) + { + HPSocketSdk.HP_TcpAgent_SetKeepAliveTime(pAgent, val); + } + + /// + /// 设置心跳确认包检测间隔(毫秒,0 不发送心跳包,如果超过若干次 [默认:WinXP 5 次, Win7 10 次] 检测不到心跳确认包则认为已断线) + /// + /// + public void SetKeepAliveInterval(uint val) + { + HPSocketSdk.HP_TcpAgent_SetKeepAliveInterval(pAgent, val); + } + + /// + /// 设置关闭服务前等待连接关闭的最长时限(毫秒,0 则不等待) + /// + /// + public void SetMaxShutdownWaitTime(uint val) + { + HPSocketSdk.HP_Agent_SetMaxShutdownWaitTime(pAgent, val); + } + + /// + /// 获取工作线程数量 + /// + /// + public uint GetWorkerThreadCount() + { + return HPSocketSdk.HP_Agent_GetWorkerThreadCount(pAgent); + } + + /// + /// 获取通信数据缓冲区大小 + /// + /// + public uint GetSocketBufferSize() + { + return HPSocketSdk.HP_TcpAgent_GetSocketBufferSize(pAgent); + } + + /// + /// 获取 Socket 缓存对象锁定时间 + /// + /// + public uint GetFreeSocketObjLockTime() + { + return HPSocketSdk.HP_Agent_GetFreeSocketObjLockTime(pAgent); + } + + /// + /// 获取 Socket 缓存池大小 + /// + /// + public uint GetFreeSocketObjPool() + { + return HPSocketSdk.HP_Agent_GetFreeSocketObjPool(pAgent); + } + + /// + /// 获取内存块缓存池大小 + /// + /// + public uint GetFreeBufferObjPool() + { + return HPSocketSdk.HP_Agent_GetFreeBufferObjPool(pAgent); + } + + /// + /// 获取 Socket 缓存池回收阀值 + /// + /// + public uint GetFreeSocketObjHold() + { + return HPSocketSdk.HP_Agent_GetFreeSocketObjHold(pAgent); + } + + /// + /// 获取内存块缓存池回收阀值 + /// + /// + public uint GetFreeBufferObjHold() + { + return HPSocketSdk.HP_Agent_GetFreeBufferObjHold(pAgent); + } + + /// + /// 获取心跳检查次数 + /// + /// + public uint GetKeepAliveTime() + { + return HPSocketSdk.HP_TcpAgent_GetKeepAliveTime(pAgent); + } + + /// + /// 获取心跳检查间隔 + /// + /// + public uint GetKeepAliveInterval() + { + return HPSocketSdk.HP_TcpAgent_GetKeepAliveInterval(pAgent); + } + + /// + /// 获取关闭服务前等待连接关闭的最长时限 + /// + /// + public uint GetMaxShutdownWaitTime() + { + return HPSocketSdk.HP_Agent_GetMaxShutdownWaitTime(pAgent); + } + + /// + /// 根据错误码返回错误信息 + /// + /// + /// + public string GetSocketErrorDesc(SocketError code) + { + IntPtr ptr = HPSocketSdk.HP_GetSocketErrorDesc(code); + string desc = Marshal.PtrToStringUni(ptr); + return desc; + } + + /// + /// 设置数据发送策略 + /// + /// + public void SetSendPolicy(SendPolicy policy) + { + HPSocketSdk.HP_Agent_SetSendPolicy(pAgent, policy); + } + + /// + /// 获取数据发送策略 + /// + /// + /// + public SendPolicy GetSendPolicy() + { + return HPSocketSdk.HP_Agent_GetSendPolicy(pAgent); + } + + /// + /// 设置数据接收策略 + /// + /// + public void SetRecvPolicy(RecvPolicy policy) + { + HPSocketSdk.HP_Agent_SetRecvPolicy(pAgent, policy); + } + + /// + /// 获取数据接收策略 + /// + /// + /// + public RecvPolicy GetRecvPolicy() + { + return HPSocketSdk.HP_Agent_GetRecvPolicy(pAgent); + } + /////////////////////////////////////////////////////////////////////////////////////// + + /// + /// 设置回调函数 + /// + /// + /// + /// + /// + /// + /// + /// + public void SetCallback(HPSocketSdk.OnPrepareConnect prepareConnect, HPSocketSdk.OnConnect connect, + HPSocketSdk.OnSend send, HPSocketSdk.OnReceive recv, HPSocketSdk.OnClose close, + HPSocketSdk.OnError error, HPSocketSdk.OnAgentShutdown agentShutdown) + { + if (IsSetCallback == true) + { + throw new Exception("已经调用过SetCallback()方法,如果您确定没手动调用过该方法,并想要手动设置各回调函数,请在构造该类构造函数中传false值,并再次调用该方法。"); + } + + + // 设置 Socket 监听器回调函数 + OnConnectCallback = new HPSocketSdk.OnConnect(connect); + OnSendCallback = new HPSocketSdk.OnSend(send); + OnPrepareConnectCallback = new HPSocketSdk.OnPrepareConnect(prepareConnect); + OnReceiveCallback = new HPSocketSdk.OnReceive(recv); + OnCloseCallback = new HPSocketSdk.OnClose(close); + OnErrorCallback = new HPSocketSdk.OnError(error); + OnAgentShutdownCallback = new HPSocketSdk.OnAgentShutdown(agentShutdown); + + // 设置 Socket 监听器回调函数 + HPSocketSdk.HP_Set_FN_Agent_OnPrepareConnect(pListener, OnPrepareConnectCallback); + HPSocketSdk.HP_Set_FN_Agent_OnConnect(pListener, OnConnectCallback); + HPSocketSdk.HP_Set_FN_Agent_OnSend(pListener, OnSendCallback); + HPSocketSdk.HP_Set_FN_Agent_OnReceive(pListener, OnReceiveCallback); + HPSocketSdk.HP_Set_FN_Agent_OnClose(pListener, OnCloseCallback); + HPSocketSdk.HP_Set_FN_Agent_OnError(pListener, OnErrorCallback); + HPSocketSdk.HP_Set_FN_Agent_OnAgentShutdown(pListener, OnAgentShutdownCallback); + + IsSetCallback = true; + } + + public virtual void SetOnAgentShutdownCallback(HPSocketSdk.OnAgentShutdown agentShutdown) + { + OnAgentShutdownCallback = new HPSocketSdk.OnAgentShutdown(agentShutdown); + HPSocketSdk.HP_Set_FN_Agent_OnAgentShutdown(pListener, OnAgentShutdownCallback); + } + + public virtual void SetOnErrorCallback(HPSocketSdk.OnError error) + { + OnErrorCallback = new HPSocketSdk.OnError(error); + HPSocketSdk.HP_Set_FN_Server_OnError(pListener, OnErrorCallback); + } + + public virtual void SetOnCloseCallback(HPSocketSdk.OnClose close) + { + OnCloseCallback = new HPSocketSdk.OnClose(close); + HPSocketSdk.HP_Set_FN_Server_OnClose(pListener, OnCloseCallback); + } + + public virtual void SetOnReceiveCallback(HPSocketSdk.OnReceive recv) + { + OnReceiveCallback = new HPSocketSdk.OnReceive(recv); + HPSocketSdk.HP_Set_FN_Server_OnReceive(pListener, OnReceiveCallback); + } + + public virtual void SetOnPrepareConnectCallback(HPSocketSdk.OnPrepareConnect prepareConnect) + { + OnPrepareConnectCallback = new HPSocketSdk.OnPrepareConnect(prepareConnect); + HPSocketSdk.HP_Set_FN_Agent_OnPrepareConnect(pListener, OnPrepareConnectCallback); + } + + public virtual void SetOnConnectCallback(HPSocketSdk.OnConnect connect) + { + OnConnectCallback = new HPSocketSdk.OnConnect(connect); + HPSocketSdk.HP_Set_FN_Agent_OnConnect(pListener, OnConnectCallback); + } + + public virtual void SetOnSendCallback(HPSocketSdk.OnSend send) + { + OnSendCallback = new HPSocketSdk.OnSend(send); + HPSocketSdk.HP_Set_FN_Server_OnSend(pListener, OnSendCallback); + } + + ///////////////////////////////////////////////////////////////////////////////////////// + + /// + /// 准备连接了 + /// + /// + /// + /// + protected virtual HandleResult OnPrepareConnect(IntPtr dwConnId, uint socket) + { + return HandleResult.Ok; + } + + /// + /// 已连接 + /// + /// + /// + protected virtual HandleResult OnConnect(IntPtr dwConnId) + { + return HandleResult.Ok; + } + + /// + /// 客户端发数据了 + /// + /// + /// + /// + /// + protected virtual HandleResult OnSend(IntPtr dwConnId, IntPtr pData, int iLength) + { + return HandleResult.Ok; + } + + /// + /// 数据到达了 + /// + /// + /// + /// + /// + protected virtual HandleResult OnReceive(IntPtr dwConnId, IntPtr pData, int iLength) + { + return HandleResult.Ok; + } + + /// + /// 连接关闭了 + /// + /// + /// + protected virtual HandleResult OnClose(IntPtr dwConnId) + { + return HandleResult.Ok; + } + + /// + /// 出错了 + /// + /// + /// + /// + /// + protected virtual HandleResult OnError(IntPtr dwConnId, SocketOperation enOperation, int iErrorCode) + { + return HandleResult.Ok; + } + + /// + /// Agent关闭了 + /// + /// + protected virtual HandleResult OnAgentShutdown() + { + return HandleResult.Ok; + } + + ///////////////////////////////////////////////////////////////////////// + + /// + /// 获取系统返回的错误码 + /// + /// + public int SYSGetLastError() + { + return HPSocketSdk.SYS_GetLastError(); + } + + /// + /// 调用系统的 ::WSAGetLastError() 方法获取通信错误代码 + /// + /// + public int SYSWSAGetLastError() + { + return HPSocketSdk.SYS_WSAGetLastError(); + } + + /// + /// 调用系统的 setsockopt() + /// + /// + /// + /// + /// + /// + /// + /// + public int SYS_SetSocketOption(IntPtr sock, int level, int name, IntPtr val, int len) + { + return HPSocketSdk.SYS_SetSocketOption(sock, level, name, val, len); + } + + /// + /// 调用系统的 getsockopt() + /// + /// + /// + /// + /// + /// + /// + /// + public int SYSGetSocketOption(IntPtr sock, int level, int name, IntPtr val, ref int len) + { + return HPSocketSdk.SYS_GetSocketOption(sock, level, name, val, ref len); + } + /// + /// 调用系统的 ioctlsocket() + /// + /// + /// + /// + /// + /// + public int SYSIoctlSocket(IntPtr sock, long cmd, IntPtr arg) + { + return HPSocketSdk.SYS_IoctlSocket(sock, cmd, arg); + } + + /// + /// 调用系统的 ::WSAIoctl() + /// + /// + /// + /// + /// + /// + /// + /// + /// + public int SYS_WSAIoctl(IntPtr sock, uint dwIoControlCode, IntPtr lpvInBuffer, uint cbInBuffer, + IntPtr lpvOutBuffer, uint cbOutBuffer, uint lpcbBytesReturned) + { + return HPSocketSdk.SYS_WSAIoctl(sock, dwIoControlCode, lpvInBuffer, cbInBuffer, + lpvOutBuffer, cbOutBuffer, lpcbBytesReturned); + } + + /// + /// 由结构体转换为byte数组 + /// + public byte[] StructureToByte(T structure) + { + int size = Marshal.SizeOf(typeof(T)); + byte[] buffer = new byte[size]; + IntPtr bufferIntPtr = Marshal.AllocHGlobal(size); + try + { + Marshal.StructureToPtr(structure, bufferIntPtr, true); + Marshal.Copy(bufferIntPtr, buffer, 0, size); + } + finally + { + Marshal.FreeHGlobal(bufferIntPtr); + } + return buffer; + } + + /// + /// 由byte数组转换为结构体 + /// + public T ByteToStructure(byte[] dataBuffer) + { + object structure = null; + int size = Marshal.SizeOf(typeof(T)); + IntPtr allocIntPtr = Marshal.AllocHGlobal(size); + try + { + Marshal.Copy(dataBuffer, 0, allocIntPtr, size); + structure = Marshal.PtrToStructure(allocIntPtr, typeof(T)); + } + finally + { + Marshal.FreeHGlobal(allocIntPtr); + } + return (T)structure; + } + + /// + /// 对象序列化成byte[] + /// + /// + /// + public byte[] ObjectToBytes(object obj) + { + using (MemoryStream ms = new MemoryStream()) + { + IFormatter formatter = new BinaryFormatter(); + formatter.Serialize(ms, obj); + return ms.GetBuffer(); + } + } + + /// + /// byte[]序列化成对象 + /// + /// + /// + public object BytesToObject(byte[] bytes) + { + using (MemoryStream ms = new MemoryStream(bytes)) + { + IFormatter formatter = new BinaryFormatter(); + return formatter.Deserialize(ms); + } + } + } +} diff --git a/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/HPSocketCS/TcpClient.cs b/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/HPSocketCS/TcpClient.cs new file mode 100644 index 000000000..1d268b71b --- /dev/null +++ b/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/HPSocketCS/TcpClient.cs @@ -0,0 +1,843 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Runtime.InteropServices; +using HPSocketCS.SDK; +using System.IO; +using System.Runtime.Serialization; +using System.Runtime.Serialization.Formatters.Binary; + +namespace HPSocketCS +{ + public class TcpClient + { + protected IntPtr _pClient = IntPtr.Zero; + + protected IntPtr pClient + { + get + { + //if (_pClient == IntPtr.Zero) + //{ + // throw new Exception("pClient == 0"); + //} + + return _pClient; + } + + set + { + _pClient = value; + } + } + + + protected IntPtr pListener = IntPtr.Zero; + + protected HPSocketSdk.OnConnect OnConnectCallback; + protected HPSocketSdk.OnSend OnSendCallback; + protected HPSocketSdk.OnPrepareConnect OnPrepareConnectCallback; + protected HPSocketSdk.OnReceive OnReceiveCallback; + protected HPSocketSdk.OnClose OnCloseCallback; + protected HPSocketSdk.OnError OnErrorCallback; + + protected bool IsSetCallback = false; + protected bool IsCreate = false; + + public TcpClient() + { + CreateListener(); + } + + ~TcpClient() + { + //if (HasStarted() == true) + //{ + // Stop(); + //} + + Destroy(); + } + + /// + /// 创建socket监听&服务组件 + /// + /// 是否使用tcpserver类默认回调函数 + /// + protected virtual bool CreateListener() + { + if (IsCreate == true || pListener != IntPtr.Zero || pClient != IntPtr.Zero) + { + return false; + } + + pListener = HPSocketSdk.Create_HP_TcpClientListener(); + if (pListener == IntPtr.Zero) + { + return false; + } + + pClient = HPSocketSdk.Create_HP_TcpClient(pListener); + if (pClient == IntPtr.Zero) + { + return false; + } + + IsCreate = true; + + return true; + } + + /// + /// 释放TcpServer和TcpServerListener + /// + public virtual void Destroy() + { + Stop(); + + if (pClient != IntPtr.Zero) + { + HPSocketSdk.Destroy_HP_TcpClient(pClient); + pClient = IntPtr.Zero; + } + if (pListener != IntPtr.Zero) + { + HPSocketSdk.Destroy_HP_TcpClientListener(pListener); + pListener = IntPtr.Zero; + } + + IsCreate = false; + } + + /// + /// 启动通讯组件并连接到服务器 + /// + /// + /// + /// 是否异步 + /// + public bool Start(string address, ushort port, bool async = false) + { + if (string.IsNullOrEmpty(address) == true) + { + throw new Exception("address is null"); + } + else if (port == 0) + { + throw new Exception("port is zero"); + } + + if (IsSetCallback == false) + { + // throw new Exception("请在调用Start方法前先调用SetCallback()方法"); + } + + if (HasStarted() == true) + { + return false; + } + + return HPSocketSdk.HP_Client_Start(pClient, address, port, async); + } + + /// + /// 停止通讯组件 + /// + /// + public bool Stop() + { + if (HasStarted() == false) + { + return false; + } + return HPSocketSdk.HP_Client_Stop(pClient); + } + + /// + /// 发送数据 + /// + /// + /// + /// + /// + public bool Send(byte[] bytes, int size) + { + return HPSocketSdk.HP_Client_Send(pClient, bytes, size); + } + + /// + /// 发送数据 + /// + /// + /// + /// + /// + public bool Send(IntPtr bufferPtr, int size) + { + return HPSocketSdk.HP_Client_Send(pClient, bufferPtr, size); + } + + + /// + /// 发送数据 + /// + /// + /// + /// + /// + public bool Send(T obj) + { + byte[] buffer = StructureToByte(obj); + return Send(buffer, buffer.Length); + } + + /// + /// 序列化对象后发送数据,序列化对象所属类必须标记[Serializable] + /// + /// + /// + /// + /// + public bool SendBySerializable(object obj) + { + byte[] buffer = ObjectToBytes(obj); + return Send(buffer, buffer.Length); + } + + /// + /// 发送数据 + /// + /// + /// + /// 针对bytes的偏移 + /// 发多大 + /// + public bool Send(byte[] bytes, int offset, int size) + { + return HPSocketSdk.HP_Client_SendPart(pClient, bytes, size, offset); + } + + /// + /// 发送数据 + /// + /// + /// + /// 针对bufferPtr的偏移 + /// 发多大 + /// + public bool Send(IntPtr bufferPtr, int offset, int size) + { + return HPSocketSdk.HP_Client_SendPart(pClient, bufferPtr, size, offset); + } + + /// + /// 发送多组数据 + /// 向指定连接发送多组数据 + /// TCP - 顺序发送所有数据包 + /// + /// 连接 ID + /// 发送缓冲区数组 + /// 发送缓冲区数目 + /// TRUE.成功,FALSE.失败,可通过 SYSGetLastError() 获取 Windows 错误代码 + public bool SendPackets(WSABUF[] buffers, int count) + { + return HPSocketSdk.HP_Client_SendPackets(pClient, buffers, count); + } + + + /// + /// 发送多组数据 + /// 向指定连接发送多组数据 + /// TCP - 顺序发送所有数据包 + /// + /// 连接 ID + /// 发送缓冲区数组 + /// 发送缓冲区数目 + /// TRUE.成功,FALSE.失败,可通过 SYSGetLastError() 获取 Windows 错误代码 + public bool SendPackets(T[] objects) + { + bool ret = false; + + WSABUF[] buffer = new WSABUF[objects.Length]; + IntPtr[] ptrs = new IntPtr[buffer.Length]; + try + { + + for (int i = 0; i < objects.Length; i++) + { + buffer[i].Length = Marshal.SizeOf(typeof(T)); + + ptrs[i] = Marshal.AllocHGlobal(buffer[i].Length); + Marshal.StructureToPtr(objects[i], ptrs[i], true); + + buffer[i].Buffer = ptrs[i]; + } + ret = SendPackets(buffer, buffer.Length); + } + catch (Exception ex) + { + throw ex; + } + finally + { + for (int i = 0; i < ptrs.Length; i++) + { + if (ptrs[i] != IntPtr.Zero) + { + Marshal.FreeHGlobal(ptrs[i]); + } + } + } + + return ret; + } + + /// + /// 名称:发送小文件 + /// 描述:向指定连接发送 4096 KB 以下的小文件 + /// + /// 文件路径 + /// 头部附加数据 + /// 尾部附加数据 + /// TRUE.成功,FALSE.失败,可通过 SYSGetLastError() 获取 Windows 错误代码 + public bool SendSmallFile(string filePath, ref WSABUF head, ref WSABUF tail) + { + return HPSocketSdk.HP_TcpClient_SendSmallFile(pClient, filePath, ref head, ref tail); + } + + /// + /// 名称:发送小文件 + /// 描述:向指定连接发送 4096 KB 以下的小文件 + /// + /// 文件路径 + /// 头部附加数据,可以为null + /// 尾部附加数据,可以为null + /// TRUE.成功,FALSE.失败,可通过 SYSGetLastError() 获取 Windows 错误代码 + public bool SendSmallFile(string filePath, byte[] head, byte[] tail) + { + IntPtr pHead = IntPtr.Zero; + IntPtr pTail = IntPtr.Zero; + WSABUF wsaHead = new WSABUF() { Length = 0, Buffer = pHead }; + WSABUF wsatail = new WSABUF() { Length = 0, Buffer = pTail }; + if (head != null) + { + wsaHead.Length = head.Length; + wsaHead.Buffer = Marshal.UnsafeAddrOfPinnedArrayElement(head, 0); + } + + if (tail != null) + { + wsaHead.Length = tail.Length; + wsaHead.Buffer = Marshal.UnsafeAddrOfPinnedArrayElement(tail, 0); + } + + return SendSmallFile(filePath, ref wsaHead, ref wsatail); + } + + /// + /// 名称:发送小文件 + /// 描述:向指定连接发送 4096 KB 以下的小文件 + /// + /// 文件路径 + /// 头部附加数据,可以为null + /// 尾部附加数据,可以为null + /// TRUE.成功,FALSE.失败,可通过 SYSGetLastError() 获取 Windows 错误代码 + public bool SendSmallFile(string filePath, T1 head, T2 tail) + { + + byte[] headBuffer = null; + if (head != null) + { + headBuffer = StructureToByte(head); + } + + byte[] tailBuffer = null; + if (tail != null) + { + StructureToByte(head); + } + return SendSmallFile(filePath, headBuffer, tailBuffer); + } + + /// + /// 获取错误码 + /// + /// + public SocketError GetlastError() + { + return HPSocketSdk.HP_Client_GetLastError(pClient); + } + + /// + /// 获取错误信息 + /// + /// + public string GetLastErrorDesc() + { + IntPtr ptr = HPSocketSdk.HP_Client_GetLastErrorDesc(pClient); + string desc = Marshal.PtrToStringUni(ptr); + return desc; + } + + /// + /// 获取连接中未发出数据的长度 + /// + /// + /// + /// + public bool GetPendingDataLength(ref int length) + { + return HPSocketSdk.HP_Client_GetPendingDataLength(pClient, ref length); + } + + // 是否启动 + public bool HasStarted() + { + if (pClient == IntPtr.Zero) + { + return false; + } + return HPSocketSdk.HP_Client_HasStarted(pClient); + } + + /// + /// 获取状态 + /// + /// + public ServiceState GetState() + { + return HPSocketSdk.HP_Client_GetState(pClient); + } + + /// + /// 获取监听socket的地址信息 + /// + /// + /// + /// + /// + public bool GetListenAddress(ref string ip, ref ushort port) + { + int ipLength = 40; + + StringBuilder sb = new StringBuilder(ipLength); + + bool ret = HPSocketSdk.HP_Client_GetLocalAddress(pClient, sb, ref ipLength, ref port); + if (ret == true) + { + ip = sb.ToString(); + } + return ret; + } + + /// + /// 获取该组件对象的连接Id + /// + /// + public IntPtr GetConnectionId() + { + return HPSocketSdk.HP_Client_GetConnectionID(pClient); + } + + /////////////////////////////////////////////////////////////////////////////////////// + + /// + /// 设置内存块缓存池大小(通常设置为 -> PUSH 模型:5 - 10;PULL 模型:10 - 20 ) + /// + /// + public void SetFreeBufferPoolSize(uint val) + { + HPSocketSdk.HP_Client_SetFreeBufferPoolSize(pClient, val); + } + + /// + /// 设置内存块缓存池回收阀值(通常设置为内存块缓存池大小的 3 倍) + /// + /// + public void SetFreeBufferPoolHold(uint val) + { + HPSocketSdk.HP_Client_SetFreeBufferPoolHold(pClient, val); + } + + /// + /// 获取内存块缓存池大小 + /// + /// + public uint GetFreeBufferPoolSize() + { + return HPSocketSdk.HP_Client_GetFreeBufferPoolSize(pClient); + } + + /// + /// 获取内存块缓存池回收阀值 + /// + /// + public uint GetFreeBufferPoolHold() + { + return HPSocketSdk.HP_Client_GetFreeBufferPoolHold(pClient); + } + + /////////////////////////////////////////////////////////////////////////////////////// + + /// + /// 设置通信数据缓冲区大小(根据平均通信数据包大小调整设置,通常设置为:(N * 1024) - sizeof(TBufferObj)) + /// + /// + public void SetSocketBufferSize(uint val) + { + HPSocketSdk.HP_TcpClient_SetSocketBufferSize(pClient, val); + } + + /// + /// 设置心跳包间隔(毫秒,0 则不发送心跳包) + /// + /// + public void SetKeepAliveTime(uint val) + { + HPSocketSdk.HP_TcpClient_SetKeepAliveTime(pClient, val); + } + + /// + /// 设置心跳确认包检测间隔(毫秒,0 不发送心跳包,如果超过若干次 [默认:WinXP 5 次, Win7 10 次] 检测不到心跳确认包则认为已断线) + /// + /// + public void SetKeepAliveInterval(uint val) + { + HPSocketSdk.HP_TcpClient_SetKeepAliveInterval(pClient, val); + } + + /// + /// 获取通信数据缓冲区大小 + /// + /// + public uint GetSocketBufferSize() + { + return HPSocketSdk.HP_TcpClient_GetSocketBufferSize(pClient); + } + + /// + /// 获取心跳检查次数 + /// + /// + public uint GetKeepAliveTime() + { + return HPSocketSdk.HP_TcpClient_GetKeepAliveTime(pClient); + } + + /// + /// 获取心跳检查间隔 + /// + /// + public uint GetKeepAliveInterval() + { + return HPSocketSdk.HP_TcpClient_GetKeepAliveInterval(pClient); + } + + + /// + /// 根据错误码返回错误信息 + /// + /// + /// + public string GetSocketErrorDesc(SocketError code) + { + IntPtr ptr = HPSocketSdk.HP_GetSocketErrorDesc(code); + string desc = Marshal.PtrToStringUni(ptr); + return desc; + } + + /////////////////////////////////////////////////////////////////////////////////////// + + /// + /// 设置回调函数 + /// + /// + /// + /// + /// + /// + /// + public void SetCallback(HPSocketSdk.OnPrepareConnect prepareConnect, HPSocketSdk.OnConnect connect, + HPSocketSdk.OnSend send, HPSocketSdk.OnReceive recv, HPSocketSdk.OnClose close, + HPSocketSdk.OnError error) + { + if (IsSetCallback == true) + { + throw new Exception("已经调用过SetCallback()方法,如果您确定没手动调用过该方法,并想要手动设置各回调函数,请在构造该类构造函数中传false值,并再次调用该方法。"); + } + + + // 设置 Socket 监听器回调函数 + OnConnectCallback = new HPSocketSdk.OnConnect(connect); + OnSendCallback = new HPSocketSdk.OnSend(send); + OnPrepareConnectCallback = new HPSocketSdk.OnPrepareConnect(prepareConnect); + OnReceiveCallback = new HPSocketSdk.OnReceive(recv); + OnCloseCallback = new HPSocketSdk.OnClose(close); + OnErrorCallback = new HPSocketSdk.OnError(error); + + // 设置 Socket 监听器回调函数 + HPSocketSdk.HP_Set_FN_Client_OnPrepareConnect(pListener, OnPrepareConnectCallback); + HPSocketSdk.HP_Set_FN_Client_OnConnect(pListener, OnConnectCallback); + HPSocketSdk.HP_Set_FN_Client_OnSend(pListener, OnSendCallback); + HPSocketSdk.HP_Set_FN_Client_OnReceive(pListener, OnReceiveCallback); + HPSocketSdk.HP_Set_FN_Client_OnClose(pListener, OnCloseCallback); + HPSocketSdk.HP_Set_FN_Client_OnError(pListener, OnErrorCallback); + + IsSetCallback = true; + } + + public virtual void SetOnErrorCallback(HPSocketSdk.OnError error) + { + OnErrorCallback = new HPSocketSdk.OnError(error); + HPSocketSdk.HP_Set_FN_Server_OnError(pListener, OnErrorCallback); + } + + public virtual void SetOnCloseCallback(HPSocketSdk.OnClose close) + { + OnCloseCallback = new HPSocketSdk.OnClose(close); + HPSocketSdk.HP_Set_FN_Server_OnClose(pListener, OnCloseCallback); + } + + public virtual void SetOnReceiveCallback(HPSocketSdk.OnReceive recv) + { + OnReceiveCallback = new HPSocketSdk.OnReceive(recv); + HPSocketSdk.HP_Set_FN_Server_OnReceive(pListener, OnReceiveCallback); + } + + public virtual void SetOnPrepareConnectCallback(HPSocketSdk.OnPrepareConnect prepareConnect) + { + OnPrepareConnectCallback = new HPSocketSdk.OnPrepareConnect(prepareConnect); + HPSocketSdk.HP_Set_FN_Agent_OnPrepareConnect(pListener, OnPrepareConnectCallback); + } + + public virtual void SetOnConnectCallback(HPSocketSdk.OnConnect connect) + { + OnConnectCallback = new HPSocketSdk.OnConnect(connect); + HPSocketSdk.HP_Set_FN_Agent_OnConnect(pListener, OnConnectCallback); + } + + public virtual void SetOnSendCallback(HPSocketSdk.OnSend send) + { + OnSendCallback = new HPSocketSdk.OnSend(send); + HPSocketSdk.HP_Set_FN_Server_OnSend(pListener, OnSendCallback); + } + ////////////////////////////////////////////////////////////////////////////////////// + + /// + /// 准备连接了 到达一次 + /// + /// + /// + /// + protected virtual HandleResult OnPrepareConnect(IntPtr dwConnId, uint socket) + { + return HandleResult.Ok; + } + + /// + /// 已连接 到达一次 + /// + /// + /// + protected virtual HandleResult OnConnect(IntPtr dwConnId) + { + return HandleResult.Ok; + } + + /// + /// 客户端发数据了 + /// + /// + /// + /// + /// + protected virtual HandleResult OnSend(IntPtr dwConnId, IntPtr pData, int iLength) + { + return HandleResult.Ok; + } + + /// + /// 数据到达了 + /// + /// + /// + /// + /// + protected virtual HandleResult OnReceive(IntPtr dwConnId, IntPtr pData, int iLength) + { + return HandleResult.Ok; + } + + /// + /// 连接关闭了 + /// + /// + /// + protected virtual HandleResult OnClose(IntPtr dwConnId) + { + return HandleResult.Ok; + } + + /// + /// 出错了 + /// + /// + /// + /// + /// + protected virtual HandleResult OnError(IntPtr dwConnId, SocketOperation enOperation, int iErrorCode) + { + return HandleResult.Ok; + } + + /////////////////////////////////////////////////////////////////////////// + + /// + /// 获取系统返回的错误码 + /// + /// + public int SYSGetLastError() + { + return HPSocketSdk.SYS_GetLastError(); + } + + /// + /// 调用系统的 ::WSAGetLastError() 方法获取通信错误代码 + /// + /// + public int SYSWSAGetLastError() + { + return HPSocketSdk.SYS_WSAGetLastError(); + } + + /// + /// 调用系统的 setsockopt() + /// + /// + /// + /// + /// + /// + /// + /// + public int SYS_SetSocketOption(IntPtr sock, int level, int name, IntPtr val, int len) + { + return HPSocketSdk.SYS_SetSocketOption(sock, level, name, val, len); + } + + /// + /// 调用系统的 getsockopt() + /// + /// + /// + /// + /// + /// + /// + /// + public int SYSGetSocketOption(IntPtr sock, int level, int name, IntPtr val, ref int len) + { + return HPSocketSdk.SYS_GetSocketOption(sock, level, name, val, ref len); + } + /// + /// 调用系统的 ioctlsocket() + /// + /// + /// + /// + /// + /// + public int SYSIoctlSocket(IntPtr sock, long cmd, IntPtr arg) + { + return HPSocketSdk.SYS_IoctlSocket(sock, cmd, arg); + } + + /// + /// 调用系统的 ::WSAIoctl() + /// + /// + /// + /// + /// + /// + /// + /// + /// + public int SYS_WSAIoctl(IntPtr sock, uint dwIoControlCode, IntPtr lpvInBuffer, uint cbInBuffer, + IntPtr lpvOutBuffer, uint cbOutBuffer, uint lpcbBytesReturned) + { + return HPSocketSdk.SYS_WSAIoctl(sock, dwIoControlCode, lpvInBuffer, cbInBuffer, + lpvOutBuffer, cbOutBuffer, lpcbBytesReturned); + } + + /// + /// 由结构体转换为byte数组 + /// + public byte[] StructureToByte(T structure) + { + int size = Marshal.SizeOf(typeof(T)); + byte[] buffer = new byte[size]; + IntPtr bufferIntPtr = Marshal.AllocHGlobal(size); + try + { + Marshal.StructureToPtr(structure, bufferIntPtr, true); + Marshal.Copy(bufferIntPtr, buffer, 0, size); + } + finally + { + Marshal.FreeHGlobal(bufferIntPtr); + } + return buffer; + } + + /// + /// 由byte数组转换为结构体 + /// + public T ByteToStructure(byte[] dataBuffer) + { + object structure = null; + int size = Marshal.SizeOf(typeof(T)); + IntPtr allocIntPtr = Marshal.AllocHGlobal(size); + try + { + Marshal.Copy(dataBuffer, 0, allocIntPtr, size); + structure = Marshal.PtrToStructure(allocIntPtr, typeof(T)); + } + finally + { + Marshal.FreeHGlobal(allocIntPtr); + } + return (T)structure; + } + + /// + /// 对象序列化成byte[] + /// + /// + /// + public byte[] ObjectToBytes(object obj) + { + using (MemoryStream ms = new MemoryStream()) + { + IFormatter formatter = new BinaryFormatter(); + formatter.Serialize(ms, obj); + return ms.GetBuffer(); + } + } + + /// + /// byte[]序列化成对象 + /// + /// + /// + public object BytesToObject(byte[] bytes) + { + using (MemoryStream ms = new MemoryStream(bytes)) + { + IFormatter formatter = new BinaryFormatter(); + return formatter.Deserialize(ms); + } + } + } +} diff --git a/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/HPSocketCS/TcpPullAgent.cs b/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/HPSocketCS/TcpPullAgent.cs new file mode 100644 index 000000000..b6b854950 --- /dev/null +++ b/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/HPSocketCS/TcpPullAgent.cs @@ -0,0 +1,128 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using HPSocketCS.SDK; + +namespace HPSocketCS +{ + public class TcpPullAgent : TcpAgent + { + protected HPSocketSdk.OnPullReceive OnPullReceiveCallback; + + public TcpPullAgent() + { + CreateListener(); + } + + ~TcpPullAgent() + { + Destroy(); + } + + /// + /// 创建socket监听&服务组件 + /// + /// 是否使用tcppullAgent类默认回调函数 + /// + protected override bool CreateListener() + { + if (IsCreate == true || pListener != IntPtr.Zero || pAgent != IntPtr.Zero) + { + return false; + } + + pListener = HPSocketSdk.Create_HP_TcpPullAgentListener(); + if (pListener == IntPtr.Zero) + { + return false; + } + + pAgent = HPSocketSdk.Create_HP_TcpPullAgent(pListener); + if (pAgent == IntPtr.Zero) + { + return false; + } + + IsCreate = true; + + return true; + } + + /// + /// 抓取数据 + /// 用户通过该方法从 Socket 组件中抓取数据 + /// + /// + /// + /// + /// + public FetchResult Fetch(IntPtr connId, IntPtr pBuffer, int size) + { + return HPSocketSdk.HP_TcpPullAgent_Fetch(pAgent, connId, pBuffer, size); + } + + /// + /// 设置回调函数 + /// + /// + /// + /// + /// + /// + /// + /// + public virtual void SetCallback(HPSocketSdk.OnPrepareConnect prepareConnect, HPSocketSdk.OnConnect connect, + HPSocketSdk.OnSend send, HPSocketSdk.OnPullReceive recv, HPSocketSdk.OnClose close, + HPSocketSdk.OnError error, HPSocketSdk.OnAgentShutdown agentShutdown) + { + + // 设置 Socket 监听器回调函数 + OnPullReceiveCallback = new HPSocketSdk.OnPullReceive(recv); + + // 设置 Socket 监听器回调函数 + HPSocketSdk.HP_Set_FN_Server_OnPullReceive(pListener, OnPullReceiveCallback); + + base.SetCallback(OnPrepareConnect, OnConnect, OnSend, OnReceive, OnClose, OnError, OnAgentShutdown); ; + } + + + public virtual void SetOnPullReceiveCallback(HPSocketSdk.OnPullReceive recv) + { + OnPullReceiveCallback = new HPSocketSdk.OnPullReceive(recv); + HPSocketSdk.HP_Set_FN_Server_OnPullReceive(pListener, OnPullReceiveCallback); + } + + /// + /// 释放TcpPullAgent和TcpPullAgentListener + /// + public override void Destroy() + { + Stop(); + + if (pAgent != IntPtr.Zero) + { + HPSocketSdk.Destroy_HP_TcpPullAgent(pAgent); + pAgent = IntPtr.Zero; + } + if (pListener != IntPtr.Zero) + { + HPSocketSdk.Destroy_HP_TcpPullAgentListener(pListener); + pListener = IntPtr.Zero; + } + + IsCreate = false; + } + + /// + /// 数据到达 + /// + /// + /// + /// + protected virtual HandleResult OnPullReceive(uint dwConnId, int iLength) + { + return HandleResult.Ok; + } + } +} diff --git a/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/HPSocketCS/TcpPullClient.cs b/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/HPSocketCS/TcpPullClient.cs new file mode 100644 index 000000000..4890fe42b --- /dev/null +++ b/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/HPSocketCS/TcpPullClient.cs @@ -0,0 +1,126 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using HPSocketCS.SDK; + +namespace HPSocketCS +{ + public class TcpPullClient : TcpClient + { + protected HPSocketSdk.OnPullReceive OnPullReceiveCallback; + + public TcpPullClient() + { + CreateListener(); + } + + ~TcpPullClient() + { + Destroy(); + } + + /// + /// 创建socket监听&服务组件 + /// + /// 是否使用tcppullclient类默认回调函数 + /// + protected override bool CreateListener() + { + if (IsCreate == true || pListener != IntPtr.Zero || pClient != IntPtr.Zero) + { + return false; + } + + pListener = HPSocketSdk.Create_HP_TcpPullClientListener(); + if (pListener == IntPtr.Zero) + { + return false; + } + + pClient = HPSocketSdk.Create_HP_TcpPullClient(pListener); + if (pClient == IntPtr.Zero) + { + return false; + } + + IsCreate = true; + + return true; + } + + /// + /// 抓取数据 + /// 用户通过该方法从 Socket 组件中抓取数据 + /// + /// + /// + /// + /// + public FetchResult Fetch(IntPtr connId, IntPtr pBuffer, int size) + { + return HPSocketSdk.HP_TcpPullClient_Fetch(pClient, connId, pBuffer, size); + } + + /// + /// 设置回调函数 + /// + /// + /// + /// + /// + /// + /// + public virtual void SetCallback(HPSocketSdk.OnPrepareConnect prepareConnect, HPSocketSdk.OnConnect connect, + HPSocketSdk.OnSend send, HPSocketSdk.OnPullReceive recv, HPSocketSdk.OnClose close, + HPSocketSdk.OnError error) + { + + // 设置 Socket 监听器回调函数 + OnPullReceiveCallback = new HPSocketSdk.OnPullReceive(recv); + + // 设置 Socket 监听器回调函数 + HPSocketSdk.HP_Set_FN_Server_OnPullReceive(pListener, OnPullReceiveCallback); + + base.SetCallback(prepareConnect, connect, send, OnReceive, close, error); + } + + public virtual void SetOnPullReceiveCallback(HPSocketSdk.OnPullReceive recv) + { + OnPullReceiveCallback = new HPSocketSdk.OnPullReceive(recv); + HPSocketSdk.HP_Set_FN_Server_OnPullReceive(pListener, OnPullReceiveCallback); + } + + /// + /// 释放TcpPullClient和TcpPullClientListener + /// + public override void Destroy() + { + Stop(); + + if (pClient != IntPtr.Zero) + { + HPSocketSdk.Destroy_HP_TcpPullClient(pClient); + pClient = IntPtr.Zero; + } + if (pListener != IntPtr.Zero) + { + HPSocketSdk.Destroy_HP_TcpPullClientListener(pListener); + pListener = IntPtr.Zero; + } + + IsCreate = false; + } + + /// + /// 数据到达 + /// + /// + /// + /// + protected virtual HandleResult OnPullReceive(uint dwConnId, int iLength) + { + return HandleResult.Ok; + } + } +} diff --git a/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/HPSocketCS/TcpPullServer.cs b/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/HPSocketCS/TcpPullServer.cs new file mode 100644 index 000000000..3b34674f5 --- /dev/null +++ b/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/HPSocketCS/TcpPullServer.cs @@ -0,0 +1,124 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Runtime.InteropServices; +using HPSocketCS.SDK; + +namespace HPSocketCS +{ + public class TcpPullServer : TcpServer + { + + protected HPSocketSdk.OnPullReceive OnPullReceiveCallback; + + public TcpPullServer() + { + CreateListener(); + } + + /// + /// 创建socket监听&服务组件 + /// + /// 是否使用tcppullserver类默认回调函数 + /// + protected override bool CreateListener() + { + if (IsCreate == true || pListener != IntPtr.Zero || pServer != IntPtr.Zero) + { + return false; + } + + pListener = HPSocketSdk.Create_HP_TcpPullServerListener(); + if (pListener == IntPtr.Zero) + { + return false; + } + + pServer = HPSocketSdk.Create_HP_TcpPullServer(pListener); + if (pServer == IntPtr.Zero) + { + return false; + } + + IsCreate = true; + + return true; + } + + /// + /// 抓取数据 + /// 用户通过该方法从 Socket 组件中抓取数据 + /// + /// + /// + /// + /// + public FetchResult Fetch(IntPtr connId, IntPtr pBuffer, int size) + { + return HPSocketSdk.HP_TcpPullServer_Fetch(pServer, connId, pBuffer, size); + } + + /// + /// 设置回调函数 + /// + /// + /// + /// + /// + /// + /// + /// + public virtual void SetCallback(HPSocketSdk.OnPrepareListen prepareListen, + HPSocketSdk.OnAccept accept, HPSocketSdk.OnSend send, + HPSocketSdk.OnPullReceive recv, HPSocketSdk.OnClose close, + HPSocketSdk.OnError error, HPSocketSdk.OnServerShutdown shutdown) + { + + // 设置 Socket 监听器回调函数 + OnPullReceiveCallback = new HPSocketSdk.OnPullReceive(recv); + + // 设置 Socket 监听器回调函数 + HPSocketSdk.HP_Set_FN_Server_OnPullReceive(pListener, OnPullReceiveCallback); + + base.SetCallback(prepareListen, accept, send, OnReceive, close, error, shutdown); + } + + public virtual void SetOnPullReceiveCallback(HPSocketSdk.OnPullReceive recv) + { + OnPullReceiveCallback = new HPSocketSdk.OnPullReceive(recv); + HPSocketSdk.HP_Set_FN_Server_OnPullReceive(pListener, OnPullReceiveCallback); + } + + /// + /// 释放TcpPullServer和TcpPullServerListener + /// + public override void Destroy() + { + Stop(); + + if (pServer != IntPtr.Zero) + { + HPSocketSdk.Destroy_HP_TcpPullServer(pServer); + pServer = IntPtr.Zero; + } + if (pListener != IntPtr.Zero) + { + HPSocketSdk.Destroy_HP_TcpPullServerListener(pListener); + pListener = IntPtr.Zero; + } + IsCreate = false; + } + + /// + /// 数据到达 + /// + /// + /// + /// + protected virtual HandleResult OnPullReceive(IntPtr dwConnId, int iLength) + { + return HandleResult.Ok; + } + } +} diff --git a/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/HPSocketCS/TcpServer.cs b/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/HPSocketCS/TcpServer.cs new file mode 100644 index 000000000..c9d0018b5 --- /dev/null +++ b/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/HPSocketCS/TcpServer.cs @@ -0,0 +1,1153 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Runtime.InteropServices; +using HPSocketCS.SDK; +using System.IO; +using System.Runtime.Serialization.Formatters.Binary; +using System.Runtime.Serialization; + +namespace HPSocketCS +{ + public class TcpServer + { + protected IntPtr _pServer = IntPtr.Zero; + protected IntPtr pServer + { + get + { + //if (_pServer == IntPtr.Zero) + //{ + // throw new Exception("pServer == 0"); + //} + + return _pServer; + } + + set + { + _pServer = value; + } + } + + protected IntPtr pListener = IntPtr.Zero; + + protected HPSocketSdk.OnAccept OnAcceptCallback; + protected HPSocketSdk.OnSend OnSendCallback; + protected HPSocketSdk.OnPrepareListen OnPrepareListenCallback; + protected HPSocketSdk.OnReceive OnReceiveCallback; + protected HPSocketSdk.OnClose OnCloseCallback; + protected HPSocketSdk.OnError OnErrorCallback; + protected HPSocketSdk.OnServerShutdown OnServerShutdownCallback; + + protected bool IsSetCallback = false; + protected bool IsCreate = false; + + /// + /// tcpserver构造 + /// + public TcpServer() + { + CreateListener(); + } + + ~TcpServer() + { + //if (HasStarted() == true) + //{ + // Stop(); + //} + + Destroy(); + } + + /// + /// 创建socket监听&服务组件 + /// + /// 是否使用tcpserver类默认回调函数 + /// + protected virtual bool CreateListener() + { + if (IsCreate == true || pListener != IntPtr.Zero || pServer != IntPtr.Zero) + { + return false; + } + + pListener = HPSocketSdk.Create_HP_TcpServerListener(); + if (pListener == IntPtr.Zero) + { + return false; + } + pServer = HPSocketSdk.Create_HP_TcpServer(pListener); + if (pServer == IntPtr.Zero) + { + return false; + } + + IsCreate = true; + + return true; + } + + /// + /// 释放TcpServer和TcpServerListener + /// + public virtual void Destroy() + { + Stop(); + + if (pServer != IntPtr.Zero) + { + HPSocketSdk.Destroy_HP_TcpServer(pServer); + pServer = IntPtr.Zero; + } + if (pListener != IntPtr.Zero) + { + HPSocketSdk.Destroy_HP_TcpServerListener(pListener); + pListener = IntPtr.Zero; + } + + IsCreate = false; + } + + + /// + /// 启动服务 + /// + /// + /// + /// + public bool Start(string address, ushort port) + { + if (string.IsNullOrEmpty(address) == true) + { + throw new Exception("address is null"); + } + else if (port == 0) + { + throw new Exception("port is zero"); + } + + if (IsSetCallback == false) + { + // throw new Exception("请在调用Start方法前先调用SetCallback()方法"); + } + + if (HasStarted() == true) + { + return false; + } + + return HPSocketSdk.HP_Server_Start(pServer, address, port); + } + + /// + /// 停止服务 + /// + /// + public bool Stop() + { + if (HasStarted() == false) + { + return false; + } + + return HPSocketSdk.HP_Server_Stop(pServer); + } + + /// + /// 发送数据 + /// + /// + /// + /// + /// + public bool Send(IntPtr connId, byte[] bytes, int size) + { + return HPSocketSdk.HP_Server_Send(pServer, connId, bytes, size); + } + + /// + /// 发送数据 + /// + /// + /// + /// + /// + public bool Send(IntPtr connId, IntPtr bufferPtr, int size) + { + return HPSocketSdk.HP_Server_Send(pServer, connId, bufferPtr, size); + } + + + /// + /// 发送数据 + /// + /// + /// + /// 针对bytes的偏移 + /// 发多大 + /// + public bool Send(IntPtr connId, byte[] bytes, int offset, int size) + { + return HPSocketSdk.HP_Server_SendPart(pServer, connId, bytes, size, offset); + } + + /// + /// 发送数据 + /// + /// + /// + /// 针对bufferPtr的偏移 + /// 发多大 + /// + public bool Send(IntPtr connId, IntPtr bufferPtr, int offset, int size) + { + return HPSocketSdk.HP_Server_SendPart(pServer, connId, bufferPtr, size, offset); + } + + /// + /// 发送数据 + /// + /// + /// + /// + /// + public bool Send(IntPtr connId, T obj) + { + byte[] buffer = StructureToByte(obj); + return Send(connId, buffer, buffer.Length); + } + + /// + /// 序列化对象后发送数据,序列化对象所属类必须标记[Serializable] + /// + /// + /// + /// + /// + public bool SendBySerializable(IntPtr connId, object obj) + { + byte[] buffer = ObjectToBytes(obj); + return Send(connId, buffer, buffer.Length); + } + + /// + /// 发送多组数据 + /// 向指定连接发送多组数据 + /// TCP - 顺序发送所有数据包 + /// + /// 连接 ID + /// 发送缓冲区数组 + /// 发送缓冲区数目 + /// TRUE.成功,FALSE.失败,可通过 SYSGetLastError() 获取 Windows 错误代码 + public bool SendPackets(IntPtr connId, WSABUF[] pBuffers, int count) + { + return HPSocketSdk.HP_Server_SendPackets(pServer, connId, pBuffers, count); + } + + /// + /// 发送多组数据 + /// 向指定连接发送多组数据 + /// TCP - 顺序发送所有数据包 + /// + /// 连接 ID + /// 发送缓冲区数组 + /// 发送缓冲区数目 + /// TRUE.成功,FALSE.失败,可通过 SYSGetLastError() 获取 Windows 错误代码 + public bool SendPackets(IntPtr connId, T[] objects) + { + bool ret = false; + + WSABUF[] buffer = new WSABUF[objects.Length]; + IntPtr[] ptrs = new IntPtr[buffer.Length]; + try + { + + for (int i = 0; i < objects.Length; i++) + { + buffer[i].Length = Marshal.SizeOf(typeof(T)); + + ptrs[i] = Marshal.AllocHGlobal(buffer[i].Length); + Marshal.StructureToPtr(objects[i], ptrs[i], true); + + buffer[i].Buffer = ptrs[i]; + } + ret = SendPackets(connId, buffer, buffer.Length); + } + catch (Exception ex) + { + throw ex; + } + finally + { + for (int i = 0; i < ptrs.Length; i++) + { + if (ptrs[i] != IntPtr.Zero) + { + Marshal.FreeHGlobal(ptrs[i]); + } + } + } + + return ret; + } + + /// + /// 名称:发送小文件 + /// 描述:向指定连接发送 4096 KB 以下的小文件 + /// + /// + /// 文件路径 + /// 头部附加数据 + /// 尾部附加数据 + /// TRUE.成功,FALSE.失败,可通过 SYSGetLastError() 获取 Windows 错误代码 + public bool SendSmallFile(IntPtr connId, string filePath, ref WSABUF head, ref WSABUF tail) + { + return HPSocketSdk.HP_TcpServer_SendSmallFile(pServer, connId, filePath, ref head, ref tail); + } + + /// + /// 名称:发送小文件 + /// 描述:向指定连接发送 4096 KB 以下的小文件 + /// + /// + /// 文件路径 + /// 头部附加数据,可以为null + /// 尾部附加数据,可以为null + /// TRUE.成功,FALSE.失败,可通过 SYSGetLastError() 获取 Windows 错误代码 + public bool SendSmallFile(IntPtr connId, string filePath, byte[] head, byte[] tail) + { + IntPtr pHead = IntPtr.Zero; + IntPtr pTail = IntPtr.Zero; + WSABUF wsaHead = new WSABUF() { Length = 0, Buffer = pHead }; + WSABUF wsatail = new WSABUF() { Length = 0, Buffer = pTail }; + if (head != null) + { + wsaHead.Length = head.Length; + wsaHead.Buffer = Marshal.UnsafeAddrOfPinnedArrayElement(head, 0); + } + + if (tail != null) + { + wsaHead.Length = tail.Length; + wsaHead.Buffer = Marshal.UnsafeAddrOfPinnedArrayElement(tail, 0); + } + + return SendSmallFile(connId, filePath, ref wsaHead, ref wsatail); + } + + /// + /// 名称:发送小文件 + /// 描述:向指定连接发送 4096 KB 以下的小文件 + /// + /// + /// 文件路径 + /// 头部附加数据,可以为null + /// 尾部附加数据,可以为null + /// TRUE.成功,FALSE.失败,可通过 SYSGetLastError() 获取 Windows 错误代码 + public bool SendSmallFile(IntPtr connId, string filePath, T1 head, T2 tail) + { + + byte[] headBuffer = null; + if (head != null) + { + headBuffer = StructureToByte(head); + } + + byte[] tailBuffer = null; + if (tail != null) + { + StructureToByte(head); + } + return SendSmallFile(connId, filePath, headBuffer, tailBuffer); + } + + /// + /// 断开与某个客户的连接 + /// + /// + /// 是否强制断开 + /// + public bool Disconnect(IntPtr dwConnId, bool force = true) + { + return HPSocketSdk.HP_Server_Disconnect(pServer, dwConnId, force); + } + + + /// + /// 断开超过指定时间的连接 + /// + /// 毫秒 + /// 强制 + /// + public bool DisconnectLongConnections(uint period, bool force = true) + { + return HPSocketSdk.HP_Server_DisconnectLongConnections(pServer, period, force); + } + + /// + /// 获取某个连接的远程ip和端口 + /// + /// + /// + /// + /// + public bool GetRemoteAddress(IntPtr connId, ref string ip, ref ushort port) + { + int ipLength = 40; + + StringBuilder sb = new StringBuilder(ipLength); + + bool ret = HPSocketSdk.HP_Server_GetRemoteAddress(pServer, connId, sb, ref ipLength, ref port) && ipLength > 0; + if (ret == true) + { + ip = sb.ToString(); + } + + return ret; + } + + /// + /// 获取错误码 + /// + /// + public SocketError GetlastError() + { + return HPSocketSdk.HP_Server_GetLastError(pServer); + } + + /// + /// 获取错误信息 + /// + /// + public string GetLastErrorDesc() + { + IntPtr ptr = HPSocketSdk.HP_Server_GetLastErrorDesc(pServer); + string desc = Marshal.PtrToStringUni(ptr); + return desc; + } + + /// + /// 获取连接中未发出数据的长度 + /// + /// + /// + /// + public bool GetPendingDataLength(IntPtr connId, ref int length) + { + return HPSocketSdk.HP_Server_GetPendingDataLength(pServer, connId, ref length); + } + + /// + /// 设置连接的附加数据 + /// + /// + /// 如果为null,则为释放设置的数据 + /// + public bool SetConnectionExtra(IntPtr connId, object obj) + { + + IntPtr ptr = IntPtr.Zero; + // 释放附加数据 + if (HPSocketSdk.HP_Server_GetConnectionExtra(pServer, connId, ref ptr) && ptr != IntPtr.Zero) + { + Marshal.FreeHGlobal(ptr); + ptr = IntPtr.Zero; + } + + if (obj != null) + { + // 设置附加数据 + ptr = Marshal.AllocHGlobal(Marshal.SizeOf(obj)); + Marshal.StructureToPtr(obj, ptr, false); + } + + return HPSocketSdk.HP_Server_SetConnectionExtra(pServer, connId, ptr); + } + + /// + /// 获取附加数据 + /// 如设置的是个结构体/类对象,可以用 Type objA = (Type)Marshal.PtrToStructure(ptr, typeof(Type)) 获取 + /// 其中Type是结构体/类名,ptr是该方法的传出值,在该方法返回为true的时候可用 + /// + /// + /// + /// + public bool GetConnectionExtra(IntPtr connId, ref IntPtr ptr) + { + return HPSocketSdk.HP_Server_GetConnectionExtra(pServer, connId, ref ptr) && ptr != IntPtr.Zero; + } + + // 是否启动 + public bool HasStarted() + { + if (pServer == IntPtr.Zero) + { + return false; + } + return HPSocketSdk.HP_Server_HasStarted(pServer); + } + + /// + /// 获取状态 + /// + /// + public ServiceState GetState() + { + return HPSocketSdk.HP_Server_GetState(pServer); + } + + /// + /// 获取连接数 + /// + /// + public uint GetConnectionCount() + { + return HPSocketSdk.HP_Server_GetConnectionCount(pServer); + } + + /// + /// 获取所有连接数,未获取到连接数返回null + /// + /// + public IntPtr[] GetAllConnectionIDs() + { + IntPtr[] arr = null; + do + { + uint count = GetConnectionCount(); + if (count == 0) + { + break; + } + arr = new IntPtr[count]; + if (HPSocketSdk.HP_Server_GetAllConnectionIDs(pServer, arr, ref count)) + { + if (arr.Length > count) + { + IntPtr[] newArr = new IntPtr[count]; + Array.Copy(arr, newArr, count); + arr = newArr; + } + break; + } + } while (true); + + return arr; + } + + /// + /// 获取监听socket的地址信息 + /// + /// + /// + /// + public bool GetListenAddress(ref string ip, ref ushort port) + { + int ipLength = 40; + + StringBuilder sb = new StringBuilder(ipLength); + + bool ret = HPSocketSdk.HP_Server_GetListenAddress(pServer, sb, ref ipLength, ref port); + if (ret == true) + { + ip = sb.ToString(); + } + return ret; + } + + /// + /// 获取指定连接的连接时长 + /// + /// + /// + /// + public bool GetConnectPeriod(IntPtr connId, ref uint period) + { + return HPSocketSdk.HP_Server_GetConnectPeriod(pServer, connId, ref period); + } + + + /////////////////////////////////////////////////////////////////////////////////////// + + /// + /// 设置工作线程数量(通常设置为 2 * CPU + 2) + /// + /// + public void SetWorkerThreadCount(uint val) + { + HPSocketSdk.HP_Server_SetWorkerThreadCount(pServer, val); + } + + /// + /// 设置 Accept 预投递数量(根据负载调整设置,Accept 预投递数量越大则支持的并发连接请求越多) + /// + /// + public void SetAcceptSocketCount(uint val) + { + HPSocketSdk.HP_TcpServer_SetAcceptSocketCount(pServer, val); + } + + /// + /// 设置通信数据缓冲区大小(根据平均通信数据包大小调整设置,通常设置为 1024 的倍数) + /// + /// + public void SetSocketBufferSize(uint val) + { + HPSocketSdk.HP_TcpServer_SetSocketBufferSize(pServer, val); + } + + /// + /// 设置监听 Socket 的等候队列大小(根据并发连接数量调整设置) + /// + /// + public void SetSocketListenQueue(uint val) + { + HPSocketSdk.HP_TcpServer_SetSocketListenQueue(pServer, val); + } + + /// + /// 设置 Socket 缓存对象锁定时间(毫秒,在锁定期间该 Socket 缓存对象不能被获取使用) + /// + /// + public void Server_SetFreeSocketObjLockTime(uint val) + { + HPSocketSdk.HP_Server_SetFreeSocketObjLockTime(pServer, val); + } + + /// + /// 设置 Socket 缓存池大小(通常设置为平均并发连接数量的 1/3 - 1/2) + /// + /// + public void SetFreeSocketObjPool(uint val) + { + HPSocketSdk.HP_Server_SetFreeSocketObjPool(pServer, val); + } + + /// + /// 设置内存块缓存池大小(通常设置为 Socket 缓存池大小的 2 - 3 倍) + /// + /// + public void SetFreeBufferObjPool(uint val) + { + HPSocketSdk.HP_Server_SetFreeBufferObjPool(pServer, val); + } + + /// + /// 设置 Socket 缓存池回收阀值(通常设置为 Socket 缓存池大小的 3 倍) + /// + /// + public void SetFreeSocketObjHold(uint val) + { + HPSocketSdk.HP_Server_SetFreeSocketObjHold(pServer, val); + } + + /// + /// 设置内存块缓存池回收阀值(通常设置为内存块缓存池大小的 3 倍) + /// + /// + public void SetFreeBufferObjHold(uint val) + { + HPSocketSdk.HP_Server_SetFreeBufferObjHold(pServer, val); + } + + /// + /// 设置心跳包间隔(毫秒,0 则不发送心跳包) + /// + /// + public void SetKeepAliveTime(uint val) + { + HPSocketSdk.HP_TcpServer_SetKeepAliveTime(pServer, val); + } + + /// + /// 设置心跳确认包检测间隔(毫秒,0 不发送心跳包,如果超过若干次 [默认:WinXP 5 次, Win7 10 次] 检测不到心跳确认包则认为已断线) + /// + /// + public void SetKeepAliveInterval(uint val) + { + HPSocketSdk.HP_TcpServer_SetKeepAliveInterval(pServer, val); + } + + /// + /// 设置关闭服务前等待连接关闭的最长时限(毫秒,0 则不等待) + /// + /// + public void SetMaxShutdownWaitTime(uint val) + { + HPSocketSdk.HP_Server_SetMaxShutdownWaitTime(pServer, val); + } + + /// + /// 获取工作线程数量 + /// + /// + public uint GetWorkerThreadCount() + { + return HPSocketSdk.HP_Server_GetWorkerThreadCount(pServer); + } + + /// + /// 获取 Accept 预投递数量 + /// + /// + public uint GetAcceptSocketCount() + { + return HPSocketSdk.HP_TcpServer_GetAcceptSocketCount(pServer); + } + + /// + /// 获取通信数据缓冲区大小 + /// + /// + public uint GetSocketBufferSize() + { + return HPSocketSdk.HP_TcpServer_GetSocketBufferSize(pServer); + } + + /// + /// 获取监听 Socket 的等候队列大小 + /// + /// + public uint GetSocketListenQueue() + { + return HPSocketSdk.HP_TcpServer_GetSocketListenQueue(pServer); + } + + /// + /// 获取 Socket 缓存对象锁定时间 + /// + /// + public uint GetFreeSocketObjLockTime() + { + return HPSocketSdk.HP_Server_GetFreeSocketObjLockTime(pServer); + } + + /// + /// 获取 Socket 缓存池大小 + /// + /// + public uint GetFreeSocketObjPool() + { + return HPSocketSdk.HP_Server_GetFreeSocketObjPool(pServer); + } + + /// + /// 获取内存块缓存池大小 + /// + /// + public uint GetFreeBufferObjPool() + { + return HPSocketSdk.HP_Server_GetFreeBufferObjPool(pServer); + } + + /// + /// 获取 Socket 缓存池回收阀值 + /// + /// + public uint GetFreeSocketObjHold() + { + return HPSocketSdk.HP_Server_GetFreeSocketObjHold(pServer); + } + + /// + /// 获取内存块缓存池回收阀值 + /// + /// + public uint GetFreeBufferObjHold() + { + return HPSocketSdk.HP_Server_GetFreeBufferObjHold(pServer); + } + + /// + /// 获取心跳检查次数 + /// + /// + public uint GetKeepAliveTime() + { + return HPSocketSdk.HP_TcpServer_GetKeepAliveTime(pServer); + } + + /// + /// 获取心跳检查间隔 + /// + /// + public uint GetKeepAliveInterval() + { + return HPSocketSdk.HP_TcpServer_GetKeepAliveInterval(pServer); + } + + /// + /// 获取关闭服务前等待连接关闭的最长时限 + /// + /// + public uint GetMaxShutdownWaitTime() + { + return HPSocketSdk.HP_Server_GetMaxShutdownWaitTime(pServer); + } + + + /// + /// 根据错误码返回错误信息 + /// + /// + /// + public string GetSocketErrorDesc(SocketError code) + { + IntPtr ptr = HPSocketSdk.HP_GetSocketErrorDesc(code); + string desc = Marshal.PtrToStringUni(ptr); + return desc; + } + + /// + /// 设置数据发送策略 + /// + /// + public void SetSendPolicy(SendPolicy policy) + { + HPSocketSdk.HP_Server_SetSendPolicy(pServer, policy); + } + + /// + /// 获取数据发送策略 + /// + /// + /// + public SendPolicy GetSendPolicy() + { + return HPSocketSdk.HP_Server_GetSendPolicy(pServer); + } + + /// + /// 设置数据接收策略 + /// + /// + public void SetRecvPolicy(RecvPolicy policy) + { + HPSocketSdk.HP_Server_SetRecvPolicy(pServer, policy); + } + + /// + /// 获取数据接收策略 + /// + /// + /// + public RecvPolicy GetRecvPolicy() + { + return HPSocketSdk.HP_Server_GetRecvPolicy(pServer); + } + /////////////////////////////////////////////////////////////////////////////////////// + + /// + /// 设置回调函数 + /// + /// + /// + /// + /// + /// + /// + /// + public virtual void SetCallback(HPSocketSdk.OnPrepareListen prepareListen, HPSocketSdk.OnAccept accept, HPSocketSdk.OnSend send, HPSocketSdk.OnReceive recv, HPSocketSdk.OnClose close, HPSocketSdk.OnError error, HPSocketSdk.OnServerShutdown shutdown) + { + if (IsSetCallback == true) + { + throw new Exception("已经调用过SetCallback()方法,如果您确定没手动调用过该方法,并想要手动设置各回调函数,请在构造该类构造函数中传false值,并再次调用该方法。"); + } + + // 设置 Socket 监听器回调函数 + OnAcceptCallback = new HPSocketSdk.OnAccept(accept); + OnSendCallback = new HPSocketSdk.OnSend(send); + OnPrepareListenCallback = new HPSocketSdk.OnPrepareListen(prepareListen); + OnReceiveCallback = new HPSocketSdk.OnReceive(recv); + OnCloseCallback = new HPSocketSdk.OnClose(close); + OnErrorCallback = new HPSocketSdk.OnError(error); + OnServerShutdownCallback = new HPSocketSdk.OnServerShutdown(shutdown); + + // 设置 Socket 监听器回调函数 + HPSocketSdk.HP_Set_FN_Server_OnPrepareListen(pListener, OnPrepareListenCallback); + HPSocketSdk.HP_Set_FN_Server_OnAccept(pListener, OnAcceptCallback); + HPSocketSdk.HP_Set_FN_Server_OnSend(pListener, OnSendCallback); + HPSocketSdk.HP_Set_FN_Server_OnReceive(pListener, OnReceiveCallback); + HPSocketSdk.HP_Set_FN_Server_OnClose(pListener, OnCloseCallback); + HPSocketSdk.HP_Set_FN_Server_OnError(pListener, OnErrorCallback); + HPSocketSdk.HP_Set_FN_Server_OnServerShutdown(pListener, OnServerShutdownCallback); + + IsSetCallback = true; + + } + + public virtual void SetOnServerShutdownCallback(HPSocketSdk.OnServerShutdown shutdown) + { + OnServerShutdownCallback = new HPSocketSdk.OnServerShutdown(shutdown); + HPSocketSdk.HP_Set_FN_Server_OnServerShutdown(pListener, OnServerShutdownCallback); + } + + public virtual void SetOnErrorCallback(HPSocketSdk.OnError error) + { + OnErrorCallback = new HPSocketSdk.OnError(error); + HPSocketSdk.HP_Set_FN_Server_OnError(pListener, OnErrorCallback); + } + + public virtual void SetOnCloseCallback(HPSocketSdk.OnClose close) + { + OnCloseCallback = new HPSocketSdk.OnClose(close); + HPSocketSdk.HP_Set_FN_Server_OnClose(pListener, OnCloseCallback); + } + + public virtual void SetOnReceiveCallback(HPSocketSdk.OnReceive recv) + { + OnReceiveCallback = new HPSocketSdk.OnReceive(recv); + HPSocketSdk.HP_Set_FN_Server_OnReceive(pListener, OnReceiveCallback); + } + + public virtual void SetOnPrepareListenCallback(HPSocketSdk.OnPrepareListen prepareListen) + { + OnPrepareListenCallback = new HPSocketSdk.OnPrepareListen(prepareListen); + HPSocketSdk.HP_Set_FN_Server_OnPrepareListen(pListener, OnPrepareListenCallback); + } + + public virtual void SetOnAcceptCallback(HPSocketSdk.OnAccept accept) + { + OnAcceptCallback = new HPSocketSdk.OnAccept(accept); + HPSocketSdk.HP_Set_FN_Server_OnAccept(pListener, OnAcceptCallback); + } + + public virtual void SetOnSendCallback(HPSocketSdk.OnSend send) + { + OnSendCallback = new HPSocketSdk.OnSend(send); + HPSocketSdk.HP_Set_FN_Server_OnSend(pListener, OnSendCallback); + } + + + /////////////////////////////////////////////////////////////////////////////////////// + + + /// + /// 监听事件 + /// + /// + /// + protected virtual HandleResult OnPrepareListen(IntPtr soListen) + { + return HandleResult.Ok; + } + + /// + /// 客户进入 + /// + /// + /// + /// + protected virtual HandleResult OnAccept(IntPtr dwConnId, IntPtr pClient) + { + return HandleResult.Ok; + } + + /// + /// 服务器发数据了 + /// + /// + /// + /// + /// + protected virtual HandleResult OnSend(IntPtr dwConnId, IntPtr pData, int iLength) + { + return HandleResult.Ok; + } + + /// + /// 数据到达了 + /// + /// + /// + /// + /// + protected virtual HandleResult OnReceive(IntPtr dwConnId, IntPtr pData, int iLength) + { + return HandleResult.Ok; + } + + /// + /// 客户离开了 + /// + /// + /// + protected virtual HandleResult OnClose(IntPtr dwConnId) + { + return HandleResult.Ok; + } + + /// + /// 出错了 + /// + /// + /// + /// + /// + protected virtual HandleResult OnError(IntPtr dwConnId, SocketOperation enOperation, int iErrorCode) + { + return HandleResult.Ok; + } + + /// + /// 服务关闭了 + /// + /// + protected virtual HandleResult OnServerShutdown() + { + return HandleResult.Ok; + } + + ///////////////////////////////////////////////////////////////////////// + + /// + /// 获取系统返回的错误码 + /// + /// + public int SYSGetLastError() + { + return HPSocketSdk.SYS_GetLastError(); + } + + /// + /// 调用系统的 ::WSAGetLastError() 方法获取通信错误代码 + /// + /// + public int SYSWSAGetLastError() + { + return HPSocketSdk.SYS_WSAGetLastError(); + } + + /// + /// 调用系统的 setsockopt() + /// + /// + /// + /// + /// + /// + /// + /// + public int SYS_SetSocketOption(IntPtr sock, int level, int name, IntPtr val, int len) + { + return HPSocketSdk.SYS_SetSocketOption(sock, level, name, val, len); + } + + /// + /// 调用系统的 getsockopt() + /// + /// + /// + /// + /// + /// + /// + /// + public int SYSGetSocketOption(IntPtr sock, int level, int name, IntPtr val, ref int len) + { + return HPSocketSdk.SYS_GetSocketOption(sock, level, name, val, ref len); + } + /// + /// 调用系统的 ioctlsocket() + /// + /// + /// + /// + /// + /// + public int SYSIoctlSocket(IntPtr sock, long cmd, IntPtr arg) + { + return HPSocketSdk.SYS_IoctlSocket(sock, cmd, arg); + } + + /// + /// 调用系统的 ::WSAIoctl() + /// + /// + /// + /// + /// + /// + /// + /// + /// + public int SYS_WSAIoctl(IntPtr sock, uint dwIoControlCode, IntPtr lpvInBuffer, uint cbInBuffer, + IntPtr lpvOutBuffer, uint cbOutBuffer, uint lpcbBytesReturned) + { + return HPSocketSdk.SYS_WSAIoctl(sock, dwIoControlCode, lpvInBuffer, cbInBuffer, + lpvOutBuffer, cbOutBuffer, lpcbBytesReturned); + } + + /// + /// 由结构体转换为byte数组 + /// + public byte[] StructureToByte(T structure) + { + int size = Marshal.SizeOf(typeof(T)); + byte[] buffer = new byte[size]; + IntPtr bufferIntPtr = Marshal.AllocHGlobal(size); + try + { + Marshal.StructureToPtr(structure, bufferIntPtr, true); + Marshal.Copy(bufferIntPtr, buffer, 0, size); + } + finally + { + Marshal.FreeHGlobal(bufferIntPtr); + } + return buffer; + } + + /// + /// 由byte数组转换为结构体 + /// + public T ByteToStructure(byte[] dataBuffer) + { + object structure = null; + int size = Marshal.SizeOf(typeof(T)); + IntPtr allocIntPtr = Marshal.AllocHGlobal(size); + try + { + Marshal.Copy(dataBuffer, 0, allocIntPtr, size); + structure = Marshal.PtrToStructure(allocIntPtr, typeof(T)); + } + finally + { + Marshal.FreeHGlobal(allocIntPtr); + } + return (T)structure; + } + + /// + /// 对象序列化成byte[] + /// + /// + /// + public byte[] ObjectToBytes(object obj) + { + using (MemoryStream ms = new MemoryStream()) + { + IFormatter formatter = new BinaryFormatter(); + formatter.Serialize(ms, obj); + return ms.GetBuffer(); + } + } + + /// + /// byte[]序列化成对象 + /// + /// + /// + public object BytesToObject(byte[] bytes) + { + using (MemoryStream ms = new MemoryStream(bytes)) + { + IFormatter formatter = new BinaryFormatter(); + return formatter.Deserialize(ms); + } + } + } +} diff --git a/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpClient-PFM/Program.cs b/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpClient-PFM/Program.cs new file mode 100644 index 000000000..4fccde30d --- /dev/null +++ b/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpClient-PFM/Program.cs @@ -0,0 +1,21 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Windows.Forms; + +namespace TcpClient_PFM +{ + static class Program + { + /// + /// 应用程序的主入口点。 + /// + [STAThread] + static void Main() + { + Application.EnableVisualStyles(); + Application.SetCompatibleTextRenderingDefault(false); + Application.Run(new frmClient()); + } + } +} diff --git a/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpClient-PFM/Properties/AssemblyInfo.cs b/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpClient-PFM/Properties/AssemblyInfo.cs new file mode 100644 index 000000000..69cbbd13b --- /dev/null +++ b/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpClient-PFM/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// 有关程序集的常规信息通过以下 +// 特性集控制。更改这些特性值可修改 +// 与程序集关联的信息。 +[assembly: AssemblyTitle("TcpClient-PMF")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("TcpClient-PMF")] +[assembly: AssemblyCopyright("Copyright © 2014")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// 将 ComVisible 设置为 false 使此程序集中的类型 +// 对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型, +// 则将该类型上的 ComVisible 特性设置为 true。 +[assembly: ComVisible(false)] + +// 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID +[assembly: Guid("217b3b79-8789-49a0-b8bd-9e65a6ac63f3")] + +// 程序集的版本信息由下面四个值组成: +// +// 主版本 +// 次版本 +// 内部版本号 +// 修订号 +// +// 可以指定所有这些值,也可以使用“内部版本号”和“修订号”的默认值, +// 方法是按如下所示使用“*”: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpClient-PFM/Properties/Resources.Designer.cs b/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpClient-PFM/Properties/Resources.Designer.cs new file mode 100644 index 000000000..54c4a76e1 --- /dev/null +++ b/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpClient-PFM/Properties/Resources.Designer.cs @@ -0,0 +1,63 @@ +//------------------------------------------------------------------------------ +// +// 此代码由工具生成。 +// 运行时版本:4.0.30319.18444 +// +// 对此文件的更改可能会导致不正确的行为,并且如果 +// 重新生成代码,这些更改将会丢失。 +// +//------------------------------------------------------------------------------ + +namespace TcpClient_PFM.Properties { + using System; + + + /// + /// 一个强类型的资源类,用于查找本地化的字符串等。 + /// + // 此类是由 StronglyTypedResourceBuilder + // 类通过类似于 ResGen 或 Visual Studio 的工具自动生成的。 + // 若要添加或移除成员,请编辑 .ResX 文件,然后重新运行 ResGen + // (以 /str 作为命令选项),或重新生成 VS 项目。 + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// + /// 返回此类使用的缓存的 ResourceManager 实例。 + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("TcpClient_PFM.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// 使用此强类型资源类,为所有资源查找 + /// 重写当前线程的 CurrentUICulture 属性。 + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + } +} diff --git a/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpClient-PFM/Properties/Resources.resx b/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpClient-PFM/Properties/Resources.resx new file mode 100644 index 000000000..af7dbebba --- /dev/null +++ b/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpClient-PFM/Properties/Resources.resx @@ -0,0 +1,117 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpClient-PFM/Properties/Settings.Designer.cs b/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpClient-PFM/Properties/Settings.Designer.cs new file mode 100644 index 000000000..e32131dea --- /dev/null +++ b/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpClient-PFM/Properties/Settings.Designer.cs @@ -0,0 +1,26 @@ +//------------------------------------------------------------------------------ +// +// 此代码由工具生成。 +// 运行时版本:4.0.30319.18444 +// +// 对此文件的更改可能会导致不正确的行为,并且如果 +// 重新生成代码,这些更改将会丢失。 +// +//------------------------------------------------------------------------------ + +namespace TcpClient_PFM.Properties { + + + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "10.0.0.0")] + internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { + + private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); + + public static Settings Default { + get { + return defaultInstance; + } + } + } +} diff --git a/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpClient-PFM/Properties/Settings.settings b/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpClient-PFM/Properties/Settings.settings new file mode 100644 index 000000000..39645652a --- /dev/null +++ b/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpClient-PFM/Properties/Settings.settings @@ -0,0 +1,7 @@ + + + + + + + diff --git a/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpClient-PFM/TcpClient-PFM.csproj b/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpClient-PFM/TcpClient-PFM.csproj new file mode 100644 index 000000000..f2ece938d --- /dev/null +++ b/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpClient-PFM/TcpClient-PFM.csproj @@ -0,0 +1,122 @@ + + + + Debug + x86 + 8.0.30703 + 2.0 + {9A2CEAF1-95CF-4E7D-91D5-42DB1F3FD29A} + WinExe + Properties + TcpClient_PFM + TcpClient-PFM + v4.0 + Client + 512 + + + x86 + true + full + false + ..\bin\x86\Debug\ + DEBUG;TRACE + prompt + 4 + + + x86 + pdbonly + true + ..\bin\x86\Release\ + TRACE + prompt + 4 + + + true + ..\bin\x64\Debug\ + DEBUG;TRACE + full + x64 + ..\bin\Debug\TcpClient-PFM.exe.CodeAnalysisLog.xml + true + GlobalSuppressions.cs + prompt + MinimumRecommendedRules.ruleset + ;D:\Program Files\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets + ;D:\Program Files\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules + + + ..\bin\x64\Release\ + TRACE + true + pdbonly + x64 + ..\bin\Release\TcpClient-PFM.exe.CodeAnalysisLog.xml + true + GlobalSuppressions.cs + prompt + MinimumRecommendedRules.ruleset + ;D:\Program Files\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets + ;D:\Program Files\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules + + + + + + + + + + + + + + + + Form + + + frmClient.cs + + + + + frmClient.cs + + + ResXFileCodeGenerator + Resources.Designer.cs + Designer + + + True + Resources.resx + True + + + SettingsSingleFileGenerator + Settings.Designer.cs + + + True + Settings.settings + True + + + + + {DFA935E2-CF37-4E26-B697-D7F3DEE19DD8} + HPSocketCS + + + + + \ No newline at end of file diff --git a/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpClient-PFM/frmClient.Designer.cs b/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpClient-PFM/frmClient.Designer.cs new file mode 100644 index 000000000..5b06812ca --- /dev/null +++ b/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpClient-PFM/frmClient.Designer.cs @@ -0,0 +1,291 @@ +namespace TcpClient_PFM +{ + partial class frmClient + { + /// + /// 必需的设计器变量。 + /// + private System.ComponentModel.IContainer components = null; + + /// + /// 清理所有正在使用的资源。 + /// + /// 如果应释放托管资源,为 true;否则为 false。 + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows 窗体设计器生成的代码 + + /// + /// 设计器支持所需的方法 - 不要 + /// 使用代码编辑器修改此方法的内容。 + /// + private void InitializeComponent() + { + this.label1 = new System.Windows.Forms.Label(); + this.label2 = new System.Windows.Forms.Label(); + this.cbxTestTime = new System.Windows.Forms.ComboBox(); + this.cbxTestInterv = new System.Windows.Forms.ComboBox(); + this.cbxThreadInterv = new System.Windows.Forms.ComboBox(); + this.cbxThreadCount = new System.Windows.Forms.ComboBox(); + this.label3 = new System.Windows.Forms.Label(); + this.label4 = new System.Windows.Forms.Label(); + this.cbxDataLength = new System.Windows.Forms.ComboBox(); + this.label5 = new System.Windows.Forms.Label(); + this.label6 = new System.Windows.Forms.Label(); + this.lbxMsg = new System.Windows.Forms.ListBox(); + this.txtPort = new System.Windows.Forms.TextBox(); + this.txtIpAddress = new System.Windows.Forms.TextBox(); + this.btnStop = new System.Windows.Forms.Button(); + this.btnStart = new System.Windows.Forms.Button(); + this.SuspendLayout(); + // + // label1 + // + this.label1.AutoSize = true; + this.label1.Location = new System.Drawing.Point(25, 15); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(71, 12); + this.label1.TabIndex = 0; + this.label1.Text = "Test Times:"; + // + // label2 + // + this.label2.AutoSize = true; + this.label2.Location = new System.Drawing.Point(19, 41); + this.label2.Name = "label2"; + this.label2.Size = new System.Drawing.Size(77, 12); + this.label2.TabIndex = 1; + this.label2.Text = "Test Interv:"; + // + // cbxTestTime + // + this.cbxTestTime.FormattingEnabled = true; + this.cbxTestTime.Items.AddRange(new object[] { + "1", + "5", + "10", + "30", + "50", + "100", + "300", + "500", + "1000"}); + this.cbxTestTime.Location = new System.Drawing.Point(101, 11); + this.cbxTestTime.Name = "cbxTestTime"; + this.cbxTestTime.Size = new System.Drawing.Size(82, 20); + this.cbxTestTime.TabIndex = 2; + // + // cbxTestInterv + // + this.cbxTestInterv.FormattingEnabled = true; + this.cbxTestInterv.Items.AddRange(new object[] { + "0", + "1", + "3", + "5", + "10", + "20", + "30", + "60", + "100"}); + this.cbxTestInterv.Location = new System.Drawing.Point(101, 38); + this.cbxTestInterv.Name = "cbxTestInterv"; + this.cbxTestInterv.Size = new System.Drawing.Size(82, 20); + this.cbxTestInterv.TabIndex = 3; + // + // cbxThreadInterv + // + this.cbxThreadInterv.FormattingEnabled = true; + this.cbxThreadInterv.Items.AddRange(new object[] { + "0", + "1", + "3", + "5", + "10", + "20", + "30", + "60", + "100"}); + this.cbxThreadInterv.Location = new System.Drawing.Point(303, 38); + this.cbxThreadInterv.Name = "cbxThreadInterv"; + this.cbxThreadInterv.Size = new System.Drawing.Size(82, 20); + this.cbxThreadInterv.TabIndex = 7; + // + // cbxThreadCount + // + this.cbxThreadCount.FormattingEnabled = true; + this.cbxThreadCount.Items.AddRange(new object[] { + "1", + "5", + "10", + "30", + "50", + "100", + "300", + "500", + "1000"}); + this.cbxThreadCount.Location = new System.Drawing.Point(303, 11); + this.cbxThreadCount.Name = "cbxThreadCount"; + this.cbxThreadCount.Size = new System.Drawing.Size(82, 20); + this.cbxThreadCount.TabIndex = 6; + // + // label3 + // + this.label3.AutoSize = true; + this.label3.Location = new System.Drawing.Point(209, 41); + this.label3.Name = "label3"; + this.label3.Size = new System.Drawing.Size(89, 12); + this.label3.TabIndex = 5; + this.label3.Text = "Thread Interv:"; + // + // label4 + // + this.label4.AutoSize = true; + this.label4.Location = new System.Drawing.Point(215, 15); + this.label4.Name = "label4"; + this.label4.Size = new System.Drawing.Size(83, 12); + this.label4.TabIndex = 4; + this.label4.Text = "Thread Count:"; + // + // cbxDataLength + // + this.cbxDataLength.FormattingEnabled = true; + this.cbxDataLength.Items.AddRange(new object[] { + "1", + "10", + "100", + "1000", + "3000", + "5000", + "10000"}); + this.cbxDataLength.Location = new System.Drawing.Point(500, 11); + this.cbxDataLength.Name = "cbxDataLength"; + this.cbxDataLength.Size = new System.Drawing.Size(82, 20); + this.cbxDataLength.TabIndex = 9; + // + // label5 + // + this.label5.AutoSize = true; + this.label5.Location = new System.Drawing.Point(418, 15); + this.label5.Name = "label5"; + this.label5.Size = new System.Drawing.Size(77, 12); + this.label5.TabIndex = 8; + this.label5.Text = "Data Length:"; + // + // label6 + // + this.label6.AutoSize = true; + this.label6.Location = new System.Drawing.Point(399, 41); + this.label6.Name = "label6"; + this.label6.Size = new System.Drawing.Size(191, 12); + this.label6.TabIndex = 10; + this.label6.Text = "\'Interv\' is to slow down speed "; + // + // lbxMsg + // + this.lbxMsg.FormattingEnabled = true; + this.lbxMsg.ItemHeight = 12; + this.lbxMsg.Location = new System.Drawing.Point(21, 67); + this.lbxMsg.Name = "lbxMsg"; + this.lbxMsg.Size = new System.Drawing.Size(561, 352); + this.lbxMsg.TabIndex = 11; + this.lbxMsg.KeyPress += new System.Windows.Forms.KeyPressEventHandler(this.lbxMsg_KeyPress); + // + // txtPort + // + this.txtPort.Location = new System.Drawing.Point(331, 430); + this.txtPort.Name = "txtPort"; + this.txtPort.Size = new System.Drawing.Size(40, 21); + this.txtPort.TabIndex = 16; + this.txtPort.Text = "5555"; + // + // txtIpAddress + // + this.txtIpAddress.Location = new System.Drawing.Point(227, 430); + this.txtIpAddress.Name = "txtIpAddress"; + this.txtIpAddress.Size = new System.Drawing.Size(98, 21); + this.txtIpAddress.TabIndex = 15; + this.txtIpAddress.Text = "127.0.0.1"; + // + // btnStop + // + this.btnStop.Anchor = System.Windows.Forms.AnchorStyles.Top; + this.btnStop.Location = new System.Drawing.Point(476, 426); + this.btnStop.Name = "btnStop"; + this.btnStop.Size = new System.Drawing.Size(106, 26); + this.btnStop.TabIndex = 14; + this.btnStop.Text = "Stop && Check"; + this.btnStop.UseVisualStyleBackColor = true; + this.btnStop.Click += new System.EventHandler(this.btnStop_Click); + // + // btnStart + // + this.btnStart.Anchor = System.Windows.Forms.AnchorStyles.Top; + this.btnStart.Location = new System.Drawing.Point(397, 426); + this.btnStart.Name = "btnStart"; + this.btnStart.Size = new System.Drawing.Size(73, 26); + this.btnStart.TabIndex = 13; + this.btnStart.Text = "Start"; + this.btnStart.UseVisualStyleBackColor = true; + this.btnStart.Click += new System.EventHandler(this.btnStart_Click); + // + // frmClient + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(600, 458); + this.Controls.Add(this.txtPort); + this.Controls.Add(this.txtIpAddress); + this.Controls.Add(this.btnStop); + this.Controls.Add(this.btnStart); + this.Controls.Add(this.lbxMsg); + this.Controls.Add(this.label6); + this.Controls.Add(this.cbxDataLength); + this.Controls.Add(this.label5); + this.Controls.Add(this.cbxThreadInterv); + this.Controls.Add(this.cbxThreadCount); + this.Controls.Add(this.label3); + this.Controls.Add(this.label4); + this.Controls.Add(this.cbxTestInterv); + this.Controls.Add(this.cbxTestTime); + this.Controls.Add(this.label2); + this.Controls.Add(this.label1); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle; + this.Name = "frmClient"; + this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen; + this.Text = "Echo-PFM Client [ \'C\' - clear list box ]"; + this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.frmClient_FormClosing); + this.Load += new System.EventHandler(this.frmClient_Load); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.Label label1; + private System.Windows.Forms.Label label2; + private System.Windows.Forms.ComboBox cbxTestTime; + private System.Windows.Forms.ComboBox cbxTestInterv; + private System.Windows.Forms.ComboBox cbxThreadInterv; + private System.Windows.Forms.ComboBox cbxThreadCount; + private System.Windows.Forms.Label label3; + private System.Windows.Forms.Label label4; + private System.Windows.Forms.ComboBox cbxDataLength; + private System.Windows.Forms.Label label5; + private System.Windows.Forms.Label label6; + private System.Windows.Forms.ListBox lbxMsg; + private System.Windows.Forms.TextBox txtPort; + private System.Windows.Forms.TextBox txtIpAddress; + private System.Windows.Forms.Button btnStop; + private System.Windows.Forms.Button btnStart; + } +} + diff --git a/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpClient-PFM/frmClient.cs b/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpClient-PFM/frmClient.cs new file mode 100644 index 000000000..f93cb9368 --- /dev/null +++ b/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpClient-PFM/frmClient.cs @@ -0,0 +1,391 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Windows.Forms; +using System.Threading; +using System.Diagnostics; +using HPSocketCS; + +namespace TcpClient_PFM +{ + public enum AppState + { + Starting, Started, Stoping, Stoped, Error + } + + public partial class frmClient : Form + { + private AppState appState = AppState.Stoped; + private delegate void ShowMsg(string msg); + private ShowMsg AddMsgDelegate; + + Stopwatch StopWatch = new Stopwatch(); + + int TestTimes = 0; + int TestInterv = 0; + int ThreadCount = 0; + int ThreadInterv = 0; + int DataLength = 0; + + long Timeconsuming = 0; + Int64 TotalReceived = 0; + Int64 TotalSent = 0; + Int64 ExpectReceived = 0; + + Thread testThread = null; + + List clientList = new List(); + + public frmClient() + { + InitializeComponent(); + } + + private void frmClient_Load(object sender, EventArgs e) + { + + // 初始化测试值 + this.cbxTestTime.SelectedIndex = 5; + this.cbxTestInterv.SelectedIndex = 1; + this.cbxThreadInterv.SelectedIndex = 0; + this.cbxThreadCount.SelectedIndex = 5; + this.cbxDataLength.SelectedIndex = 5; + + try + { + // 加个委托显示msg,因为on系列都是在工作线程中调用的,ui不允许直接操作 + AddMsgDelegate = new ShowMsg(AddMsg); + + SetAppState(AppState.Stoped); + + AddMsg("提示:32位系统和程序,调整参数时,组合包的【大小】不要超过系统支持的内存。"); + } + catch (Exception ex) + { + SetAppState(AppState.Error); + AddMsg(ex.Message); + } + } + + private bool CheckParams() + { + bool ret = false; + if (TestTimes <= 0) + { + this.cbxTestTime.Focus(); + } + else if (TestInterv < 0) + { + this.cbxTestInterv.Focus(); + } + else if (ThreadCount <= 0) + { + this.cbxThreadCount.Focus(); + } + else if (ThreadInterv < 0) + { + this.cbxThreadInterv.Focus(); + } + else if (DataLength <= 0) + { + this.cbxDataLength.Focus(); + } + else + { + ret = true; + } + + return ret; + } + + private void btnStart_Click(object sender, EventArgs e) + { + try + { + string address = this.txtIpAddress.Text.Trim(); + ushort port = ushort.Parse(this.txtPort.Text.Trim()); + TestTimes = int.Parse(this.cbxTestTime.Text.Trim()); + TestInterv = int.Parse(this.cbxTestInterv.Text.Trim()); + ThreadCount = int.Parse(this.cbxThreadCount.Text.Trim()); + ThreadInterv = int.Parse(this.cbxThreadInterv.Text.Trim()); + DataLength = int.Parse(this.cbxDataLength.Text.Trim()); + if (CheckParams() == false) + { + throw new Exception("params error!"); + } + + SetAppState(AppState.Starting); + + Timeconsuming = 0; + TotalReceived = 0; + TotalSent = 0; + ExpectReceived = (Int64)TestTimes * (Int64)ThreadCount * (Int64)DataLength; + + clientList.Clear(); + + // 创建指定线程个数的客户端 + for (int i = 0; i < ThreadCount; i++) + { + TcpClient client = new TcpClient(); + client.SetCallback(OnPrepareConnect, OnConnect, OnSend, OnReceive, OnClose, OnError); + if (client.Start(address, port) == true) + { + clientList.Add(client); + } + else + { + foreach (var c in clientList) + { + c.Stop(); + } + clientList.Clear(); + throw new Exception(string.Format(" > {2}, Connection to server fail ->({0},{1})", client.GetlastError(), client.GetLastErrorDesc(), i)); + } + } + + AddMsg(string.Format("$ Client start ok -> ({0}:{1})", address, port)); + + // 延迟3秒 + int sendDelay = 3; + AddMsg(string.Format(" *** willing to send data after {0} seconds ...", sendDelay)); + // Delay2(sendDelay * 1000); + + SetAppState(AppState.Started); + + testThread = new Thread(delegate() + { + Thread.Sleep(sendDelay * 1000); + AddMsg(string.Format(" *** begin... ***", sendDelay)); + // 发送的数据包 + byte[] sendBytes = new byte[DataLength]; + + + StopWatch.Restart(); + bool isTerminated = false; + for (int i = 0; i < TestTimes; i++) + { + for (int j = 0; j < ThreadCount; j++) + { + TcpClient client = clientList[j]; + if (client.Send(sendBytes, sendBytes.Length) == false) + { + AddMsg(string.Format("$ Client send fail [sock: {0}, seq: {1}] -> {3} ({2})", + i + 1, + j + 1, + client.SYSGetLastError(), + client.GetSocketErrorDesc(SocketError.DataSend))); + isTerminated = true; + break; + } + + if (ThreadInterv > 0 && j + 1 < ThreadCount) + { + Thread.Sleep(ThreadInterv); + //Delay2(ThreadInterv); + } + } + + if (isTerminated == true) + { + break; + } + + if (TestInterv > 0 && i + 1 < TestTimes) + { + Thread.Sleep(TestInterv); + //Delay2(TestInterv); + } + } + }); + testThread.Start(); + } + catch (Exception ex) + { + SetAppState(AppState.Stoped); + AddMsg(string.Format("$ Start fail msg:{0}", ex.Message)); + } + } + + private void btnStop_Click(object sender, EventArgs e) + { + SetAppState(AppState.Stoping); + + for (int i = 0; i < clientList.Count; i++) + { + if (clientList[i].Stop() == true) + { + AddMsg(string.Format("$ Client stopping ... --> ({0})", i + 1)); + } + } + + if (testThread.ThreadState == System.Threading.ThreadState.Running) + { + testThread.Abort(); + } + + Delay2(100); + + AddMsg(string.Format("*** Summary: expect - {0}, send - {1}, recv - {2}", + ExpectReceived, TotalSent, TotalReceived)); + + if (ExpectReceived == TotalSent && TotalSent == TotalReceived) + { + AddMsg(string.Format(" *** Success: time consuming - {0} millisecond !", Timeconsuming)); + } + else + { + AddMsg("*** Fail: manual terminated ? (or data lost)"); + } + + SetAppState(AppState.Stoped); + } + + HandleResult OnPrepareConnect(IntPtr dwConnId, uint socket) + { + return HandleResult.Ok; + } + + HandleResult OnConnect(IntPtr dwConnId) + { + // 已连接 到达一次 + AddMsg(string.Format(" > [{0}, OnConnect]", dwConnId)); + return HandleResult.Ok; + } + + HandleResult OnSend(IntPtr dwConnId, IntPtr pData, int iLength) + { + // 客户端发数据了 + Interlocked.Add(ref TotalSent, iLength); + return HandleResult.Ok; + } + + HandleResult OnReceive(IntPtr dwConnId, IntPtr pData, int iLength) + { + // 数据到达了 + + Interlocked.Add(ref TotalReceived, iLength); + if (TotalReceived == ExpectReceived) + { + StopWatch.Stop(); + Timeconsuming = StopWatch.ElapsedMilliseconds; + AddMsg(string.Format("Total time consuming: {0}", Timeconsuming)); + } + + return HandleResult.Ok; + } + + HandleResult OnClose(IntPtr dwConnId) + { + // 连接关闭了 + return HandleResult.Ok; + } + + HandleResult OnError(IntPtr dwConnId, SocketOperation enOperation, int iErrorCode) + { + // 出错了 + return HandleResult.Ok; + } + + + /// + /// 设置程序状态 + /// + /// + void SetAppState(AppState state) + { + appState = state; + this.btnStart.Enabled = (appState == AppState.Stoped); + this.btnStop.Enabled = (appState == AppState.Started); + this.txtIpAddress.Enabled = (appState == AppState.Stoped); + this.txtPort.Enabled = (appState == AppState.Stoped); + this.cbxTestTime.Enabled = (appState == AppState.Stoped); + this.cbxTestInterv.Enabled = (appState == AppState.Stoped); + this.cbxThreadInterv.Enabled = (appState == AppState.Stoped); + this.cbxThreadCount.Enabled = (appState == AppState.Stoped); + this.cbxDataLength.Enabled = (appState == AppState.Stoped); + } + + /// + /// 往listbox加一条项目 + /// + /// + void AddMsg(string msg) + { + if (this.lbxMsg.InvokeRequired) + { + // 很帅的调自己 + this.lbxMsg.Invoke(AddMsgDelegate, msg); + } + else + { + if (this.lbxMsg.Items.Count > 100) + { + this.lbxMsg.Items.RemoveAt(0); + } + this.lbxMsg.Items.Add(msg); + this.lbxMsg.TopIndex = this.lbxMsg.Items.Count - (int)(this.lbxMsg.Height / this.lbxMsg.ItemHeight); + } + } + + public delegate void SleepDelegate(int num); + + /// + /// 精确延迟,摘自网络 + /// + /// + private void Delay1(long time) + { + long b = DateTime.Now.Ticks / 10000; + long e = 0; long c = 0; ; + do + { + e = DateTime.Now.Ticks / 10000; + c = e - b; + Application.DoEvents(); + } + while (c < time); + } + + private void AsyncDelay(int time) + { + Thread.Sleep(time); + } + + /// + /// 精确延迟,摘自网络 + /// + /// + private void Delay2(int time) + { + SleepDelegate delay = new SleepDelegate(AsyncDelay); + IAsyncResult ar = delay.BeginInvoke(time, null, null); + while (ar.IsCompleted == false) + { + Application.DoEvents(); + } + delay.EndInvoke(ar); + } + + private void lbxMsg_KeyPress(object sender, KeyPressEventArgs e) + { + // 清理listbox + if (e.KeyChar == 'c' || e.KeyChar == 'C') + { + this.lbxMsg.Items.Clear(); + } + } + + private void frmClient_FormClosing(object sender, FormClosingEventArgs e) + { + if (appState == AppState.Started) + { + btnStop_Click(sender, e); + } + } + + } +} diff --git a/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpClient-PFM/frmClient.resx b/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpClient-PFM/frmClient.resx new file mode 100644 index 000000000..1af7de150 --- /dev/null +++ b/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpClient-PFM/frmClient.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpClient/Program.cs b/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpClient/Program.cs new file mode 100644 index 000000000..7ca14ba77 --- /dev/null +++ b/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpClient/Program.cs @@ -0,0 +1,21 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Windows.Forms; + +namespace TcpClient +{ + static class Program + { + /// + /// 应用程序的主入口点。 + /// + [STAThread] + static void Main() + { + Application.EnableVisualStyles(); + Application.SetCompatibleTextRenderingDefault(false); + Application.Run(new frmClient()); + } + } +} diff --git a/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpClient/Properties/AssemblyInfo.cs b/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpClient/Properties/AssemblyInfo.cs new file mode 100644 index 000000000..547a67069 --- /dev/null +++ b/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpClient/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// 有关程序集的常规信息通过以下 +// 特性集控制。更改这些特性值可修改 +// 与程序集关联的信息。 +[assembly: AssemblyTitle("Client")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("Client")] +[assembly: AssemblyCopyright("Copyright © 2014")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// 将 ComVisible 设置为 false 使此程序集中的类型 +// 对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型, +// 则将该类型上的 ComVisible 特性设置为 true。 +[assembly: ComVisible(false)] + +// 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID +[assembly: Guid("0b4a498a-774e-4250-bf80-a05682b557fb")] + +// 程序集的版本信息由下面四个值组成: +// +// 主版本 +// 次版本 +// 内部版本号 +// 修订号 +// +// 可以指定所有这些值,也可以使用“内部版本号”和“修订号”的默认值, +// 方法是按如下所示使用“*”: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpClient/Properties/Resources.Designer.cs b/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpClient/Properties/Resources.Designer.cs new file mode 100644 index 000000000..e753f0058 --- /dev/null +++ b/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpClient/Properties/Resources.Designer.cs @@ -0,0 +1,63 @@ +//------------------------------------------------------------------------------ +// +// 此代码由工具生成。 +// 运行时版本:4.0.30319.18444 +// +// 对此文件的更改可能会导致不正确的行为,并且如果 +// 重新生成代码,这些更改将会丢失。 +// +//------------------------------------------------------------------------------ + +namespace TcpClient.Properties { + using System; + + + /// + /// 一个强类型的资源类,用于查找本地化的字符串等。 + /// + // 此类是由 StronglyTypedResourceBuilder + // 类通过类似于 ResGen 或 Visual Studio 的工具自动生成的。 + // 若要添加或移除成员,请编辑 .ResX 文件,然后重新运行 ResGen + // (以 /str 作为命令选项),或重新生成 VS 项目。 + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// + /// 返回此类使用的缓存的 ResourceManager 实例。 + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("TcpClient.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// 使用此强类型资源类,为所有资源查找 + /// 重写当前线程的 CurrentUICulture 属性。 + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + } +} diff --git a/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpClient/Properties/Resources.resx b/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpClient/Properties/Resources.resx new file mode 100644 index 000000000..af7dbebba --- /dev/null +++ b/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpClient/Properties/Resources.resx @@ -0,0 +1,117 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpClient/Properties/Settings.Designer.cs b/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpClient/Properties/Settings.Designer.cs new file mode 100644 index 000000000..319bf2100 --- /dev/null +++ b/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpClient/Properties/Settings.Designer.cs @@ -0,0 +1,26 @@ +//------------------------------------------------------------------------------ +// +// 此代码由工具生成。 +// 运行时版本:4.0.30319.18444 +// +// 对此文件的更改可能会导致不正确的行为,并且如果 +// 重新生成代码,这些更改将会丢失。 +// +//------------------------------------------------------------------------------ + +namespace TcpClient.Properties { + + + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "10.0.0.0")] + internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { + + private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); + + public static Settings Default { + get { + return defaultInstance; + } + } + } +} diff --git a/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpClient/Properties/Settings.settings b/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpClient/Properties/Settings.settings new file mode 100644 index 000000000..39645652a --- /dev/null +++ b/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpClient/Properties/Settings.settings @@ -0,0 +1,7 @@ + + + + + + + diff --git a/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpClient/TcpClient.csproj b/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpClient/TcpClient.csproj new file mode 100644 index 000000000..269eeee46 --- /dev/null +++ b/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpClient/TcpClient.csproj @@ -0,0 +1,127 @@ + + + + Debug + x86 + 8.0.30703 + 2.0 + {B6E43918-236A-4EA7-84C8-ED4A98049907} + WinExe + Properties + TcpClient + TcpClient + v4.0 + Client + 512 + + + x86 + true + full + false + ..\bin\x86\Debug\ + DEBUG;TRACE + prompt + 4 + + + x86 + pdbonly + true + ..\bin\x86\Release\ + TRACE + prompt + 4 + false + + + true + ..\bin\x64\Debug\ + DEBUG;TRACE + full + x64 + ..\bin\Debug\TcpClient.exe.CodeAnalysisLog.xml + true + GlobalSuppressions.cs + prompt + MinimumRecommendedRules.ruleset + ;D:\Program Files\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets + true + ;D:\Program Files\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules + true + + + ..\bin\x64\Release\ + TRACE + true + pdbonly + x64 + ..\bin\Release\TcpClient.exe.CodeAnalysisLog.xml + true + GlobalSuppressions.cs + prompt + MinimumRecommendedRules.ruleset + ;D:\Program Files\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets + true + ;D:\Program Files\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules + true + + + + + + + + + + + + + + + + Form + + + frmClient.cs + + + + + frmClient.cs + + + ResXFileCodeGenerator + Resources.Designer.cs + Designer + + + True + Resources.resx + True + + + SettingsSingleFileGenerator + Settings.Designer.cs + + + True + Settings.settings + True + + + + + {DFA935E2-CF37-4E26-B697-D7F3DEE19DD8} + HPSocketCS + + + + + \ No newline at end of file diff --git a/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpClient/frmClient.Designer.cs b/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpClient/frmClient.Designer.cs new file mode 100644 index 000000000..dd52f4676 --- /dev/null +++ b/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpClient/frmClient.Designer.cs @@ -0,0 +1,205 @@ +namespace TcpClient +{ + partial class frmClient + { + /// + /// 必需的设计器变量。 + /// + private System.ComponentModel.IContainer components = null; + + /// + /// 清理所有正在使用的资源。 + /// + /// 如果应释放托管资源,为 true;否则为 false。 + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows 窗体设计器生成的代码 + + /// + /// 设计器支持所需的方法 - 不要 + /// 使用代码编辑器修改此方法的内容。 + /// + private void InitializeComponent() + { + this.groupBox1 = new System.Windows.Forms.GroupBox(); + this.cbxAsyncConn = new System.Windows.Forms.CheckBox(); + this.txtPort = new System.Windows.Forms.TextBox(); + this.txtIpAddress = new System.Windows.Forms.TextBox(); + this.btnStop = new System.Windows.Forms.Button(); + this.btnStart = new System.Windows.Forms.Button(); + this.lbxMsg = new System.Windows.Forms.ListBox(); + this.txtSend = new System.Windows.Forms.TextBox(); + this.btnSend = new System.Windows.Forms.Button(); + this.btnSendFile = new System.Windows.Forms.Button(); + this.btnSendSerializableObject = new System.Windows.Forms.Button(); + this.groupBox1.SuspendLayout(); + this.SuspendLayout(); + // + // groupBox1 + // + this.groupBox1.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.groupBox1.Controls.Add(this.cbxAsyncConn); + this.groupBox1.Controls.Add(this.txtPort); + this.groupBox1.Controls.Add(this.txtIpAddress); + this.groupBox1.Controls.Add(this.btnStop); + this.groupBox1.Controls.Add(this.btnStart); + this.groupBox1.Location = new System.Drawing.Point(12, 2); + this.groupBox1.Name = "groupBox1"; + this.groupBox1.Size = new System.Drawing.Size(464, 47); + this.groupBox1.TabIndex = 11; + this.groupBox1.TabStop = false; + // + // cbxAsyncConn + // + this.cbxAsyncConn.AutoSize = true; + this.cbxAsyncConn.Checked = true; + this.cbxAsyncConn.CheckState = System.Windows.Forms.CheckState.Checked; + this.cbxAsyncConn.Location = new System.Drawing.Point(134, 20); + this.cbxAsyncConn.Name = "cbxAsyncConn"; + this.cbxAsyncConn.Size = new System.Drawing.Size(84, 16); + this.cbxAsyncConn.TabIndex = 13; + this.cbxAsyncConn.Text = "Async Conn"; + this.cbxAsyncConn.UseVisualStyleBackColor = true; + // + // txtPort + // + this.txtPort.Location = new System.Drawing.Point(88, 18); + this.txtPort.Name = "txtPort"; + this.txtPort.Size = new System.Drawing.Size(40, 21); + this.txtPort.TabIndex = 12; + this.txtPort.Text = "5555"; + // + // txtIpAddress + // + this.txtIpAddress.Location = new System.Drawing.Point(11, 18); + this.txtIpAddress.Name = "txtIpAddress"; + this.txtIpAddress.Size = new System.Drawing.Size(71, 21); + this.txtIpAddress.TabIndex = 11; + this.txtIpAddress.Text = "127.0.0.1"; + // + // btnStop + // + this.btnStop.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.btnStop.Location = new System.Drawing.Point(407, 15); + this.btnStop.Name = "btnStop"; + this.btnStop.Size = new System.Drawing.Size(47, 26); + this.btnStop.TabIndex = 10; + this.btnStop.Text = "Stop"; + this.btnStop.UseVisualStyleBackColor = true; + this.btnStop.Click += new System.EventHandler(this.btnStop_Click); + // + // btnStart + // + this.btnStart.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.btnStart.Location = new System.Drawing.Point(354, 15); + this.btnStart.Name = "btnStart"; + this.btnStart.Size = new System.Drawing.Size(47, 26); + this.btnStart.TabIndex = 9; + this.btnStart.Text = "Start"; + this.btnStart.UseVisualStyleBackColor = true; + this.btnStart.Click += new System.EventHandler(this.btnStart_Click); + // + // lbxMsg + // + this.lbxMsg.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.lbxMsg.FormattingEnabled = true; + this.lbxMsg.ItemHeight = 12; + this.lbxMsg.Location = new System.Drawing.Point(12, 63); + this.lbxMsg.Name = "lbxMsg"; + this.lbxMsg.Size = new System.Drawing.Size(465, 244); + this.lbxMsg.TabIndex = 10; + this.lbxMsg.KeyPress += new System.Windows.Forms.KeyPressEventHandler(this.lbxMsg_KeyPress); + // + // txtSend + // + this.txtSend.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.txtSend.Location = new System.Drawing.Point(11, 321); + this.txtSend.Name = "txtSend"; + this.txtSend.Size = new System.Drawing.Size(413, 21); + this.txtSend.TabIndex = 12; + this.txtSend.Text = "text to be sent"; + // + // btnSend + // + this.btnSend.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); + this.btnSend.Location = new System.Drawing.Point(430, 317); + this.btnSend.Name = "btnSend"; + this.btnSend.Size = new System.Drawing.Size(47, 26); + this.btnSend.TabIndex = 13; + this.btnSend.Text = "Send"; + this.btnSend.UseVisualStyleBackColor = true; + this.btnSend.Click += new System.EventHandler(this.btnSend_Click); + // + // btnSendFile + // + this.btnSendFile.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); + this.btnSendFile.Location = new System.Drawing.Point(206, 348); + this.btnSendFile.Name = "btnSendFile"; + this.btnSendFile.Size = new System.Drawing.Size(75, 26); + this.btnSendFile.TabIndex = 14; + this.btnSendFile.Text = "Send file"; + this.btnSendFile.UseVisualStyleBackColor = true; + this.btnSendFile.Click += new System.EventHandler(this.btnSendFile_Click); + // + // btnSendSerializableObject + // + this.btnSendSerializableObject.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); + this.btnSendSerializableObject.Location = new System.Drawing.Point(313, 348); + this.btnSendSerializableObject.Name = "btnSendSerializableObject"; + this.btnSendSerializableObject.Size = new System.Drawing.Size(163, 26); + this.btnSendSerializableObject.TabIndex = 15; + this.btnSendSerializableObject.Text = "Send serializable object"; + this.btnSendSerializableObject.UseVisualStyleBackColor = true; + this.btnSendSerializableObject.Click += new System.EventHandler(this.btnSendSerializableObject_Click); + // + // frmClient + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(485, 378); + this.Controls.Add(this.btnSendSerializableObject); + this.Controls.Add(this.btnSendFile); + this.Controls.Add(this.btnSend); + this.Controls.Add(this.txtSend); + this.Controls.Add(this.groupBox1); + this.Controls.Add(this.lbxMsg); + this.Name = "frmClient"; + this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen; + this.Text = "Echo-TcpClient [ \'C\' - clear list box ]"; + this.FormClosed += new System.Windows.Forms.FormClosedEventHandler(this.frmClient_FormClosed); + this.Load += new System.EventHandler(this.frmClient_Load); + this.groupBox1.ResumeLayout(false); + this.groupBox1.PerformLayout(); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.GroupBox groupBox1; + private System.Windows.Forms.TextBox txtPort; + private System.Windows.Forms.TextBox txtIpAddress; + private System.Windows.Forms.Button btnStop; + private System.Windows.Forms.Button btnStart; + private System.Windows.Forms.ListBox lbxMsg; + private System.Windows.Forms.CheckBox cbxAsyncConn; + private System.Windows.Forms.TextBox txtSend; + private System.Windows.Forms.Button btnSend; + private System.Windows.Forms.Button btnSendFile; + private System.Windows.Forms.Button btnSendSerializableObject; + + } +} + diff --git a/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpClient/frmClient.cs b/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpClient/frmClient.cs new file mode 100644 index 000000000..121e809b0 --- /dev/null +++ b/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpClient/frmClient.cs @@ -0,0 +1,550 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Windows.Forms; +using HPSocketCS; +using System.Runtime.InteropServices; +using System.IO; +using System.Threading; + +namespace TcpClient +{ + public enum AppState + { + Starting, Started, Stoping, Stoped, Error + } + + public enum StudentType + { + None, Array, List, Single, + } + + public partial class frmClient : Form + { + private AppState appState = AppState.Stoped; + + private delegate void ConnectUpdateUiDelegate(); + private delegate void SetAppStateDelegate(AppState state); + private delegate void ShowMsg(string msg); + private ShowMsg AddMsgDelegate; + HPSocketCS.TcpClient client = new HPSocketCS.TcpClient(); + + bool isSendFile = false; + StudentType studentType = StudentType.None; + public frmClient() + { + InitializeComponent(); + } + + private void frmClient_Load(object sender, EventArgs e) + { + try + { + // 加个委托显示msg,因为on系列都是在工作线程中调用的,ui不允许直接操作 + AddMsgDelegate = new ShowMsg(AddMsg); + + + // 设置 Socket 监听器回调函数 + client.SetCallback(OnPrepareConnect, OnConnect, OnSend, OnReceive, OnClose, OnError); + + + SetAppState(AppState.Stoped); + } + catch (Exception ex) + { + SetAppState(AppState.Error); + AddMsg(ex.Message); + } + } + + private void btnStart_Click(object sender, EventArgs e) + { + try + { + String ip = this.txtIpAddress.Text.Trim(); + ushort port = ushort.Parse(this.txtPort.Text.Trim()); + + // 写在这个位置是上面可能会异常 + SetAppState(AppState.Starting); + + AddMsg(string.Format("$Client Starting ... -> ({0}:{1})", ip, port)); + + if (client.Start(ip, port, this.cbxAsyncConn.Checked)) + { + if (cbxAsyncConn.Checked == false) + { + SetAppState(AppState.Started); + } + + AddMsg(string.Format("$Client Start OK -> ({0}:{1})", ip, port)); + } + else + { + SetAppState(AppState.Stoped); + throw new Exception(string.Format("$Client Start Error -> {0}({1})", client.GetLastErrorDesc(), client.GetlastError())); + } + } + catch (Exception ex) + { + AddMsg(ex.Message); + } + } + + private void btnStop_Click(object sender, EventArgs e) + { + + // 停止服务 + AddMsg("$Server Stop"); + if (client.Stop()) + { + SetAppState(AppState.Stoped); + } + else + { + AddMsg(string.Format("$Stop Error -> {0}({1})", client.GetLastErrorDesc(), client.GetlastError())); + } + } + + private void btnSend_Click(object sender, EventArgs e) + { + try + { + string send = this.txtSend.Text; + if (send.Length == 0) + { + return; + } + + byte[] bytes = Encoding.Default.GetBytes(send); + IntPtr dwConnId = client.GetConnectionId(); + + // 发送 + if (client.Send(bytes, bytes.Length)) + { + AddMsg(string.Format("$ ({0}) Send OK --> {1}", dwConnId, send)); + } + else + { + AddMsg(string.Format("$ ({0}) Send Fail --> {1} ({2})", dwConnId, send, bytes.Length)); + } + + } + catch (Exception ex) + { + AddMsg(string.Format("$ Send Fail --> msg ({0})", ex.Message)); + } + + } + + private void btnSendSerializableObject_Click(object sender, EventArgs e) + { + try + { + // 注: 对象序列化发送数据较大 + + if (studentType != StudentType.None) + { + // 正在执行 + throw new Exception("being implemented"); + } + + + + IntPtr dwConnId = client.GetConnectionId(); + + Thread thread = new Thread(new ThreadStart(delegate() + { + Student[] students = new Student[2]; + students[0] = new Student(); + students[0].Id = 1; + students[0].Name = "张三"; + students[0].Sex = Sex.Female; + students[1] = new Student(); + students[1].Id = 2; + students[1].Name = "李四"; + students[1].Sex = Sex.Male; + + // 发送数组对象 + studentType = StudentType.Array; + if (client.SendBySerializable(students)) + { + AddMsg(string.Format("$ ({0}) Send OK --> {1}", dwConnId, "Student[]")); + } + else + { + AddMsg(string.Format("$ ({0}) Send Fail --> {1}", dwConnId, "Student[]")); + } + + //////////////////////////////////////////////////////////////////////////////// + + // 改变性别 + students[0].Sex = Sex.Transsexual; + + List stuList = new List(); + stuList.Add(students[0]); + stuList.Add(students[1]); + + // 防止粘包,延迟2秒发送下一组数据 + AddMsg(" *** 2 seconds after sending ..."); + Thread.Sleep(2000); + + // 发送list对象 + studentType = StudentType.List; + if (client.SendBySerializable(stuList)) + { + AddMsg(string.Format("$ ({0}) Send OK --> {1}", dwConnId, "List")); + } + else + { + AddMsg(string.Format("$ ({0}) Send Fail --> {1}", dwConnId, "List")); + } + + //////////////////////////////////////////////////////////////////////////////// + + // 防止粘包,延迟2秒发送下一组数据 + AddMsg(" *** 2 seconds after sending ..."); + Thread.Sleep(2000); + + // 改变性别 + students[0].Sex = Sex.Unknown; + + // 发送单个学员信息 + studentType = StudentType.Single; + if (client.SendBySerializable(students[0])) + { + AddMsg(string.Format("$ ({0}) Send OK --> {1}", dwConnId, "Student")); + } + else + { + AddMsg(string.Format("$ ({0}) Send Fail --> {1}", dwConnId, "Student")); + } + + })); + thread.Start(); + } + catch (Exception ex) + { + studentType = StudentType.None; + AddMsg(string.Format("$ Send Fail --> msg ({0})", ex.Message)); + } + } + + private void lbxMsg_KeyPress(object sender, KeyPressEventArgs e) + { + + // 清理listbox + if (e.KeyChar == 'c' || e.KeyChar == 'C') + { + this.lbxMsg.Items.Clear(); + } + } + + void ConnectUpdateUi() + { + if (this.cbxAsyncConn.Checked == true) + { + SetAppState(AppState.Started); + } + } + + + private bool SendFileToServer(string filePath) + { + FileInfo fi = new FileInfo(filePath); + if (fi.Length > 4096 * 1024) + { + throw new Exception("被发送文件大小不能超过4096KB。"); + } + else if (fi.Length == 0) + { + throw new Exception("文件大小不能为0。"); + } + + // 头附加数据 + MyFileInfo myFile = new MyFileInfo() + { + FilePath = filePath, + FileSize = fi.Length, + }; + + // 发送文件标记,用来在onrecv里判断是否文件回包 + isSendFile = true; + + // 不附加尾数据 + bool ret = client.SendSmallFile(filePath, myFile, null); + if (ret == false) + { + isSendFile = false; + int error = client.SYSGetLastError(); + AddMsg(string.Format(" > [SendSmallFile] errorCode:{0}", error)); + } + + return ret; + } + + HandleResult OnPrepareConnect(IntPtr dwConnId, uint socket) + { + return HandleResult.Ok; + } + + HandleResult OnConnect(IntPtr dwConnId) + { + // 已连接 到达一次 + + // 如果是异步联接,更新界面状态 + this.Invoke(new ConnectUpdateUiDelegate(ConnectUpdateUi)); + + AddMsg(string.Format(" > [{0},OnConnect]", dwConnId)); + + return HandleResult.Ok; + } + + HandleResult OnSend(IntPtr dwConnId, IntPtr pData, int iLength) + { + // 客户端发数据了 + AddMsg(string.Format(" > [{0},OnSend] -> ({1} bytes)", dwConnId, iLength)); + + return HandleResult.Ok; + } + + HandleResult OnReceive(IntPtr dwConnId, IntPtr pData, int iLength) + { + // 数据到达了 + if (isSendFile == true) + { + // 如果发送了文件,并接收到了返回数据 + isSendFile = false; + MyFileInfo myFile = (MyFileInfo)Marshal.PtrToStructure(pData, typeof(MyFileInfo)); + int objSize = Marshal.SizeOf(myFile); + // 因为没有附加尾数据,所以大小可以用iLength - objSize + byte[] bytes = new byte[iLength - objSize]; + Marshal.Copy(pData + objSize, bytes, 0, iLength - objSize); + + string txt = Encoding.Default.GetString(bytes); + string msg = string.Empty; + if (txt.Length > 100) + { + msg = txt.Substring(0, 100) + "......"; + } + else + { + msg = txt; + } + + AddMsg(string.Format(" > [{0},OnReceive] -> FileInfo(Path:\"{1}\",Size:{2})", dwConnId, myFile.FilePath, myFile.FileSize)); + AddMsg(string.Format(" > [{0},OnReceive] -> FileContent(\"{1}\")", dwConnId, msg)); + } + else if (studentType != StudentType.None) + { + byte[] bytes = new byte[iLength]; + Marshal.Copy(pData, bytes, 0, iLength); + + switch (studentType) + { + case StudentType.Array: + Student[] students = client.BytesToObject(bytes) as Student[]; + foreach (var stu in students) + { + AddMsg(string.Format(" > [{0},OnReceive] -> Student({1},{2},{3})", dwConnId, stu.Id, stu.Name, stu.GetSexString())); + } + break; + case StudentType.List: + List stuList = client.BytesToObject(bytes) as List; + foreach (var stu in stuList) + { + AddMsg(string.Format(" > [{0},OnReceive] -> Student({1},{2},{3})", dwConnId, stu.Id, stu.Name, stu.GetSexString())); + } + break; + case StudentType.Single: + Student student = client.BytesToObject(bytes) as Student; + AddMsg(string.Format(" > [{0},OnReceive] -> Student({1},{2},{3})", dwConnId, student.Id, student.Name, student.GetSexString())); + studentType = StudentType.None; + break; + } + } + else + { + AddMsg(string.Format(" > [{0},OnReceive] -> ({1} bytes)", dwConnId, iLength)); + } + + return HandleResult.Ok; + } + + HandleResult OnClose(IntPtr dwConnId) + { + // 连接关闭了 + + AddMsg(string.Format(" > [{0},OnClose]", dwConnId)); + + // 通知界面 + this.Invoke(new SetAppStateDelegate(SetAppState), AppState.Stoped); + return HandleResult.Ok; + } + + HandleResult OnError(IntPtr dwConnId, SocketOperation enOperation, int iErrorCode) + { + // 出错了 + + AddMsg(string.Format(" > [{0},OnError] -> OP:{1},CODE:{2}", dwConnId, enOperation, iErrorCode)); + + // 通知界面,只处理了连接错误,也没进行是不是连接错误的判断,所以有错误就会设置界面 + // 生产环境请自己控制 + this.Invoke(new SetAppStateDelegate(SetAppState), AppState.Stoped); + + return HandleResult.Ok; + } + + /// + /// 设置程序状态 + /// + /// + void SetAppState(AppState state) + { + appState = state; + this.btnStart.Enabled = (appState == AppState.Stoped); + this.btnStop.Enabled = (appState == AppState.Started); + this.txtIpAddress.Enabled = (appState == AppState.Stoped); + this.txtPort.Enabled = (appState == AppState.Stoped); + this.cbxAsyncConn.Enabled = (appState == AppState.Stoped); + this.btnSend.Enabled = (appState == AppState.Started); + this.btnSendFile.Enabled = (appState == AppState.Started); + this.btnSendSerializableObject.Enabled = (appState == AppState.Started); + } + + /// + /// 往listbox加一条项目 + /// + /// + void AddMsg(string msg) + { + if (this.lbxMsg.InvokeRequired) + { + // 很帅的调自己 + this.lbxMsg.Invoke(AddMsgDelegate, msg); + } + else + { + if (this.lbxMsg.Items.Count > 100) + { + this.lbxMsg.Items.RemoveAt(0); + } + this.lbxMsg.Items.Add(msg); + this.lbxMsg.TopIndex = this.lbxMsg.Items.Count - (int)(this.lbxMsg.Height / this.lbxMsg.ItemHeight); + } + } + + private void frmClient_FormClosed(object sender, FormClosedEventArgs e) + { + client.Destroy(); + } + + + + private void btnSendFile_Click(object sender, EventArgs e) + { + try + { + + OpenFileDialog ofd = new OpenFileDialog(); + // ofd.InitialDirectory = "c:\\" ; + //ofd.Filter = "txt files (*.txt)|*.txt|All files (*.*)|*.*"; + ofd.Filter = "txt files (*.txt)|*.txt"; + ofd.RestoreDirectory = true; + ofd.CheckFileExists = true; + ofd.CheckPathExists = true; + if (ofd.ShowDialog() == DialogResult.OK) + { + SendFileToServer(ofd.FileName); + } + } + catch (Exception ex) + { + MessageBox.Show(ex.Message); + + } + } + + } + + [StructLayout(LayoutKind.Sequential, Pack = 1)] + public struct MyFileInfo + { + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 255)] + public string FilePath; + public long FileSize; + } + + /// + /// 学员性别 + /// + public enum Sex + { + /// + /// 男 + /// + Male = 1, + + /// + /// 女 + /// + Female = 2, + + /// + /// 变性人 + /// + Transsexual = 3, + + /// + /// 未知 + /// + Unknown = 4, + + } + + /// + /// 学员类 + /// + [Serializable] + public class Student + { + /// + /// 编号 + /// + public int Id { get; set; } + + /// + /// 姓名 + /// + public string Name { get; set; } + + /// + /// 性别 + /// + public Sex Sex { get; set; } + + public string GetSexString() + { + string sex = string.Empty; + switch (Sex) + { + case Sex.Male: + sex = "男"; + break; + case Sex.Female: + sex = "女"; + break; + case Sex.Transsexual: + sex = "变性人"; + break; + default: + sex = "未知"; + break; + } + return sex; + } + } +} diff --git a/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpClient/frmClient.resx b/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpClient/frmClient.resx new file mode 100644 index 000000000..1af7de150 --- /dev/null +++ b/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpClient/frmClient.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpProxyServer/Program.cs b/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpProxyServer/Program.cs new file mode 100644 index 000000000..3f5e79fc1 --- /dev/null +++ b/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpProxyServer/Program.cs @@ -0,0 +1,21 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Windows.Forms; + +namespace TcpProxyServer +{ + static class Program + { + /// + /// 应用程序的主入口点。 + /// + [STAThread] + static void Main() + { + Application.EnableVisualStyles(); + Application.SetCompatibleTextRenderingDefault(false); + Application.Run(new frmProxyServer()); + } + } +} diff --git a/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpProxyServer/Properties/AssemblyInfo.cs b/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpProxyServer/Properties/AssemblyInfo.cs new file mode 100644 index 000000000..7208514cc --- /dev/null +++ b/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpProxyServer/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// 有关程序集的常规信息通过以下 +// 特性集控制。更改这些特性值可修改 +// 与程序集关联的信息。 +[assembly: AssemblyTitle("TcpProxyServer")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("TcpProxyServer")] +[assembly: AssemblyCopyright("Copyright © 2014")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// 将 ComVisible 设置为 false 使此程序集中的类型 +// 对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型, +// 则将该类型上的 ComVisible 特性设置为 true。 +[assembly: ComVisible(false)] + +// 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID +[assembly: Guid("83e0db2e-c90a-4cd6-871e-83181027b537")] + +// 程序集的版本信息由下面四个值组成: +// +// 主版本 +// 次版本 +// 内部版本号 +// 修订号 +// +// 可以指定所有这些值,也可以使用“内部版本号”和“修订号”的默认值, +// 方法是按如下所示使用“*”: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpProxyServer/Properties/Resources.Designer.cs b/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpProxyServer/Properties/Resources.Designer.cs new file mode 100644 index 000000000..9869c2499 --- /dev/null +++ b/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpProxyServer/Properties/Resources.Designer.cs @@ -0,0 +1,71 @@ +//------------------------------------------------------------------------------ +// +// 此代码由工具生成。 +// 运行时版本: 4.0.30319.18444 +// +// 对此文件的更改可能会导致不正确的行为,并且如果 +// 重新生成代码,这些更改将丢失。 +// +//------------------------------------------------------------------------------ + +namespace TcpProxyServer.Properties +{ + + + /// + /// 一个强类型的资源类,用于查找本地化的字符串等。 + /// + // 此类是由 StronglyTypedResourceBuilder + // 类通过类似于 ResGen 或 Visual Studio 的工具自动生成的。 + // 若要添加或移除成员,请编辑 .ResX 文件,然后重新运行 ResGen + // (以 /str 作为命令选项),或重新生成 VS 项目。 + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources + { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() + { + } + + /// + /// 返回此类使用的、缓存的 ResourceManager 实例。 + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager + { + get + { + if ((resourceMan == null)) + { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("TcpProxyServer.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// 为所有资源查找重写当前线程的 CurrentUICulture 属性, + /// 方法是使用此强类型资源类。 + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture + { + get + { + return resourceCulture; + } + set + { + resourceCulture = value; + } + } + } +} diff --git a/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpProxyServer/Properties/Resources.resx b/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpProxyServer/Properties/Resources.resx new file mode 100644 index 000000000..af7dbebba --- /dev/null +++ b/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpProxyServer/Properties/Resources.resx @@ -0,0 +1,117 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpProxyServer/Properties/Settings.Designer.cs b/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpProxyServer/Properties/Settings.Designer.cs new file mode 100644 index 000000000..e79e77e2d --- /dev/null +++ b/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpProxyServer/Properties/Settings.Designer.cs @@ -0,0 +1,30 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.18444 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace TcpProxyServer.Properties +{ + + + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "10.0.0.0")] + internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase + { + + private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); + + public static Settings Default + { + get + { + return defaultInstance; + } + } + } +} diff --git a/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpProxyServer/Properties/Settings.settings b/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpProxyServer/Properties/Settings.settings new file mode 100644 index 000000000..39645652a --- /dev/null +++ b/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpProxyServer/Properties/Settings.settings @@ -0,0 +1,7 @@ + + + + + + + diff --git a/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpProxyServer/ProxyServer.cs b/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpProxyServer/ProxyServer.cs new file mode 100644 index 000000000..b52b1087d --- /dev/null +++ b/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpProxyServer/ProxyServer.cs @@ -0,0 +1,415 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using HPSocketCS; +using System.Runtime.InteropServices; + +namespace TcpProxyServer +{ + public class ProxyServer + { + /// + /// 绑定地址 + /// + public string BindAddr { get; set; } + + /// + /// 绑定端口 + /// + public ushort BindPort { get; set; } + + /// + /// 目标地址 + /// + public string TargetAddr { get; set; } + + /// + /// 目标端口 + /// + public ushort TargetPort { get; set; } + + // 为了简单直接定义了一个支持log输出的委托 + public delegate void ShowMsg(string msg); + /// + /// 日志输出 + /// + public ShowMsg AddMsgDelegate; + + protected TcpServer server = new TcpServer(); + protected TcpAgent agent = new TcpAgent(); + + + public ProxyServer() + { + server.SetCallback(OnServerPrepareListen, OnServerAccept, OnServerSend, OnServerReceive, OnServerClose, + OnServerError, OnServerShutdown); + + agent.SetCallback(OnAgentPrepareConnect, OnAgentConnect, OnAgentSend, OnAgentReceive, OnAgentClose, + OnAgentError, OnAgentShutdown); + } + + public bool Start() + { + if (string.IsNullOrEmpty(BindAddr) || string.IsNullOrEmpty(TargetAddr) || + BindPort == 0 || TargetPort == 0 || AddMsgDelegate == null) + { + throw new Exception("请先设置属性[BindAddr,TargetAddr,BindPort,TargetPort,AddMsgDelegate]"); + } + + bool isStart = server.Start(BindAddr, BindPort); + if (isStart == false) + { + AddMsg(string.Format(" > Server start fail -> {0}({1})", server.GetLastErrorDesc(), server.GetlastError())); + return isStart; + } + + isStart = agent.Start(BindAddr, false); + if (isStart == false) + { + AddMsg(string.Format(" > Server start fail -> {0}({1})", agent.GetLastErrorDesc(), agent.GetlastError())); + return isStart; + } + + return isStart; + } + + public bool Stop() + { + return server.Stop() && agent.Stop(); + } + + private void AddMsg(string msg) + { + AddMsgDelegate(msg); + } + + + public bool Disconnect(IntPtr dwConnId, bool force = true) + { + return server.Disconnect(dwConnId, force); + } + + //////////////////////////////Agent////////////////////////////////////////////////// + + /// + /// 准备连接了 + /// + /// + /// + /// + protected virtual HandleResult OnAgentPrepareConnect(IntPtr dwConnId, uint socket) + { + return HandleResult.Ok; + } + + /// + /// 已连接 + /// + /// + /// + protected virtual HandleResult OnAgentConnect(IntPtr dwConnId) + { + AddMsg(string.Format(" > [{0},OnAgentConnect]", dwConnId)); + return HandleResult.Ok; + } + + /// + /// 客户端发数据了 + /// + /// + /// + /// + /// + protected virtual HandleResult OnAgentSend(IntPtr dwConnId, IntPtr pData, int iLength) + { + AddMsg(string.Format(" > [{0},OnAgentSend] -> ({1} bytes)", dwConnId, iLength)); + return HandleResult.Ok; + } + + /// + /// 数据到达了 + /// + /// + /// + /// + /// + protected virtual HandleResult OnAgentReceive(IntPtr dwConnId, IntPtr pData, int iLength) + { + // 获取附加数据 + IntPtr extraPtr = IntPtr.Zero; + if (agent.GetConnectionExtra(dwConnId, ref extraPtr) == false) + { + return HandleResult.Error; + } + + ConnExtraData extra = (ConnExtraData)Marshal.PtrToStructure(extraPtr, typeof(ConnExtraData)); + AddMsg(string.Format(" > [{0},OnAgentReceive] -> ({1} bytes)", dwConnId, iLength)); + if (extra.Server.Send(extra.ConnIdForServer, pData, iLength) == false) + { + return HandleResult.Error; + } + + return HandleResult.Ok; + } + + /// + /// 连接关闭了 + /// + /// + /// + protected virtual HandleResult OnAgentClose(IntPtr dwConnId) + { + AddMsg(string.Format(" > [{0},OnAgentClose]", dwConnId)); + + // 获取附加数据 + IntPtr extraPtr = IntPtr.Zero; + if (agent.GetConnectionExtra(dwConnId, ref extraPtr) == false) + { + return HandleResult.Error; + } + + ConnExtraData extra = (ConnExtraData)Marshal.PtrToStructure(extraPtr, typeof(ConnExtraData)); + + agent.SetConnectionExtra(dwConnId, null); + + if (extra.FreeType == 0) + { + + // 由Target断开连接,释放server连接 + extra.FreeType = 1; + server.SetConnectionExtra(extra.ConnIdForServer, extra); + extra.Server.Disconnect(extra.ConnIdForServer); + } + + + return HandleResult.Ok; + } + + /// + /// 出错了 + /// + /// + /// + /// + /// + protected virtual HandleResult OnAgentError(IntPtr dwConnId, SocketOperation enOperation, int iErrorCode) + { + AddMsg(string.Format(" > [{0},OnAgentError] -> OP:{1},CODE:{2}", dwConnId, enOperation, iErrorCode)); + // return HPSocketSdk.HandleResult.Ok; + + // 因为要释放附加数据,所以直接返回OnAgentClose()了 + return OnAgentClose(dwConnId); + } + + /// + /// Agent关闭了 + /// + /// + protected virtual HandleResult OnAgentShutdown() + { + AddMsg(" > [OnAgentShutdown]"); + return HandleResult.Ok; + } + + //////////////////////////////Server////////////////////////////////////////////////// + + /// + /// 监听事件 + /// + /// + /// + protected virtual HandleResult OnServerPrepareListen(IntPtr soListen) + { + return HandleResult.Ok; + } + + /// + /// 客户进入 + /// + /// + /// + /// + protected virtual HandleResult OnServerAccept(IntPtr dwConnId, IntPtr pClient) + { + // 获取客户端ip和端口 + string ip = string.Empty; + ushort port = 0; + if (server.GetRemoteAddress(dwConnId, ref ip, ref port)) + { + AddMsg(string.Format(" > [{0},OnServerAccept] -> PASS({1}:{2})", dwConnId, ip.ToString(), port)); + } + else + { + AddMsg(string.Format(" > [{0},OnServerAccept] -> Server_GetClientAddress() Error", dwConnId)); + return HandleResult.Error; + } + + IntPtr clientConnId = IntPtr.Zero; + + // 一次不成功的事偶尔可能发生,三次连接都不成功,那就真连不上了 + // 当server有连接进入,使用agent连接到目标服务器 + if (agent.Connect(TargetAddr, TargetPort, ref clientConnId) == false) + { + if (agent.Connect(TargetAddr, TargetPort, ref clientConnId) == false) + { + if (agent.Connect(TargetAddr, TargetPort, ref clientConnId) == false) + { + AddMsg(string.Format(" > [Client->Connect] fail -> ID:{0}", clientConnId)); + return HandleResult.Error; + } + } + } + + + // 设置附加数据 + ConnExtraData extra = new ConnExtraData(); + extra.ConnIdForServer = dwConnId; + extra.ConnIdForClient = clientConnId; + extra.Server = server; + extra.FreeType = 0; + if (server.SetConnectionExtra(dwConnId, extra) == false) + { + AddMsg(string.Format(" > [{0},OnServerAccept] -> server.SetConnectionExtra fail", dwConnId)); + return HandleResult.Error; + } + + if (agent.SetConnectionExtra(clientConnId, extra) == false) + { + server.SetConnectionExtra(dwConnId, null); + AddMsg(string.Format(" > [{0}-{1},OnServerAccept] -> agent.SetConnectionExtra fail", dwConnId, clientConnId)); + return HandleResult.Error; + } + + return HandleResult.Ok; + } + + /// + /// 服务器发数据了 + /// + /// + /// + /// + /// + protected virtual HandleResult OnServerSend(IntPtr dwConnId, IntPtr pData, int iLength) + { + AddMsg(string.Format(" > [Server->OnServerSend] -> ({0} bytes)", iLength)); + return HandleResult.Ok; + } + + /// + /// 数据到达了 + /// + /// + /// + /// + /// + protected virtual HandleResult OnServerReceive(IntPtr dwConnId, IntPtr pData, int iLength) + { + + try + { + // 获取附加数据 + IntPtr extraPtr = IntPtr.Zero; + + if (server.GetConnectionExtra(dwConnId, ref extraPtr) == false) + { + return HandleResult.Error; + } + + // extra 就是accept里传入的附加数据了 + ConnExtraData extra = (ConnExtraData)Marshal.PtrToStructure(extraPtr, typeof(ConnExtraData)); + + AddMsg(string.Format(" > [Server->OnServerReceive] -> ({0} bytes)", iLength)); + + // 服务端收到数据了,应该调用agent发送到顶层服务器,实现 client(N)->server->targetServer 的中转 + if (agent.Send(extra.ConnIdForClient, pData, iLength) == false) + { + return HandleResult.Error; + } + + return HandleResult.Ok; + + } + catch (Exception) + { + return HandleResult.Error; + } + + } + + /// + /// 客户离开了 + /// + /// + /// + protected virtual HandleResult OnServerClose(IntPtr dwConnId) + { + // 获取附加数据 + IntPtr extraPtr = IntPtr.Zero; + if (server.GetConnectionExtra(dwConnId, ref extraPtr) == false) + { + return HandleResult.Error; + } + + // extra 就是accept里传入的附加数据了 + ConnExtraData extra = (ConnExtraData)Marshal.PtrToStructure(extraPtr, typeof(ConnExtraData)); + if (extra.FreeType == 0) + { + // 由client(N)断开连接,释放agent数据 + agent.Disconnect(extra.ConnIdForClient); + agent.SetConnectionExtra(extra.ConnIdForClient, null); + } + + server.SetConnectionExtra(dwConnId, null); + + AddMsg(string.Format(" > [{0},OnServerClose]", dwConnId)); + return HandleResult.Ok; + } + + /// + /// 出错了 + /// + /// + /// + /// + /// + protected virtual HandleResult OnServerError(IntPtr dwConnId, SocketOperation enOperation, int iErrorCode) + { + AddMsg(string.Format(" > [{0},OnServerError] -> OP:{1},CODE:{2}", dwConnId, enOperation, iErrorCode)); + // return HPSocketSdk.HandleResult.Ok; + + // 因为要释放附加数据,所以直接返回OnServerClose()了 + return OnServerClose(dwConnId); + } + + /// + /// 服务关闭了 + /// + /// + protected virtual HandleResult OnServerShutdown() + { + AddMsg(" > [OnServerShutdown]"); + return HandleResult.Ok; + } + + //////////////////////////////////////////////////////////////////////////////// + } + + + [StructLayout(LayoutKind.Sequential)] + public class ConnExtraData + { + // server的CONNID + public IntPtr ConnIdForServer; + + // client的CONNID + public IntPtr ConnIdForClient; + + // 保存server端指针,方便在cclient里调用 + public TcpServer Server; + + // 释放方式 + public uint FreeType; + } +} diff --git a/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpProxyServer/TcpProxyServer.csproj b/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpProxyServer/TcpProxyServer.csproj new file mode 100644 index 000000000..b38a14435 --- /dev/null +++ b/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpProxyServer/TcpProxyServer.csproj @@ -0,0 +1,122 @@ + + + + Debug + x86 + 8.0.30703 + 2.0 + {5FEB9E6D-2526-4F4F-957C-093D7FFB9B98} + WinExe + Properties + TcpProxyServer + TcpProxyServer + v4.0 + Client + 512 + + + x86 + true + full + false + ..\bin\x86\Debug\ + DEBUG;TRACE + prompt + 4 + + + x86 + pdbonly + true + ..\bin\x86\Release\ + TRACE + prompt + 4 + + + true + ..\bin\x64\Debug\ + DEBUG;TRACE + full + x64 + ..\bin\Debug\TcpProxyServer.exe.CodeAnalysisLog.xml + true + GlobalSuppressions.cs + prompt + MinimumRecommendedRules.ruleset + ;D:\Program Files\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets + ;D:\Program Files\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules + + + ..\bin\x64\Release\ + TRACE + true + pdbonly + x64 + ..\bin\Release\TcpProxyServer.exe.CodeAnalysisLog.xml + true + GlobalSuppressions.cs + prompt + MinimumRecommendedRules.ruleset + ;D:\Program Files\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets + ;D:\Program Files\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules + + + + + + + + + + + + + + + + Form + + + frmProxyServer.cs + + + + + + frmProxyServer.cs + + + ResXFileCodeGenerator + Resources.Designer.cs + Designer + + + True + Resources.resx + + + SettingsSingleFileGenerator + Settings.Designer.cs + + + True + Settings.settings + True + + + + + {DFA935E2-CF37-4E26-B697-D7F3DEE19DD8} + HPSocketCS + + + + + \ No newline at end of file diff --git a/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpProxyServer/frmProxyServer.Designer.cs b/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpProxyServer/frmProxyServer.Designer.cs new file mode 100644 index 000000000..c407ebf67 --- /dev/null +++ b/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpProxyServer/frmProxyServer.Designer.cs @@ -0,0 +1,198 @@ +namespace TcpProxyServer +{ + partial class frmProxyServer + { + /// + /// 必需的设计器变量。 + /// + private System.ComponentModel.IContainer components = null; + + /// + /// 清理所有正在使用的资源。 + /// + /// 如果应释放托管资源,为 true;否则为 false。 + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows 窗体设计器生成的代码 + + /// + /// 设计器支持所需的方法 - 不要 + /// 使用代码编辑器修改此方法的内容。 + /// + private void InitializeComponent() + { + this.lbxMsg = new System.Windows.Forms.ListBox(); + this.label1 = new System.Windows.Forms.Label(); + this.label2 = new System.Windows.Forms.Label(); + this.txtBindAddr = new System.Windows.Forms.TextBox(); + this.txtTargetAddr = new System.Windows.Forms.TextBox(); + this.txtBindPort = new System.Windows.Forms.TextBox(); + this.txtTargetPort = new System.Windows.Forms.TextBox(); + this.label3 = new System.Windows.Forms.Label(); + this.txtDisConn = new System.Windows.Forms.TextBox(); + this.btnDisconn = new System.Windows.Forms.Button(); + this.btnStart = new System.Windows.Forms.Button(); + this.btnStop = new System.Windows.Forms.Button(); + this.SuspendLayout(); + // + // lbxMsg + // + this.lbxMsg.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.lbxMsg.FormattingEnabled = true; + this.lbxMsg.ItemHeight = 12; + this.lbxMsg.Location = new System.Drawing.Point(1, 1); + this.lbxMsg.Name = "lbxMsg"; + this.lbxMsg.Size = new System.Drawing.Size(474, 304); + this.lbxMsg.TabIndex = 5; + this.lbxMsg.KeyPress += new System.Windows.Forms.KeyPressEventHandler(this.lbxMsg_KeyPress); + // + // label1 + // + this.label1.AutoSize = true; + this.label1.Location = new System.Drawing.Point(12, 319); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(41, 12); + this.label1.TabIndex = 6; + this.label1.Text = "Local:"; + // + // label2 + // + this.label2.AutoSize = true; + this.label2.Location = new System.Drawing.Point(6, 341); + this.label2.Name = "label2"; + this.label2.Size = new System.Drawing.Size(47, 12); + this.label2.TabIndex = 7; + this.label2.Text = "Target:"; + // + // txtBindAddr + // + this.txtBindAddr.Location = new System.Drawing.Point(60, 316); + this.txtBindAddr.Name = "txtBindAddr"; + this.txtBindAddr.Size = new System.Drawing.Size(100, 21); + this.txtBindAddr.TabIndex = 8; + this.txtBindAddr.Text = "0.0.0.0"; + // + // txtTargetAddr + // + this.txtTargetAddr.Location = new System.Drawing.Point(60, 343); + this.txtTargetAddr.Name = "txtTargetAddr"; + this.txtTargetAddr.Size = new System.Drawing.Size(100, 21); + this.txtTargetAddr.TabIndex = 9; + this.txtTargetAddr.Text = "127.0.0.1"; + // + // txtBindPort + // + this.txtBindPort.Location = new System.Drawing.Point(166, 316); + this.txtBindPort.Name = "txtBindPort"; + this.txtBindPort.Size = new System.Drawing.Size(48, 21); + this.txtBindPort.TabIndex = 10; + this.txtBindPort.Text = "7000"; + // + // txtTargetPort + // + this.txtTargetPort.Location = new System.Drawing.Point(166, 343); + this.txtTargetPort.Name = "txtTargetPort"; + this.txtTargetPort.Size = new System.Drawing.Size(48, 21); + this.txtTargetPort.TabIndex = 11; + this.txtTargetPort.Text = "5555"; + // + // label3 + // + this.label3.AutoSize = true; + this.label3.Location = new System.Drawing.Point(221, 336); + this.label3.Name = "label3"; + this.label3.Size = new System.Drawing.Size(47, 12); + this.label3.TabIndex = 12; + this.label3.Text = "CONNID:"; + // + // txtDisConn + // + this.txtDisConn.Location = new System.Drawing.Point(274, 332); + this.txtDisConn.Name = "txtDisConn"; + this.txtDisConn.Size = new System.Drawing.Size(47, 21); + this.txtDisConn.TabIndex = 13; + this.txtDisConn.TextChanged += new System.EventHandler(this.txtDisConn_TextChanged); + // + // btnDisconn + // + this.btnDisconn.Location = new System.Drawing.Point(328, 331); + this.btnDisconn.Name = "btnDisconn"; + this.btnDisconn.Size = new System.Drawing.Size(61, 23); + this.btnDisconn.TabIndex = 14; + this.btnDisconn.Text = "Dis conn"; + this.btnDisconn.UseVisualStyleBackColor = true; + this.btnDisconn.Click += new System.EventHandler(this.btnDisconn_Click); + // + // btnStart + // + this.btnStart.Location = new System.Drawing.Point(412, 314); + this.btnStart.Name = "btnStart"; + this.btnStart.Size = new System.Drawing.Size(61, 23); + this.btnStart.TabIndex = 15; + this.btnStart.Text = "Start"; + this.btnStart.UseVisualStyleBackColor = true; + this.btnStart.Click += new System.EventHandler(this.btnStart_Click); + // + // btnStop + // + this.btnStop.Location = new System.Drawing.Point(412, 343); + this.btnStop.Name = "btnStop"; + this.btnStop.Size = new System.Drawing.Size(61, 23); + this.btnStop.TabIndex = 16; + this.btnStop.Text = "Stop"; + this.btnStop.UseVisualStyleBackColor = true; + this.btnStop.Click += new System.EventHandler(this.btnStop_Click); + // + // frmProxyServer + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(475, 370); + this.Controls.Add(this.btnStop); + this.Controls.Add(this.btnStart); + this.Controls.Add(this.btnDisconn); + this.Controls.Add(this.txtDisConn); + this.Controls.Add(this.label3); + this.Controls.Add(this.txtTargetPort); + this.Controls.Add(this.txtBindPort); + this.Controls.Add(this.txtTargetAddr); + this.Controls.Add(this.txtBindAddr); + this.Controls.Add(this.label2); + this.Controls.Add(this.label1); + this.Controls.Add(this.lbxMsg); + this.Name = "frmProxyServer"; + this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen; + this.Text = "ProxyServer [ \'C\' - clear list box ]"; + this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.frmProxyServer_FormClosing); + this.Load += new System.EventHandler(this.Form1_Load); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.ListBox lbxMsg; + private System.Windows.Forms.Label label1; + private System.Windows.Forms.Label label2; + private System.Windows.Forms.TextBox txtBindAddr; + private System.Windows.Forms.TextBox txtTargetAddr; + private System.Windows.Forms.TextBox txtBindPort; + private System.Windows.Forms.TextBox txtTargetPort; + private System.Windows.Forms.Label label3; + private System.Windows.Forms.TextBox txtDisConn; + private System.Windows.Forms.Button btnDisconn; + private System.Windows.Forms.Button btnStart; + private System.Windows.Forms.Button btnStop; + } +} + diff --git a/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpProxyServer/frmProxyServer.cs b/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpProxyServer/frmProxyServer.cs new file mode 100644 index 000000000..d4653281d --- /dev/null +++ b/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpProxyServer/frmProxyServer.cs @@ -0,0 +1,183 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Windows.Forms; + +namespace TcpProxyServer +{ + public enum AppState + { + Starting, Started, Stoping, Stoped, Error + } + + public partial class frmProxyServer : Form + { + private AppState appState = AppState.Stoped; + + private delegate void ShowMsg(string msg); + private ShowMsg AddMsgDelegate; + + private ProxyServer proxyServer = null; + + + public frmProxyServer() + { + InitializeComponent(); + } + + private void Form1_Load(object sender, EventArgs e) + { + try + { + proxyServer = new ProxyServer(); + + // 加个委托显示msg,因为on系列都是在工作线程中调用的,ui不允许直接操作 + AddMsgDelegate = new ShowMsg(AddMsg); + + proxyServer.AddMsgDelegate = new ProxyServer.ShowMsg(AddMsg); + + SetAppState(AppState.Stoped); + } + catch (Exception ex) + { + SetAppState(AppState.Error); + AddMsg(ex.Message); + } + } + + /// + /// 往listbox加一条项目 + /// + /// + void AddMsg(string msg) + { + if (this.lbxMsg.InvokeRequired) + { + // 很帅的调自己 + this.lbxMsg.Invoke(AddMsgDelegate, msg); + } + else + { + if (this.lbxMsg.Items.Count > 100) + { + this.lbxMsg.Items.RemoveAt(0); + } + this.lbxMsg.Items.Add(msg); + this.lbxMsg.TopIndex = this.lbxMsg.Items.Count - (int)(this.lbxMsg.Height / this.lbxMsg.ItemHeight); + } + } + + + /// + /// 设置程序状态 + /// + /// + void SetAppState(AppState state) + { + appState = state; + this.btnStart.Enabled = (appState == AppState.Stoped); + this.btnStop.Enabled = (appState == AppState.Started); + this.txtBindAddr.Enabled = (appState == AppState.Stoped); + this.txtBindPort.Enabled = (appState == AppState.Stoped); + this.txtTargetAddr.Enabled = (appState == AppState.Stoped); + this.txtTargetPort.Enabled = (appState == AppState.Stoped); + this.txtDisConn.Enabled = (appState == AppState.Started); + this.btnDisconn.Enabled = (appState == AppState.Started && this.txtDisConn.Text.Length > 0); + } + + private void txtDisConn_TextChanged(object sender, EventArgs e) + { + // CONNID框被改变事件 + this.btnDisconn.Enabled = (appState == AppState.Started && this.txtDisConn.Text.Length > 0); + } + + private void lbxMsg_KeyPress(object sender, KeyPressEventArgs e) + { + // 清理listbox + if (e.KeyChar == 'c' || e.KeyChar == 'C') + { + this.lbxMsg.Items.Clear(); + } + } + + private void btnStart_Click(object sender, EventArgs e) + { + try + { + proxyServer.BindAddr = this.txtBindAddr.Text.Trim(); + proxyServer.BindPort = ushort.Parse(this.txtBindPort.Text.Trim()); + proxyServer.TargetAddr = this.txtTargetAddr.Text.Trim(); + proxyServer.TargetPort = ushort.Parse(this.txtTargetPort.Text.Trim()); + + // 写在这个位置是上面可能会异常 + SetAppState(AppState.Starting); + + // 启动服务 + if (proxyServer.Start()) + { + SetAppState(AppState.Started); + throw new Exception(string.Format("$Server Start OK -> ({0}:{1}->{2}:{3})", + proxyServer.BindAddr, proxyServer.BindPort, + proxyServer.TargetAddr, proxyServer.TargetPort)); + } + else + { + SetAppState(AppState.Stoped); + } + } + catch (Exception ex) + { + AddMsg(ex.Message); + } + } + + private void btnDisconn_Click(object sender, EventArgs e) + { + try + { + // 未做64位判断 + IntPtr dwConnId = (IntPtr)Convert.ToUInt32(this.txtDisConn.Text.Trim()); + + // 断开指定客户 + if (proxyServer.Disconnect(dwConnId)) + { + AddMsg(string.Format("$({0}) Disconnect OK", dwConnId)); + } + else + { + throw new Exception(string.Format("Disconnect({0}) Error", dwConnId)); + } + } + catch (Exception ex) + { + AddMsg(ex.Message); + } + } + private void btnStop_Click(object sender, EventArgs e) + { + SetAppState(AppState.Stoping); + + // 停止服务 + AddMsg("$Server Stop"); + if (proxyServer.Stop()) + { + SetAppState(AppState.Stoped); + } + else + { + AddMsg("$Stop Error"); + } + } + + private void frmProxyServer_FormClosing(object sender, FormClosingEventArgs e) + { + proxyServer.Stop(); + } + + } + +} diff --git a/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpProxyServer/frmProxyServer.resx b/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpProxyServer/frmProxyServer.resx new file mode 100644 index 000000000..1af7de150 --- /dev/null +++ b/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpProxyServer/frmProxyServer.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpPullClient/Program.cs b/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpPullClient/Program.cs new file mode 100644 index 000000000..b68512802 --- /dev/null +++ b/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpPullClient/Program.cs @@ -0,0 +1,21 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Windows.Forms; + +namespace TcpPullClient +{ + static class Program + { + /// + /// 应用程序的主入口点。 + /// + [STAThread] + static void Main() + { + Application.EnableVisualStyles(); + Application.SetCompatibleTextRenderingDefault(false); + Application.Run(new frmClient()); + } + } +} diff --git a/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpPullClient/Properties/AssemblyInfo.cs b/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpPullClient/Properties/AssemblyInfo.cs new file mode 100644 index 000000000..547a67069 --- /dev/null +++ b/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpPullClient/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// 有关程序集的常规信息通过以下 +// 特性集控制。更改这些特性值可修改 +// 与程序集关联的信息。 +[assembly: AssemblyTitle("Client")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("Client")] +[assembly: AssemblyCopyright("Copyright © 2014")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// 将 ComVisible 设置为 false 使此程序集中的类型 +// 对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型, +// 则将该类型上的 ComVisible 特性设置为 true。 +[assembly: ComVisible(false)] + +// 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID +[assembly: Guid("0b4a498a-774e-4250-bf80-a05682b557fb")] + +// 程序集的版本信息由下面四个值组成: +// +// 主版本 +// 次版本 +// 内部版本号 +// 修订号 +// +// 可以指定所有这些值,也可以使用“内部版本号”和“修订号”的默认值, +// 方法是按如下所示使用“*”: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpPullClient/Properties/Resources.Designer.cs b/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpPullClient/Properties/Resources.Designer.cs new file mode 100644 index 000000000..045c0a15d --- /dev/null +++ b/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpPullClient/Properties/Resources.Designer.cs @@ -0,0 +1,63 @@ +//------------------------------------------------------------------------------ +// +// 此代码由工具生成。 +// 运行时版本:4.0.30319.18444 +// +// 对此文件的更改可能会导致不正确的行为,并且如果 +// 重新生成代码,这些更改将会丢失。 +// +//------------------------------------------------------------------------------ + +namespace TcpPullClient.Properties { + using System; + + + /// + /// 一个强类型的资源类,用于查找本地化的字符串等。 + /// + // 此类是由 StronglyTypedResourceBuilder + // 类通过类似于 ResGen 或 Visual Studio 的工具自动生成的。 + // 若要添加或移除成员,请编辑 .ResX 文件,然后重新运行 ResGen + // (以 /str 作为命令选项),或重新生成 VS 项目。 + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// + /// 返回此类使用的缓存的 ResourceManager 实例。 + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("TcpPullClient.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// 使用此强类型资源类,为所有资源查找 + /// 重写当前线程的 CurrentUICulture 属性。 + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + } +} diff --git a/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpPullClient/Properties/Resources.resx b/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpPullClient/Properties/Resources.resx new file mode 100644 index 000000000..af7dbebba --- /dev/null +++ b/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpPullClient/Properties/Resources.resx @@ -0,0 +1,117 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpPullClient/Properties/Settings.Designer.cs b/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpPullClient/Properties/Settings.Designer.cs new file mode 100644 index 000000000..7a49c3b7d --- /dev/null +++ b/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpPullClient/Properties/Settings.Designer.cs @@ -0,0 +1,26 @@ +//------------------------------------------------------------------------------ +// +// 此代码由工具生成。 +// 运行时版本:4.0.30319.18444 +// +// 对此文件的更改可能会导致不正确的行为,并且如果 +// 重新生成代码,这些更改将会丢失。 +// +//------------------------------------------------------------------------------ + +namespace TcpPullClient.Properties { + + + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "10.0.0.0")] + internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { + + private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); + + public static Settings Default { + get { + return defaultInstance; + } + } + } +} diff --git a/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpPullClient/Properties/Settings.settings b/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpPullClient/Properties/Settings.settings new file mode 100644 index 000000000..39645652a --- /dev/null +++ b/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpPullClient/Properties/Settings.settings @@ -0,0 +1,7 @@ + + + + + + + diff --git a/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpPullClient/TcpPullClient.csproj b/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpPullClient/TcpPullClient.csproj new file mode 100644 index 000000000..2f76aaf11 --- /dev/null +++ b/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpPullClient/TcpPullClient.csproj @@ -0,0 +1,127 @@ + + + + Debug + x86 + 8.0.30703 + 2.0 + {B9965E66-853A-47CC-B0C9-197B5A29ABFC} + WinExe + Properties + TcpPullClient + TcpPullClient + v4.0 + Client + 512 + + + x86 + true + full + false + ..\bin\x86\Debug\ + DEBUG;TRACE + prompt + 4 + + + x86 + pdbonly + true + ..\bin\x86\Release\ + TRACE + prompt + 4 + false + + + true + ..\bin\x64\Debug\ + DEBUG;TRACE + full + x64 + ..\bin\Debug\TcpPullClient.exe.CodeAnalysisLog.xml + true + GlobalSuppressions.cs + prompt + MinimumRecommendedRules.ruleset + ;D:\Program Files\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets + true + ;D:\Program Files\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules + true + + + ..\bin\x64\Release\ + TRACE + true + pdbonly + x64 + ..\bin\Release\TcpPullClient.exe.CodeAnalysisLog.xml + true + GlobalSuppressions.cs + prompt + MinimumRecommendedRules.ruleset + ;D:\Program Files\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets + true + ;D:\Program Files\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules + true + + + + + + + + + + + + + + + + Form + + + frmClient.cs + + + + + frmClient.cs + + + ResXFileCodeGenerator + Resources.Designer.cs + Designer + + + True + Resources.resx + True + + + SettingsSingleFileGenerator + Settings.Designer.cs + + + True + Settings.settings + True + + + + + {DFA935E2-CF37-4E26-B697-D7F3DEE19DD8} + HPSocketCS + + + + + \ No newline at end of file diff --git a/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpPullClient/frmClient.Designer.cs b/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpPullClient/frmClient.Designer.cs new file mode 100644 index 000000000..c28dc1769 --- /dev/null +++ b/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpPullClient/frmClient.Designer.cs @@ -0,0 +1,177 @@ +namespace TcpPullClient +{ + partial class frmClient + { + /// + /// 必需的设计器变量。 + /// + private System.ComponentModel.IContainer components = null; + + /// + /// 清理所有正在使用的资源。 + /// + /// 如果应释放托管资源,为 true;否则为 false。 + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows 窗体设计器生成的代码 + + /// + /// 设计器支持所需的方法 - 不要 + /// 使用代码编辑器修改此方法的内容。 + /// + private void InitializeComponent() + { + this.groupBox1 = new System.Windows.Forms.GroupBox(); + this.cbxAsyncConn = new System.Windows.Forms.CheckBox(); + this.txtPort = new System.Windows.Forms.TextBox(); + this.txtIpAddress = new System.Windows.Forms.TextBox(); + this.btnStop = new System.Windows.Forms.Button(); + this.btnStart = new System.Windows.Forms.Button(); + this.lbxMsg = new System.Windows.Forms.ListBox(); + this.txtSend = new System.Windows.Forms.TextBox(); + this.btnSend = new System.Windows.Forms.Button(); + this.groupBox1.SuspendLayout(); + this.SuspendLayout(); + // + // groupBox1 + // + this.groupBox1.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.groupBox1.Controls.Add(this.cbxAsyncConn); + this.groupBox1.Controls.Add(this.txtPort); + this.groupBox1.Controls.Add(this.txtIpAddress); + this.groupBox1.Controls.Add(this.btnStop); + this.groupBox1.Controls.Add(this.btnStart); + this.groupBox1.Location = new System.Drawing.Point(12, 2); + this.groupBox1.Name = "groupBox1"; + this.groupBox1.Size = new System.Drawing.Size(464, 47); + this.groupBox1.TabIndex = 11; + this.groupBox1.TabStop = false; + // + // cbxAsyncConn + // + this.cbxAsyncConn.AutoSize = true; + this.cbxAsyncConn.Checked = true; + this.cbxAsyncConn.CheckState = System.Windows.Forms.CheckState.Checked; + this.cbxAsyncConn.Location = new System.Drawing.Point(134, 20); + this.cbxAsyncConn.Name = "cbxAsyncConn"; + this.cbxAsyncConn.Size = new System.Drawing.Size(84, 16); + this.cbxAsyncConn.TabIndex = 13; + this.cbxAsyncConn.Text = "Async Conn"; + this.cbxAsyncConn.UseVisualStyleBackColor = true; + // + // txtPort + // + this.txtPort.Location = new System.Drawing.Point(88, 18); + this.txtPort.Name = "txtPort"; + this.txtPort.Size = new System.Drawing.Size(40, 21); + this.txtPort.TabIndex = 12; + this.txtPort.Text = "5555"; + // + // txtIpAddress + // + this.txtIpAddress.Location = new System.Drawing.Point(11, 18); + this.txtIpAddress.Name = "txtIpAddress"; + this.txtIpAddress.Size = new System.Drawing.Size(71, 21); + this.txtIpAddress.TabIndex = 11; + this.txtIpAddress.Text = "127.0.0.1"; + // + // btnStop + // + this.btnStop.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.btnStop.Location = new System.Drawing.Point(407, 15); + this.btnStop.Name = "btnStop"; + this.btnStop.Size = new System.Drawing.Size(47, 26); + this.btnStop.TabIndex = 10; + this.btnStop.Text = "Stop"; + this.btnStop.UseVisualStyleBackColor = true; + this.btnStop.Click += new System.EventHandler(this.btnStop_Click); + // + // btnStart + // + this.btnStart.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.btnStart.Location = new System.Drawing.Point(354, 15); + this.btnStart.Name = "btnStart"; + this.btnStart.Size = new System.Drawing.Size(47, 26); + this.btnStart.TabIndex = 9; + this.btnStart.Text = "Start"; + this.btnStart.UseVisualStyleBackColor = true; + this.btnStart.Click += new System.EventHandler(this.btnStart_Click); + // + // lbxMsg + // + this.lbxMsg.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.lbxMsg.FormattingEnabled = true; + this.lbxMsg.ItemHeight = 12; + this.lbxMsg.Location = new System.Drawing.Point(11, 62); + this.lbxMsg.Name = "lbxMsg"; + this.lbxMsg.Size = new System.Drawing.Size(465, 256); + this.lbxMsg.TabIndex = 10; + this.lbxMsg.KeyPress += new System.Windows.Forms.KeyPressEventHandler(this.lbxMsg_KeyPress); + // + // txtSend + // + this.txtSend.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.txtSend.Location = new System.Drawing.Point(12, 324); + this.txtSend.Name = "txtSend"; + this.txtSend.Size = new System.Drawing.Size(411, 21); + this.txtSend.TabIndex = 12; + this.txtSend.Text = "text to be sent"; + // + // btnSend + // + this.btnSend.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); + this.btnSend.Location = new System.Drawing.Point(429, 321); + this.btnSend.Name = "btnSend"; + this.btnSend.Size = new System.Drawing.Size(47, 26); + this.btnSend.TabIndex = 13; + this.btnSend.Text = "Send"; + this.btnSend.UseVisualStyleBackColor = true; + this.btnSend.Click += new System.EventHandler(this.btnSend_Click); + // + // frmClient + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(485, 350); + this.Controls.Add(this.btnSend); + this.Controls.Add(this.txtSend); + this.Controls.Add(this.groupBox1); + this.Controls.Add(this.lbxMsg); + this.Name = "frmClient"; + this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen; + this.Text = "Echo-TcpPullClient [ \'C\' - clear list box ]"; + this.FormClosed += new System.Windows.Forms.FormClosedEventHandler(this.frmClient_FormClosed); + this.Load += new System.EventHandler(this.frmClient_Load); + this.groupBox1.ResumeLayout(false); + this.groupBox1.PerformLayout(); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.GroupBox groupBox1; + private System.Windows.Forms.TextBox txtPort; + private System.Windows.Forms.TextBox txtIpAddress; + private System.Windows.Forms.Button btnStop; + private System.Windows.Forms.Button btnStart; + private System.Windows.Forms.ListBox lbxMsg; + private System.Windows.Forms.CheckBox cbxAsyncConn; + private System.Windows.Forms.TextBox txtSend; + private System.Windows.Forms.Button btnSend; + + } +} + diff --git a/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpPullClient/frmClient.cs b/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpPullClient/frmClient.cs new file mode 100644 index 000000000..e9b07b377 --- /dev/null +++ b/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpPullClient/frmClient.cs @@ -0,0 +1,374 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Windows.Forms; +using HPSocketCS; +using System.Runtime.InteropServices; + +namespace TcpPullClient +{ + public enum AppState + { + Starting, Started, Stoping, Stoped, Error + } + + public partial class frmClient : Form + { + private AppState appState = AppState.Stoped; + + private delegate void ConnectUpdateUiDelegate(); + private delegate void SetAppStateDelegate(AppState state); + private delegate void ShowMsg(string msg); + private ShowMsg AddMsgDelegate; + HPSocketCS.TcpPullClient client = new HPSocketCS.TcpPullClient(); + + int id = 0; + + // 包头大小 + int pkgHeaderSize = Marshal.SizeOf(new PkgHeader()); + PkgInfo pkgInfo = new PkgInfo(); + + public frmClient() + { + InitializeComponent(); + } + + private void frmClient_Load(object sender, EventArgs e) + { + try + { + // 加个委托显示msg,因为on系列都是在工作线程中调用的,ui不允许直接操作 + AddMsgDelegate = new ShowMsg(AddMsg); + + pkgInfo.IsHeader = true; + pkgInfo.Length = pkgHeaderSize; + + // 设置 Socket 监听器回调函数 + client.SetCallback(OnPrepareConnect, OnConnect, OnSend, OnReceive, OnClose, OnError); + + + SetAppState(AppState.Stoped); + } + catch (Exception ex) + { + SetAppState(AppState.Error); + AddMsg(ex.Message); + } + } + + private void btnStart_Click(object sender, EventArgs e) + { + try + { + String ip = this.txtIpAddress.Text.Trim(); + ushort port = ushort.Parse(this.txtPort.Text.Trim()); + + // 写在这个位置是上面可能会异常 + SetAppState(AppState.Starting); + + AddMsg(string.Format("$Client Starting ... -> ({0}:{1})", ip, port)); + + if (client.Start(ip, port, this.cbxAsyncConn.Checked)) + { + if (cbxAsyncConn.Checked == false) + { + SetAppState(AppState.Started); + } + } + else + { + SetAppState(AppState.Stoped); + throw new Exception(string.Format("$Client Start Error -> {0}({1})", client.GetLastErrorDesc(), client.GetlastError())); + } + } + catch (Exception ex) + { + AddMsg(ex.Message); + } + } + + private void btnStop_Click(object sender, EventArgs e) + { + + // 停止服务 + AddMsg("$Server Stop"); + if (client.Stop()) + { + SetAppState(AppState.Stoped); + } + else + { + AddMsg(string.Format("$Stop Error -> {0}({1})", client.GetLastErrorDesc(), client.GetlastError())); + } + } + + private void btnSend_Click(object sender, EventArgs e) + { + IntPtr bufferPtr = IntPtr.Zero; + try + { + string send = this.txtSend.Text; + if (send.Length == 0) + { + return; + } + + // 封包体 + byte[] bodyBytes = Encoding.Default.GetBytes(send); + + // 封包头 + PkgHeader header = new PkgHeader(); + header.Id = ++id; + header.BodySize = bodyBytes.Length; + byte[] headerBytes = client.StructureToByte(header); + + + // 组合最终发送的封包 (封包头+封包体) + byte[] sendBytes = GetSendBuffer(headerBytes, bodyBytes); + + // 发送 + IntPtr dwConnId = client.GetConnectionId(); + if (client.Send(sendBytes, sendBytes.Length)) + { + AddMsg(string.Format("$ ({0}) Send OK --> {1}", dwConnId, send)); + } + else + { + AddMsg(string.Format("$ ({0}) Send Fail --> {1} ({2})", dwConnId, send, sendBytes.Length)); + } + + } + catch (Exception) + { + + } + finally + { + if (bufferPtr != IntPtr.Zero) + { + Marshal.FreeHGlobal(bufferPtr); + } + } + + + } + + private void lbxMsg_KeyPress(object sender, KeyPressEventArgs e) + { + + // 清理listbox + if (e.KeyChar == 'c' || e.KeyChar == 'C') + { + this.lbxMsg.Items.Clear(); + } + } + + void ConnectUpdateUi() + { + if (this.cbxAsyncConn.Checked == true) + { + SetAppState(AppState.Started); + } + } + + HandleResult OnPrepareConnect(IntPtr dwConnId, uint socket) + { + return HandleResult.Ok; + } + + HandleResult OnConnect(IntPtr dwConnId) + { + // 已连接 到达一次 + // 如果是异步联接,更新界面状态 + + this.Invoke(new ConnectUpdateUiDelegate(ConnectUpdateUi)); + + AddMsg(string.Format(" > [{0},OnConnect]", dwConnId)); + + return HandleResult.Ok; + } + + HandleResult OnSend(IntPtr dwConnId, IntPtr pData, int iLength) + { + // 客户端发数据了 + AddMsg(string.Format(" > [{0},OnSend] -> ({1} bytes)", dwConnId, iLength)); + + return HandleResult.Ok; + } + + HandleResult OnReceive(IntPtr dwConnId, int iLength) + { + // 数据到达了 + + // 需要长度 + int required = pkgInfo.Length; + + // 剩余大小 + int remain = iLength; + + + while (remain >= required) + { + IntPtr bufferPtr = IntPtr.Zero; + try + { + remain -= required; + bufferPtr = Marshal.AllocHGlobal(required); ; + if (client.Fetch(dwConnId, bufferPtr, required) == FetchResult.Ok) + { + if (pkgInfo.IsHeader == true) + { + PkgHeader header = (PkgHeader)Marshal.PtrToStructure(bufferPtr, typeof(PkgHeader)); + + // 调试信息 + Console.WriteLine("[Client] head -> Id: {0}, BodySize: {1}\r\n", header.Id, header.BodySize); + + required = header.BodySize; + } + else + { + // 调试信息 + string recvString = Marshal.PtrToStringAnsi(bufferPtr, required); + Console.WriteLine("[Client] body -> text: {0}\r\n", recvString); + + required = pkgHeaderSize; + } + + AddMsg(string.Format(" > [{0},OnReceive] -> ({1} bytes)", dwConnId, pkgInfo.Length)); + + pkgInfo.IsHeader = !pkgInfo.IsHeader; + pkgInfo.Length = required; + } + } + catch + { + return HandleResult.Error; + } + finally + { + if (bufferPtr != IntPtr.Zero) + { + Marshal.FreeHGlobal(bufferPtr); + bufferPtr = IntPtr.Zero; + } + } + } + + return HandleResult.Ok; + } + + HandleResult OnClose(IntPtr dwConnId) + { + // 连接关闭了 + + AddMsg(string.Format(" > [{0},OnClose]", dwConnId)); + + // 通知界面 + this.Invoke(new SetAppStateDelegate(SetAppState), AppState.Stoped); + return HandleResult.Ok; + } + + HandleResult OnError(IntPtr dwConnId, SocketOperation enOperation, int iErrorCode) + { + // 出错了 + + AddMsg(string.Format(" > [{0},OnError] -> OP:{1},CODE:{2}", dwConnId, enOperation, iErrorCode)); + + // 通知界面,只处理了连接错误,也没进行是不是连接错误的判断,所以有错误就会设置界面 + // 生产环境请自己控制 + this.Invoke(new SetAppStateDelegate(SetAppState), AppState.Stoped); + + return HandleResult.Ok; + } + + /// + /// 设置程序状态 + /// + /// + void SetAppState(AppState state) + { + appState = state; + this.btnStart.Enabled = (appState == AppState.Stoped); + this.btnStop.Enabled = (appState == AppState.Started); + this.txtIpAddress.Enabled = (appState == AppState.Stoped); + this.txtPort.Enabled = (appState == AppState.Stoped); + this.cbxAsyncConn.Enabled = (appState == AppState.Stoped); + this.btnSend.Enabled = (appState == AppState.Started); + } + + /// + /// 往listbox加一条项目 + /// + /// + void AddMsg(string msg) + { + if (this.lbxMsg.InvokeRequired) + { + // 很帅的调自己 + this.lbxMsg.Invoke(AddMsgDelegate, msg); + } + else + { + if (this.lbxMsg.Items.Count > 100) + { + this.lbxMsg.Items.RemoveAt(0); + } + this.lbxMsg.Items.Add(msg); + this.lbxMsg.TopIndex = this.lbxMsg.Items.Count - (int)(this.lbxMsg.Height / this.lbxMsg.ItemHeight); + } + } + + private void frmClient_FormClosed(object sender, FormClosedEventArgs e) + { + client.Destroy(); + } + + private byte[] GetSendBuffer(byte[] headerBytes, byte[] bodyBytes) + { + IntPtr ptr = IntPtr.Zero; + try + { + int bufferSize = headerBytes.Length + bodyBytes.Length; + ptr = Marshal.AllocHGlobal(bufferSize); + + // 拷贝包头到缓冲区首部 + Marshal.Copy(headerBytes, 0, ptr, headerBytes.Length); + + // 拷贝包体到缓冲区剩余部分 + Marshal.Copy(bodyBytes, 0, ptr + headerBytes.Length, bodyBytes.Length); + + byte[] bytes = new byte[bufferSize]; + Marshal.Copy(ptr, bytes, 0, bufferSize); + + return bytes; + } + finally + { + if (ptr != IntPtr.Zero) + { + Marshal.FreeHGlobal(ptr); + } + } + + } + + } + + [StructLayout(LayoutKind.Sequential)] + public class PkgHeader + { + public int Id; + public int BodySize; + } + + [StructLayout(LayoutKind.Sequential)] + public class PkgInfo + { + public bool IsHeader; + public int Length; + } +} diff --git a/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpPullClient/frmClient.resx b/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpPullClient/frmClient.resx new file mode 100644 index 000000000..1af7de150 --- /dev/null +++ b/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpPullClient/frmClient.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpPullServer/Program.cs b/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpPullServer/Program.cs new file mode 100644 index 000000000..181f94d05 --- /dev/null +++ b/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpPullServer/Program.cs @@ -0,0 +1,21 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Windows.Forms; + +namespace TcpPullServer +{ + static class Program + { + /// + /// 应用程序的主入口点。 + /// + [STAThread] + static void Main() + { + Application.EnableVisualStyles(); + Application.SetCompatibleTextRenderingDefault(false); + Application.Run(new frmServer()); + } + } +} diff --git a/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpPullServer/Properties/AssemblyInfo.cs b/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpPullServer/Properties/AssemblyInfo.cs new file mode 100644 index 000000000..fcd4bd3d3 --- /dev/null +++ b/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpPullServer/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// 有关程序集的常规信息通过以下 +// 特性集控制。更改这些特性值可修改 +// 与程序集关联的信息。 +[assembly: AssemblyTitle("Server")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("Server")] +[assembly: AssemblyCopyright("Copyright © 2014")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// 将 ComVisible 设置为 false 使此程序集中的类型 +// 对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型, +// 则将该类型上的 ComVisible 特性设置为 true。 +[assembly: ComVisible(false)] + +// 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID +[assembly: Guid("a8f79261-fd62-4f4b-aed5-01bf44660ad1")] + +// 程序集的版本信息由下面四个值组成: +// +// 主版本 +// 次版本 +// 内部版本号 +// 修订号 +// +// 可以指定所有这些值,也可以使用“内部版本号”和“修订号”的默认值, +// 方法是按如下所示使用“*”: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpPullServer/Properties/Resources.Designer.cs b/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpPullServer/Properties/Resources.Designer.cs new file mode 100644 index 000000000..fa7465295 --- /dev/null +++ b/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpPullServer/Properties/Resources.Designer.cs @@ -0,0 +1,63 @@ +//------------------------------------------------------------------------------ +// +// 此代码由工具生成。 +// 运行时版本:4.0.30319.18444 +// +// 对此文件的更改可能会导致不正确的行为,并且如果 +// 重新生成代码,这些更改将会丢失。 +// +//------------------------------------------------------------------------------ + +namespace TcpPullServer.Properties { + using System; + + + /// + /// 一个强类型的资源类,用于查找本地化的字符串等。 + /// + // 此类是由 StronglyTypedResourceBuilder + // 类通过类似于 ResGen 或 Visual Studio 的工具自动生成的。 + // 若要添加或移除成员,请编辑 .ResX 文件,然后重新运行 ResGen + // (以 /str 作为命令选项),或重新生成 VS 项目。 + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// + /// 返回此类使用的缓存的 ResourceManager 实例。 + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("TcpPullServer.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// 使用此强类型资源类,为所有资源查找 + /// 重写当前线程的 CurrentUICulture 属性。 + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + } +} diff --git a/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpPullServer/Properties/Resources.resx b/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpPullServer/Properties/Resources.resx new file mode 100644 index 000000000..af7dbebba --- /dev/null +++ b/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpPullServer/Properties/Resources.resx @@ -0,0 +1,117 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpPullServer/Properties/Settings.Designer.cs b/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpPullServer/Properties/Settings.Designer.cs new file mode 100644 index 000000000..5b98cbb5f --- /dev/null +++ b/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpPullServer/Properties/Settings.Designer.cs @@ -0,0 +1,26 @@ +//------------------------------------------------------------------------------ +// +// 此代码由工具生成。 +// 运行时版本:4.0.30319.18444 +// +// 对此文件的更改可能会导致不正确的行为,并且如果 +// 重新生成代码,这些更改将会丢失。 +// +//------------------------------------------------------------------------------ + +namespace TcpPullServer.Properties { + + + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "10.0.0.0")] + internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { + + private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); + + public static Settings Default { + get { + return defaultInstance; + } + } + } +} diff --git a/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpPullServer/Properties/Settings.settings b/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpPullServer/Properties/Settings.settings new file mode 100644 index 000000000..39645652a --- /dev/null +++ b/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpPullServer/Properties/Settings.settings @@ -0,0 +1,7 @@ + + + + + + + diff --git a/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpPullServer/TcpPullServer.csproj b/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpPullServer/TcpPullServer.csproj new file mode 100644 index 000000000..e4f9382b6 --- /dev/null +++ b/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpPullServer/TcpPullServer.csproj @@ -0,0 +1,126 @@ + + + + Debug + x86 + 8.0.30703 + 2.0 + {B6654857-4C82-4F92-AD7A-21FD3ED5BBFA} + WinExe + Properties + TcpPullServer + TcpPullServer + v4.0 + Client + 512 + + + x86 + true + full + false + ..\bin\x86\Debug\ + DEBUG;TRACE + prompt + 4 + + + x86 + pdbonly + true + ..\bin\x86\Release\ + TRACE + prompt + 4 + + + true + ..\bin\x64\Debug\ + DEBUG;TRACE + full + x64 + ..\bin\Debug\TcpPullServer.exe.CodeAnalysisLog.xml + true + GlobalSuppressions.cs + prompt + MinimumRecommendedRules.ruleset + ;D:\Program Files\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets + true + ;D:\Program Files\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules + true + + + ..\bin\x64\Release\ + TRACE + true + pdbonly + x64 + ..\bin\Release\TcpPullServer.exe.CodeAnalysisLog.xml + true + GlobalSuppressions.cs + prompt + MinimumRecommendedRules.ruleset + ;D:\Program Files\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets + true + ;D:\Program Files\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules + true + + + + + + + + + + + + + + + + Form + + + frmServer.cs + + + + + frmServer.cs + + + ResXFileCodeGenerator + Resources.Designer.cs + Designer + + + True + Resources.resx + True + + + SettingsSingleFileGenerator + Settings.Designer.cs + + + True + Settings.settings + True + + + + + {DFA935E2-CF37-4E26-B697-D7F3DEE19DD8} + HPSocketCS + + + + + \ No newline at end of file diff --git a/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpPullServer/frmServer.Designer.cs b/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpPullServer/frmServer.Designer.cs new file mode 100644 index 000000000..c0c227869 --- /dev/null +++ b/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpPullServer/frmServer.Designer.cs @@ -0,0 +1,169 @@ +namespace TcpPullServer +{ + partial class frmServer + { + /// + /// 必需的设计器变量。 + /// + private System.ComponentModel.IContainer components = null; + + /// + /// 清理所有正在使用的资源。 + /// + /// 如果应释放托管资源,为 true;否则为 false。 + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows 窗体设计器生成的代码 + + /// + /// 设计器支持所需的方法 - 不要 + /// 使用代码编辑器修改此方法的内容。 + /// + private void InitializeComponent() + { + this.lbxMsg = new System.Windows.Forms.ListBox(); + this.groupBox1 = new System.Windows.Forms.GroupBox(); + this.label1 = new System.Windows.Forms.Label(); + this.btnDisconn = new System.Windows.Forms.Button(); + this.txtDisConn = new System.Windows.Forms.TextBox(); + this.txtPort = new System.Windows.Forms.TextBox(); + this.txtIpAddress = new System.Windows.Forms.TextBox(); + this.btnStop = new System.Windows.Forms.Button(); + this.btnStart = new System.Windows.Forms.Button(); + this.groupBox1.SuspendLayout(); + this.SuspendLayout(); + // + // lbxMsg + // + this.lbxMsg.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.lbxMsg.FormattingEnabled = true; + this.lbxMsg.ItemHeight = 12; + this.lbxMsg.Location = new System.Drawing.Point(11, 62); + this.lbxMsg.Name = "lbxMsg"; + this.lbxMsg.Size = new System.Drawing.Size(465, 304); + this.lbxMsg.TabIndex = 4; + this.lbxMsg.KeyPress += new System.Windows.Forms.KeyPressEventHandler(this.lbxMsg_KeyPress); + // + // groupBox1 + // + this.groupBox1.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.groupBox1.Controls.Add(this.label1); + this.groupBox1.Controls.Add(this.btnDisconn); + this.groupBox1.Controls.Add(this.txtDisConn); + this.groupBox1.Controls.Add(this.txtPort); + this.groupBox1.Controls.Add(this.txtIpAddress); + this.groupBox1.Controls.Add(this.btnStop); + this.groupBox1.Controls.Add(this.btnStart); + this.groupBox1.Location = new System.Drawing.Point(12, 2); + this.groupBox1.Name = "groupBox1"; + this.groupBox1.Size = new System.Drawing.Size(462, 47); + this.groupBox1.TabIndex = 9; + this.groupBox1.TabStop = false; + // + // label1 + // + this.label1.AutoSize = true; + this.label1.Location = new System.Drawing.Point(132, 22); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(41, 12); + this.label1.TabIndex = 15; + this.label1.Text = "CONNID"; + // + // btnDisconn + // + this.btnDisconn.Location = new System.Drawing.Point(223, 15); + this.btnDisconn.Name = "btnDisconn"; + this.btnDisconn.Size = new System.Drawing.Size(33, 26); + this.btnDisconn.TabIndex = 14; + this.btnDisconn.Text = "Dis"; + this.btnDisconn.UseVisualStyleBackColor = true; + this.btnDisconn.Click += new System.EventHandler(this.btnDisconn_Click); + // + // txtDisConn + // + this.txtDisConn.Location = new System.Drawing.Point(178, 18); + this.txtDisConn.Name = "txtDisConn"; + this.txtDisConn.Size = new System.Drawing.Size(40, 21); + this.txtDisConn.TabIndex = 13; + this.txtDisConn.TextChanged += new System.EventHandler(this.txtDisConn_TextChanged); + // + // txtPort + // + this.txtPort.Location = new System.Drawing.Point(88, 18); + this.txtPort.Name = "txtPort"; + this.txtPort.Size = new System.Drawing.Size(40, 21); + this.txtPort.TabIndex = 12; + this.txtPort.Text = "5555"; + // + // txtIpAddress + // + this.txtIpAddress.Location = new System.Drawing.Point(11, 18); + this.txtIpAddress.Name = "txtIpAddress"; + this.txtIpAddress.Size = new System.Drawing.Size(71, 21); + this.txtIpAddress.TabIndex = 11; + this.txtIpAddress.Text = "0.0.0.0"; + // + // btnStop + // + this.btnStop.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.btnStop.Location = new System.Drawing.Point(403, 15); + this.btnStop.Name = "btnStop"; + this.btnStop.Size = new System.Drawing.Size(47, 26); + this.btnStop.TabIndex = 10; + this.btnStop.Text = "Stop"; + this.btnStop.UseVisualStyleBackColor = true; + this.btnStop.Click += new System.EventHandler(this.btnStop_Click); + // + // btnStart + // + this.btnStart.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.btnStart.Location = new System.Drawing.Point(350, 15); + this.btnStart.Name = "btnStart"; + this.btnStart.Size = new System.Drawing.Size(47, 26); + this.btnStart.TabIndex = 9; + this.btnStart.Text = "Start"; + this.btnStart.UseVisualStyleBackColor = true; + this.btnStart.Click += new System.EventHandler(this.btnStart_Click); + // + // frmServer + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(486, 377); + this.Controls.Add(this.groupBox1); + this.Controls.Add(this.lbxMsg); + this.Name = "frmServer"; + this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen; + this.Text = "Form1"; + this.FormClosed += new System.Windows.Forms.FormClosedEventHandler(this.frmServer_FormClosed); + this.Load += new System.EventHandler(this.Form1_Load); + this.groupBox1.ResumeLayout(false); + this.groupBox1.PerformLayout(); + this.ResumeLayout(false); + + } + + #endregion + + private System.Windows.Forms.ListBox lbxMsg; + private System.Windows.Forms.GroupBox groupBox1; + private System.Windows.Forms.Label label1; + private System.Windows.Forms.Button btnDisconn; + private System.Windows.Forms.TextBox txtDisConn; + private System.Windows.Forms.TextBox txtPort; + private System.Windows.Forms.Button btnStop; + private System.Windows.Forms.Button btnStart; + private System.Windows.Forms.TextBox txtIpAddress; + } +} + diff --git a/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpPullServer/frmServer.cs b/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpPullServer/frmServer.cs new file mode 100644 index 000000000..303c20b0b --- /dev/null +++ b/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpPullServer/frmServer.cs @@ -0,0 +1,392 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Windows.Forms; +using System.Runtime.InteropServices; +using HPSocketCS; + +namespace TcpPullServer +{ + public enum AppState + { + Starting, Started, Stoping, Stoped, Error + } + + public partial class frmServer : Form + { + private AppState appState = AppState.Stoped; + + private delegate void ShowMsg(string msg); + private ShowMsg AddMsgDelegate; + + HPSocketCS.TcpPullServer server = new HPSocketCS.TcpPullServer(); + + + // 包头大小 + int pkgHeaderSize = Marshal.SizeOf(new PkgHeader()); + + private string title = "Echo TcpPullServer [ 'C' - clear list box ]"; + public frmServer() + { + InitializeComponent(); + } + + private void Form1_Load(object sender, EventArgs e) + { + try + { + + this.Text = title; + // 本机测试没必要改地址,有需求请注释或删除 + this.txtIpAddress.ReadOnly = true; + + // 加个委托显示msg,因为on系列都是在工作线程中调用的,ui不允许直接操作 + AddMsgDelegate = new ShowMsg(AddMsg); + + // 设置回调函数 + server.SetCallback(OnPrepareListen, OnAccept, OnSend, OnReceive, OnClose, OnError, OnServerShutdown); + + SetAppState(AppState.Stoped); + } + catch (Exception ex) + { + SetAppState(AppState.Error); + AddMsg(ex.Message); + } + } + + private void btnStart_Click(object sender, EventArgs e) + { + try + { + String ip = this.txtIpAddress.Text.Trim(); + ushort port = ushort.Parse(this.txtPort.Text.Trim()); + + // 写在这个位置是上面可能会异常 + SetAppState(AppState.Starting); + + // 启动服务 + if (server.Start(ip, port)) + { + this.Text = string.Format("{2} - ({0}:{1})", ip, port, title); + SetAppState(AppState.Started); + throw new Exception(string.Format("$Server Start OK -> ({0}:{1})", ip, port)); + } + else + { + SetAppState(AppState.Stoped); + throw new Exception(string.Format("$Server Start Error -> {0}({1})", server.GetLastErrorDesc(), server.GetlastError())); + } + } + catch (Exception ex) + { + AddMsg(ex.Message); + } + } + + private void btnStop_Click(object sender, EventArgs e) + { + SetAppState(AppState.Stoping); + + // 停止服务 + AddMsg("$Server Stop"); + if (server.Stop()) + { + this.Text = title; + SetAppState(AppState.Stoped); + } + else + { + AddMsg(string.Format("$Stop Error -> {0}({1})", server.GetLastErrorDesc(), server.GetlastError())); + } + } + + private void btnDisconn_Click(object sender, EventArgs e) + { + try + { + // 未做64位判断 + IntPtr dwConnId = (IntPtr)Convert.ToUInt32(this.txtDisConn.Text.Trim()); + + // 断开指定客户 + if (server.Disconnect(dwConnId, true)) + { + AddMsg(string.Format("$({0}) Disconnect OK", dwConnId)); + } + else + { + throw new Exception(string.Format("Disconnect({0}) Error", dwConnId)); + } + } + catch (Exception ex) + { + AddMsg(ex.Message); + } + } + + + HandleResult OnPrepareListen(IntPtr soListen) + { + // 监听事件到达了,一般没什么用吧? + + return HandleResult.Ok; + } + + HandleResult OnAccept(IntPtr dwConnId, IntPtr pClient) + { + // 客户进入了 + + + // 获取客户端ip和端口 + string ip = string.Empty; + ushort port = 0; + if (server.GetRemoteAddress(dwConnId, ref ip, ref port)) + { + AddMsg(string.Format(" > [{0},OnAccept] -> PASS({1}:{2})", dwConnId, ip.ToString(), port)); + } + else + { + AddMsg(string.Format(" > [{0},OnAccept] -> Server_GetClientAddress() Error", dwConnId)); + } + + + // 设置附加数据 + ClientInfo ci = new ClientInfo(); + ci.ConnId = dwConnId; + ci.IpAddress = ip; + ci.Port = port; + ci.PkgInfo = new PkgInfo() + { + IsHeader = true, + Length = pkgHeaderSize, + }; + if (server.SetConnectionExtra(dwConnId, ci) == false) + { + AddMsg(string.Format(" > [{0},OnAccept] -> SetConnectionExtra fail", dwConnId)); + } + + return HandleResult.Ok; + } + + HandleResult OnSend(IntPtr dwConnId, IntPtr pData, int iLength) + { + // 服务器发数据了 + + + AddMsg(string.Format(" > [{0},OnSend] -> ({1} bytes)", dwConnId, iLength)); + + return HandleResult.Ok; + } + + HandleResult OnReceive(IntPtr dwConnId, int iLength) + { + // 数据到达了 + IntPtr clientPtr = IntPtr.Zero; + if (server.GetConnectionExtra(dwConnId, ref clientPtr) == false) + { + return HandleResult.Error; + } + ClientInfo ci = (ClientInfo)Marshal.PtrToStructure(clientPtr, typeof(ClientInfo)); + PkgInfo pkgInfo = ci.PkgInfo; + + + // 需要长度 + int required = pkgInfo.Length; + + // 剩余大小 + int remain = iLength; + + while (remain >= required) + { + IntPtr bufferPtr = IntPtr.Zero; + try + { + remain -= required; + bufferPtr = Marshal.AllocHGlobal(required); ; + if (server.Fetch(dwConnId, bufferPtr, required) == FetchResult.Ok) + { + if (pkgInfo.IsHeader == true) + { + PkgHeader header = (PkgHeader)Marshal.PtrToStructure(bufferPtr, typeof(PkgHeader)); + + // 调试信息 + Console.WriteLine("[Server] head -> Id: {0}, BodySize: {1}\r\n", header.Id, header.BodySize); + + required = header.BodySize; + } + else + { + // 调试信息 + string recvString = Marshal.PtrToStringAnsi(bufferPtr, required); + Console.WriteLine("[Server] body -> text: {0}\r\n", recvString); + + // intptr转string + //Marshal.PtrToStringAnsi(bufferPtr, required); + + //intptr转byte[] + // byte[] bytes = new byte[required]; + // Marshal.Copy(bufferPtr, bytes, 0, required); + + required = pkgHeaderSize; + + } + + AddMsg(string.Format(" > [{0},OnReceive] -> ({1} bytes)", dwConnId, pkgInfo.Length)); + + // 回发数据 + byte[] sendBytes = new byte[pkgInfo.Length]; + Marshal.Copy(bufferPtr, sendBytes, 0, sendBytes.Length); + if (server.Send(dwConnId, sendBytes, sendBytes.Length) == false) + { + throw new Exception("server.Send() == false"); + } + + // 在后面赋值,因为前面需要用到pkgInfo.Length + pkgInfo.IsHeader = !pkgInfo.IsHeader; + pkgInfo.Length = required; + if (server.SetConnectionExtra(dwConnId, ci) == false) + { + return HandleResult.Error; + } + } + + } + catch + { + return HandleResult.Error; + } + finally + { + if (bufferPtr != IntPtr.Zero) + { + Marshal.FreeHGlobal(bufferPtr); + bufferPtr = IntPtr.Zero; + } + } + } + + return HandleResult.Ok; + } + + HandleResult OnClose(IntPtr dwConnId) + { + // 客户离开了 + + + // 释放附加数据 + if (server.SetConnectionExtra(dwConnId, null) == false) + { + AddMsg(string.Format(" > [{0},OnClose] -> SetConnectionExtra({0}, null) fail", dwConnId)); + } + + + AddMsg(string.Format(" > [{0},OnClose]", dwConnId)); + return HandleResult.Ok; + } + + HandleResult OnError(IntPtr dwConnId, SocketOperation enOperation, int iErrorCode) + { + // 客户出错了 + + AddMsg(string.Format(" > [{0},OnError] -> OP:{1},CODE:{2}", dwConnId, enOperation, iErrorCode)); + // return HPSocketSdk.HandleResult.Ok; + + // 因为要释放附加数据,所以直接返回OnClose()了 + return OnClose(dwConnId); + } + + HandleResult OnServerShutdown() + { + // 服务关闭了 + + + AddMsg(" > [OnServerShutdown]"); + return HandleResult.Ok; + } + + + /// + /// 设置程序状态 + /// + /// + void SetAppState(AppState state) + { + appState = state; + this.btnStart.Enabled = (appState == AppState.Stoped); + this.btnStop.Enabled = (appState == AppState.Started); + this.txtIpAddress.Enabled = (appState == AppState.Stoped); + this.txtPort.Enabled = (appState == AppState.Stoped); + this.txtDisConn.Enabled = (appState == AppState.Started); + this.btnDisconn.Enabled = (appState == AppState.Started && this.txtDisConn.Text.Length > 0); + } + + /// + /// 往listbox加一条项目 + /// + /// + void AddMsg(string msg) + { + if (this.lbxMsg.InvokeRequired) + { + // 很帅的调自己 + this.lbxMsg.Invoke(AddMsgDelegate, msg); + } + else + { + if (this.lbxMsg.Items.Count > 100) + { + this.lbxMsg.Items.RemoveAt(0); + } + this.lbxMsg.Items.Add(msg); + this.lbxMsg.TopIndex = this.lbxMsg.Items.Count - (int)(this.lbxMsg.Height / this.lbxMsg.ItemHeight); + } + } + + private void txtDisConn_TextChanged(object sender, EventArgs e) + { + // CONNID框被改变事件 + this.btnDisconn.Enabled = (appState == AppState.Started && this.txtDisConn.Text.Length > 0); + } + + private void lbxMsg_KeyPress(object sender, KeyPressEventArgs e) + { + // 清理listbox + if (e.KeyChar == 'c' || e.KeyChar == 'C') + { + this.lbxMsg.Items.Clear(); + } + } + + private void frmServer_FormClosed(object sender, FormClosedEventArgs e) + { + server.Destroy(); + } + } + + [StructLayout(LayoutKind.Sequential)] + public class ClientInfo + { + public IntPtr ConnId { get; set; } + public string IpAddress { get; set; } + public ushort Port { get; set; } + public PkgInfo PkgInfo { get; set; } + } + + [StructLayout(LayoutKind.Sequential)] + public class PkgHeader + { + public int Id; + public int BodySize; + } + + [StructLayout(LayoutKind.Sequential)] + public class PkgInfo + { + public bool IsHeader; + public int Length; + } +} diff --git a/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpPullServer/frmServer.resx b/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpPullServer/frmServer.resx new file mode 100644 index 000000000..1af7de150 --- /dev/null +++ b/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpPullServer/frmServer.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpServer-PFM/Program.cs b/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpServer-PFM/Program.cs new file mode 100644 index 000000000..4a3923e91 --- /dev/null +++ b/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpServer-PFM/Program.cs @@ -0,0 +1,21 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Windows.Forms; + +namespace TcpServer_PFM +{ + static class Program + { + /// + /// 应用程序的主入口点。 + /// + [STAThread] + static void Main() + { + Application.EnableVisualStyles(); + Application.SetCompatibleTextRenderingDefault(false); + Application.Run(new frmServer()); + } + } +} diff --git a/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpServer-PFM/Properties/AssemblyInfo.cs b/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpServer-PFM/Properties/AssemblyInfo.cs new file mode 100644 index 000000000..fcd4bd3d3 --- /dev/null +++ b/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpServer-PFM/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// 有关程序集的常规信息通过以下 +// 特性集控制。更改这些特性值可修改 +// 与程序集关联的信息。 +[assembly: AssemblyTitle("Server")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("Server")] +[assembly: AssemblyCopyright("Copyright © 2014")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// 将 ComVisible 设置为 false 使此程序集中的类型 +// 对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型, +// 则将该类型上的 ComVisible 特性设置为 true。 +[assembly: ComVisible(false)] + +// 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID +[assembly: Guid("a8f79261-fd62-4f4b-aed5-01bf44660ad1")] + +// 程序集的版本信息由下面四个值组成: +// +// 主版本 +// 次版本 +// 内部版本号 +// 修订号 +// +// 可以指定所有这些值,也可以使用“内部版本号”和“修订号”的默认值, +// 方法是按如下所示使用“*”: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpServer-PFM/Properties/Resources.Designer.cs b/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpServer-PFM/Properties/Resources.Designer.cs new file mode 100644 index 000000000..fe2b41333 --- /dev/null +++ b/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpServer-PFM/Properties/Resources.Designer.cs @@ -0,0 +1,63 @@ +//------------------------------------------------------------------------------ +// +// 此代码由工具生成。 +// 运行时版本:4.0.30319.18444 +// +// 对此文件的更改可能会导致不正确的行为,并且如果 +// 重新生成代码,这些更改将会丢失。 +// +//------------------------------------------------------------------------------ + +namespace TcpServer_PFM.Properties { + using System; + + + /// + /// 一个强类型的资源类,用于查找本地化的字符串等。 + /// + // 此类是由 StronglyTypedResourceBuilder + // 类通过类似于 ResGen 或 Visual Studio 的工具自动生成的。 + // 若要添加或移除成员,请编辑 .ResX 文件,然后重新运行 ResGen + // (以 /str 作为命令选项),或重新生成 VS 项目。 + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// + /// 返回此类使用的缓存的 ResourceManager 实例。 + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("TcpServer_PFM.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// 使用此强类型资源类,为所有资源查找 + /// 重写当前线程的 CurrentUICulture 属性。 + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + } +} diff --git a/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpServer-PFM/Properties/Resources.resx b/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpServer-PFM/Properties/Resources.resx new file mode 100644 index 000000000..af7dbebba --- /dev/null +++ b/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpServer-PFM/Properties/Resources.resx @@ -0,0 +1,117 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpServer-PFM/Properties/Settings.Designer.cs b/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpServer-PFM/Properties/Settings.Designer.cs new file mode 100644 index 000000000..20366263c --- /dev/null +++ b/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpServer-PFM/Properties/Settings.Designer.cs @@ -0,0 +1,26 @@ +//------------------------------------------------------------------------------ +// +// 此代码由工具生成。 +// 运行时版本:4.0.30319.18444 +// +// 对此文件的更改可能会导致不正确的行为,并且如果 +// 重新生成代码,这些更改将会丢失。 +// +//------------------------------------------------------------------------------ + +namespace TcpServer_PFM.Properties { + + + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "10.0.0.0")] + internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { + + private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); + + public static Settings Default { + get { + return defaultInstance; + } + } + } +} diff --git a/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpServer-PFM/Properties/Settings.settings b/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpServer-PFM/Properties/Settings.settings new file mode 100644 index 000000000..39645652a --- /dev/null +++ b/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpServer-PFM/Properties/Settings.settings @@ -0,0 +1,7 @@ + + + + + + + diff --git a/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpServer-PFM/TcpServer-PFM.csproj b/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpServer-PFM/TcpServer-PFM.csproj new file mode 100644 index 000000000..b55bdcd4a --- /dev/null +++ b/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpServer-PFM/TcpServer-PFM.csproj @@ -0,0 +1,122 @@ + + + + Debug + x86 + 8.0.30703 + 2.0 + {10426A79-A3B3-4CD2-BD84-02AAEE27FB75} + WinExe + Properties + TcpServer_PFM + TcpServer-PFM + v4.0 + Client + 512 + + + x86 + true + full + false + ..\bin\x86\Debug\ + DEBUG;TRACE + prompt + 4 + + + x86 + pdbonly + true + ..\bin\x86\Release\ + TRACE + prompt + 4 + + + true + ..\bin\x64\Debug\ + DEBUG;TRACE + full + x64 + ..\bin\Debug\TcpServer-PFM.exe.CodeAnalysisLog.xml + true + GlobalSuppressions.cs + prompt + MinimumRecommendedRules.ruleset + ;D:\Program Files\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets + ;D:\Program Files\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules + + + ..\bin\x64\Release\ + TRACE + true + pdbonly + x64 + ..\bin\Release\TcpServer-PFM.exe.CodeAnalysisLog.xml + true + GlobalSuppressions.cs + prompt + MinimumRecommendedRules.ruleset + ;D:\Program Files\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets + ;D:\Program Files\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules + + + + + + + + + + + + + + + + Form + + + frmServer.cs + + + + + frmServer.cs + + + ResXFileCodeGenerator + Resources.Designer.cs + Designer + + + True + Resources.resx + True + + + SettingsSingleFileGenerator + Settings.Designer.cs + + + True + Settings.settings + True + + + + + {DFA935E2-CF37-4E26-B697-D7F3DEE19DD8} + HPSocketCS + + + + + \ No newline at end of file diff --git a/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpServer-PFM/frmServer.Designer.cs b/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpServer-PFM/frmServer.Designer.cs new file mode 100644 index 000000000..cfd0ca76d --- /dev/null +++ b/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpServer-PFM/frmServer.Designer.cs @@ -0,0 +1,169 @@ +namespace TcpServer_PFM +{ + partial class frmServer + { + /// + /// 必需的设计器变量。 + /// + private System.ComponentModel.IContainer components = null; + + /// + /// 清理所有正在使用的资源。 + /// + /// 如果应释放托管资源,为 true;否则为 false。 + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows 窗体设计器生成的代码 + + /// + /// 设计器支持所需的方法 - 不要 + /// 使用代码编辑器修改此方法的内容。 + /// + private void InitializeComponent() + { + this.lbxMsg = new System.Windows.Forms.ListBox(); + this.groupBox1 = new System.Windows.Forms.GroupBox(); + this.label1 = new System.Windows.Forms.Label(); + this.btnDisconn = new System.Windows.Forms.Button(); + this.txtDisConn = new System.Windows.Forms.TextBox(); + this.txtPort = new System.Windows.Forms.TextBox(); + this.txtIpAddress = new System.Windows.Forms.TextBox(); + this.btnStop = new System.Windows.Forms.Button(); + this.btnStart = new System.Windows.Forms.Button(); + this.groupBox1.SuspendLayout(); + this.SuspendLayout(); + // + // lbxMsg + // + this.lbxMsg.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.lbxMsg.FormattingEnabled = true; + this.lbxMsg.ItemHeight = 12; + this.lbxMsg.Location = new System.Drawing.Point(11, 62); + this.lbxMsg.Name = "lbxMsg"; + this.lbxMsg.Size = new System.Drawing.Size(465, 304); + this.lbxMsg.TabIndex = 4; + this.lbxMsg.KeyPress += new System.Windows.Forms.KeyPressEventHandler(this.lbxMsg_KeyPress); + // + // groupBox1 + // + this.groupBox1.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.groupBox1.Controls.Add(this.label1); + this.groupBox1.Controls.Add(this.btnDisconn); + this.groupBox1.Controls.Add(this.txtDisConn); + this.groupBox1.Controls.Add(this.txtPort); + this.groupBox1.Controls.Add(this.txtIpAddress); + this.groupBox1.Controls.Add(this.btnStop); + this.groupBox1.Controls.Add(this.btnStart); + this.groupBox1.Location = new System.Drawing.Point(12, 2); + this.groupBox1.Name = "groupBox1"; + this.groupBox1.Size = new System.Drawing.Size(462, 47); + this.groupBox1.TabIndex = 9; + this.groupBox1.TabStop = false; + // + // label1 + // + this.label1.AutoSize = true; + this.label1.Location = new System.Drawing.Point(132, 22); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(41, 12); + this.label1.TabIndex = 15; + this.label1.Text = "CONNID"; + // + // btnDisconn + // + this.btnDisconn.Location = new System.Drawing.Point(223, 15); + this.btnDisconn.Name = "btnDisconn"; + this.btnDisconn.Size = new System.Drawing.Size(33, 26); + this.btnDisconn.TabIndex = 14; + this.btnDisconn.Text = "Dis"; + this.btnDisconn.UseVisualStyleBackColor = true; + this.btnDisconn.Click += new System.EventHandler(this.btnDisconn_Click); + // + // txtDisConn + // + this.txtDisConn.Location = new System.Drawing.Point(178, 18); + this.txtDisConn.Name = "txtDisConn"; + this.txtDisConn.Size = new System.Drawing.Size(40, 21); + this.txtDisConn.TabIndex = 13; + this.txtDisConn.TextChanged += new System.EventHandler(this.txtDisConn_TextChanged); + // + // txtPort + // + this.txtPort.Location = new System.Drawing.Point(88, 18); + this.txtPort.Name = "txtPort"; + this.txtPort.Size = new System.Drawing.Size(40, 21); + this.txtPort.TabIndex = 12; + this.txtPort.Text = "5555"; + // + // txtIpAddress + // + this.txtIpAddress.Location = new System.Drawing.Point(11, 18); + this.txtIpAddress.Name = "txtIpAddress"; + this.txtIpAddress.Size = new System.Drawing.Size(71, 21); + this.txtIpAddress.TabIndex = 11; + this.txtIpAddress.Text = "0.0.0.0"; + // + // btnStop + // + this.btnStop.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.btnStop.Location = new System.Drawing.Point(403, 15); + this.btnStop.Name = "btnStop"; + this.btnStop.Size = new System.Drawing.Size(47, 26); + this.btnStop.TabIndex = 10; + this.btnStop.Text = "Stop"; + this.btnStop.UseVisualStyleBackColor = true; + this.btnStop.Click += new System.EventHandler(this.btnStop_Click); + // + // btnStart + // + this.btnStart.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.btnStart.Location = new System.Drawing.Point(350, 15); + this.btnStart.Name = "btnStart"; + this.btnStart.Size = new System.Drawing.Size(47, 26); + this.btnStart.TabIndex = 9; + this.btnStart.Text = "Start"; + this.btnStart.UseVisualStyleBackColor = true; + this.btnStart.Click += new System.EventHandler(this.btnStart_Click); + // + // frmServer + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(486, 377); + this.Controls.Add(this.groupBox1); + this.Controls.Add(this.lbxMsg); + this.Name = "frmServer"; + this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen; + this.Text = "Form1"; + this.FormClosed += new System.Windows.Forms.FormClosedEventHandler(this.frmServer_FormClosed); + this.Load += new System.EventHandler(this.Form1_Load); + this.groupBox1.ResumeLayout(false); + this.groupBox1.PerformLayout(); + this.ResumeLayout(false); + + } + + #endregion + + private System.Windows.Forms.ListBox lbxMsg; + private System.Windows.Forms.GroupBox groupBox1; + private System.Windows.Forms.Label label1; + private System.Windows.Forms.Button btnDisconn; + private System.Windows.Forms.TextBox txtDisConn; + private System.Windows.Forms.TextBox txtPort; + private System.Windows.Forms.Button btnStop; + private System.Windows.Forms.Button btnStart; + private System.Windows.Forms.TextBox txtIpAddress; + } +} + diff --git a/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpServer-PFM/frmServer.cs b/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpServer-PFM/frmServer.cs new file mode 100644 index 000000000..762e4740d --- /dev/null +++ b/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpServer-PFM/frmServer.cs @@ -0,0 +1,378 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Windows.Forms; +using System.Runtime.InteropServices; +using HPSocketCS; +using System.Threading; + +namespace TcpServer_PFM +{ + public enum AppState + { + Starting, Started, Stoping, Stoped, Error + } + + public partial class frmServer : Form + { + private AppState appState = AppState.Stoped; + + private delegate void ShowMsg(string msg); + private ShowMsg AddMsgDelegate; + + HPSocketCS.TcpServer server = new HPSocketCS.TcpServer(); + + private static string title = "Echo-PFM Server [ 'C' - clear list box, 'R' - reset statics data ]"; + + + private long totalReceived = 0; + private long totalSent = 0; + private long clientCount = 0; + + + + public frmServer() + { + InitializeComponent(); + } + + private void Form1_Load(object sender, EventArgs e) + { + try + { + + this.Text = title; + // 本机测试没必要改地址,有需求请注释或删除 + this.txtIpAddress.ReadOnly = true; + + // 加个委托显示msg,因为on系列都是在工作线程中调用的,ui不允许直接操作 + AddMsgDelegate = new ShowMsg(AddMsg); + + + // 设置回调函数 + server.SetCallback(OnPrepareListen, OnAccept, OnSend, OnReceive, OnClose, OnError, OnServerShutdown); + + SetAppState(AppState.Stoped); + } + catch (Exception ex) + { + SetAppState(AppState.Error); + AddMsg(ex.Message); + } + } + + private void btnStart_Click(object sender, EventArgs e) + { + try + { + String ip = this.txtIpAddress.Text.Trim(); + ushort port = ushort.Parse(this.txtPort.Text.Trim()); + + // 写在这个位置是上面可能会异常 + SetAppState(AppState.Starting); + + Reset(); + + // 启动服务 + if (server.Start(ip, port)) + { + this.Text = string.Format("{2} - ({0}:{1})", ip, port, title); + SetAppState(AppState.Started); + throw new Exception(string.Format("$Server Start OK -> ({0}:{1})", ip, port)); + } + else + { + SetAppState(AppState.Stoped); + throw new Exception(string.Format("$Server Start Error -> {0}({1})", server.GetLastErrorDesc(), server.GetlastError())); + } + } + catch (Exception ex) + { + AddMsg(ex.Message); + } + } + + private void btnStop_Click(object sender, EventArgs e) + { + SetAppState(AppState.Stoping); + + // 停止服务 + AddMsg("$Server Stop"); + if (server.Stop()) + { + this.Text = title; + SetAppState(AppState.Stoped); + } + else + { + AddMsg(string.Format("$Stop Error -> {0}({1})", server.GetLastErrorDesc(), server.GetlastError())); + } + } + + private void btnDisconn_Click(object sender, EventArgs e) + { + try + { + // 未做64位判断 + IntPtr dwConnId = (IntPtr)Convert.ToUInt32(this.txtDisConn.Text.Trim()); + + // 断开指定客户 + if (server.Disconnect(dwConnId, true)) + { + AddMsg(string.Format("$({0}) Disconnect OK", dwConnId)); + } + else + { + throw new Exception(string.Format("Disconnect({0}) Error", dwConnId)); + } + } + catch (Exception ex) + { + AddMsg(ex.Message); + } + } + + void Reset(bool isSetClientCount = true) + { + if (isSetClientCount) + { + clientCount = 0; + } + + totalReceived = 0; + totalSent = 0; + } + + HandleResult OnPrepareListen(IntPtr soListen) + { + // 监听事件到达了,一般没什么用吧? + + return HandleResult.Ok; + } + + HandleResult OnAccept(IntPtr dwConnId, IntPtr pClient) + { + // 客户进入了 + if (clientCount == 0) + { + lock (title) + { + if (clientCount == 0) + { + Reset(false); + } + } + } + + Interlocked.Increment(ref clientCount); + + // 获取客户端ip和端口 + string ip = string.Empty; + ushort port = 0; + if (server.GetRemoteAddress(dwConnId, ref ip, ref port)) + { + AddMsg(string.Format(" > [{0},OnAccept] -> PASS({1}:{2})", dwConnId, ip.ToString(), port)); + } + else + { + AddMsg(string.Format(" > [{0},OnAccept] -> Server_GetClientAddress() Error", dwConnId)); + } + + return HandleResult.Ok; + } + + HandleResult OnSend(IntPtr dwConnId, IntPtr pData, int iLength) + { + // 服务器发数据了 + Interlocked.Add(ref totalSent, iLength); + + //AddMsg(string.Format(" > [{0},OnSend] -> ({1} bytes)", dwConnId, iLength)); + + return HandleResult.Ok; + } + + HandleResult OnReceive(IntPtr dwConnId, IntPtr pData, int iLength) + { + // 数据到达了 + + Interlocked.Add(ref totalReceived, iLength); + + if (server.Send(dwConnId, pData, iLength)) + { + return HandleResult.Ok; + } + + return HandleResult.Error; + + /*try + {*/ + /* + // 从pData中获取字符串 + // string str = Marshal.PtrToStringAnsi(pData, iLength); + + // intptr转byte[] + // byte[] bytes = new byte[iLength]; + // Marshal.Copy(pData, bytes, 0, iLength); + + + // 获取附加数据 + IntPtr clientPtr = IntPtr.Zero; + if (server.GetConnectionExtra(dwConnId, ref clientPtr)) + { + // ci 就是accept里传入的附加数据了 + ClientInfo ci = (ClientInfo)Marshal.PtrToStructure(clientPtr, typeof(ClientInfo)); + AddMsg(string.Format(" > [{0},OnReceive] -> {1}:{2} ({3} bytes)", ci.ConnId, ci.IpAddress, ci.Port, iLength)); + } + else + { + AddMsg(string.Format(" > [{0},OnReceive] -> ({1} bytes)", dwConnId, iLength)); + } + + if (server.Send(dwConnId, pData, iLength)) + { + return HandleResult.Ok; + } + + return HandleResult.Error;*/ + /*} + catch (Exception) + { + return HandleResult.IGNORE; + }*/ + + + } + + HandleResult OnClose(IntPtr dwConnId) + { + // 客户离开了 + + AddMsg(string.Format(" > [{0},OnClose]", dwConnId)); + Calculate(); + + return HandleResult.Ok; + } + + + HandleResult OnError(IntPtr dwConnId, SocketOperation enOperation, int iErrorCode) + { + // 客户出错了 + + AddMsg(string.Format(" > [{0},OnError] -> OP:{1},CODE:{2}", dwConnId, enOperation, iErrorCode)); + Calculate(); + + return HandleResult.Ok; + } + + HandleResult OnServerShutdown() + { + // 服务关闭了 + + + AddMsg(" > [OnServerShutdown]"); + return HandleResult.Ok; + } + + void Calculate() + { + if(clientCount > 0) + { + lock(title) + { + + if(clientCount > 0) + { + Interlocked.Decrement(ref clientCount); + + if(clientCount == 0) + { + //::WaitWithMessageLoop(600L); + Thread tmpThread = new Thread(ShowTotalMsg); + tmpThread.Start(); + } + } + } + } + } + + void ShowTotalMsg() + { + Thread.Sleep(600); + AddMsg(string.Format(" *** Summary: send - {0}, recv - {1}", totalSent, totalReceived)); + } + + /// + /// 设置程序状态 + /// + /// + void SetAppState(AppState state) + { + appState = state; + this.btnStart.Enabled = (appState == AppState.Stoped); + this.btnStop.Enabled = (appState == AppState.Started); + this.txtIpAddress.Enabled = (appState == AppState.Stoped); + this.txtPort.Enabled = (appState == AppState.Stoped); + this.txtDisConn.Enabled = (appState == AppState.Started); + this.btnDisconn.Enabled = (appState == AppState.Started && this.txtDisConn.Text.Length > 0); + } + + /// + /// 往listbox加一条项目 + /// + /// + void AddMsg(string msg) + { + if (this.lbxMsg.InvokeRequired) + { + // 很帅的调自己 + this.lbxMsg.Invoke(AddMsgDelegate, msg); + } + else + { + if (this.lbxMsg.Items.Count > 100) + { + this.lbxMsg.Items.RemoveAt(0); + } + this.lbxMsg.Items.Add(msg); + this.lbxMsg.TopIndex = this.lbxMsg.Items.Count - (int)(this.lbxMsg.Height / this.lbxMsg.ItemHeight); + } + } + + private void txtDisConn_TextChanged(object sender, EventArgs e) + { + // CONNID框被改变事件 + this.btnDisconn.Enabled = (appState == AppState.Started && this.txtDisConn.Text.Length > 0); + } + + private void lbxMsg_KeyPress(object sender, KeyPressEventArgs e) + { + // 清理listbox + if (e.KeyChar == 'c' || e.KeyChar == 'C') + { + this.lbxMsg.Items.Clear(); + } + else if (e.KeyChar == 'r' || e.KeyChar == 'R') + { + Reset(); + AddMsg(string.Format(" *** Reset Statics: CC - {0}, TS - {1}, TR - {2}", clientCount, totalSent, totalReceived)); + } + } + + private void frmServer_FormClosed(object sender, FormClosedEventArgs e) + { + server.Destroy(); + } + } + + [StructLayout(LayoutKind.Sequential)] + public class ClientInfo + { + public uint ConnId { get; set; } + public string IpAddress { get; set; } + public ushort Port { get; set; } + } +} diff --git a/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpServer-PFM/frmServer.resx b/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpServer-PFM/frmServer.resx new file mode 100644 index 000000000..1af7de150 --- /dev/null +++ b/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpServer-PFM/frmServer.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpServer/Program.cs b/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpServer/Program.cs new file mode 100644 index 000000000..4a3923e91 --- /dev/null +++ b/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpServer/Program.cs @@ -0,0 +1,21 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Windows.Forms; + +namespace TcpServer_PFM +{ + static class Program + { + /// + /// 应用程序的主入口点。 + /// + [STAThread] + static void Main() + { + Application.EnableVisualStyles(); + Application.SetCompatibleTextRenderingDefault(false); + Application.Run(new frmServer()); + } + } +} diff --git a/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpServer/Properties/AssemblyInfo.cs b/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpServer/Properties/AssemblyInfo.cs new file mode 100644 index 000000000..fcd4bd3d3 --- /dev/null +++ b/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpServer/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// 有关程序集的常规信息通过以下 +// 特性集控制。更改这些特性值可修改 +// 与程序集关联的信息。 +[assembly: AssemblyTitle("Server")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("Server")] +[assembly: AssemblyCopyright("Copyright © 2014")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// 将 ComVisible 设置为 false 使此程序集中的类型 +// 对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型, +// 则将该类型上的 ComVisible 特性设置为 true。 +[assembly: ComVisible(false)] + +// 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID +[assembly: Guid("a8f79261-fd62-4f4b-aed5-01bf44660ad1")] + +// 程序集的版本信息由下面四个值组成: +// +// 主版本 +// 次版本 +// 内部版本号 +// 修订号 +// +// 可以指定所有这些值,也可以使用“内部版本号”和“修订号”的默认值, +// 方法是按如下所示使用“*”: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpServer/Properties/Resources.Designer.cs b/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpServer/Properties/Resources.Designer.cs new file mode 100644 index 000000000..fe2b41333 --- /dev/null +++ b/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpServer/Properties/Resources.Designer.cs @@ -0,0 +1,63 @@ +//------------------------------------------------------------------------------ +// +// 此代码由工具生成。 +// 运行时版本:4.0.30319.18444 +// +// 对此文件的更改可能会导致不正确的行为,并且如果 +// 重新生成代码,这些更改将会丢失。 +// +//------------------------------------------------------------------------------ + +namespace TcpServer_PFM.Properties { + using System; + + + /// + /// 一个强类型的资源类,用于查找本地化的字符串等。 + /// + // 此类是由 StronglyTypedResourceBuilder + // 类通过类似于 ResGen 或 Visual Studio 的工具自动生成的。 + // 若要添加或移除成员,请编辑 .ResX 文件,然后重新运行 ResGen + // (以 /str 作为命令选项),或重新生成 VS 项目。 + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// + /// 返回此类使用的缓存的 ResourceManager 实例。 + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("TcpServer_PFM.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// 使用此强类型资源类,为所有资源查找 + /// 重写当前线程的 CurrentUICulture 属性。 + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + } +} diff --git a/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpServer/Properties/Resources.resx b/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpServer/Properties/Resources.resx new file mode 100644 index 000000000..af7dbebba --- /dev/null +++ b/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpServer/Properties/Resources.resx @@ -0,0 +1,117 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpServer/Properties/Settings.Designer.cs b/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpServer/Properties/Settings.Designer.cs new file mode 100644 index 000000000..20366263c --- /dev/null +++ b/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpServer/Properties/Settings.Designer.cs @@ -0,0 +1,26 @@ +//------------------------------------------------------------------------------ +// +// 此代码由工具生成。 +// 运行时版本:4.0.30319.18444 +// +// 对此文件的更改可能会导致不正确的行为,并且如果 +// 重新生成代码,这些更改将会丢失。 +// +//------------------------------------------------------------------------------ + +namespace TcpServer_PFM.Properties { + + + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "10.0.0.0")] + internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { + + private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); + + public static Settings Default { + get { + return defaultInstance; + } + } + } +} diff --git a/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpServer/Properties/Settings.settings b/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpServer/Properties/Settings.settings new file mode 100644 index 000000000..39645652a --- /dev/null +++ b/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpServer/Properties/Settings.settings @@ -0,0 +1,7 @@ + + + + + + + diff --git a/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpServer/TcpServer.csproj b/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpServer/TcpServer.csproj new file mode 100644 index 000000000..5e8be459d --- /dev/null +++ b/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpServer/TcpServer.csproj @@ -0,0 +1,122 @@ + + + + Debug + x86 + 8.0.30703 + 2.0 + {9A3339BC-37F0-4D03-9ACE-51CC4CF75277} + WinExe + Properties + TcpServer_PFM + TcpServer + v4.0 + Client + 512 + + + x86 + true + full + false + ..\bin\x86\Debug\ + DEBUG;TRACE + prompt + 4 + + + x86 + pdbonly + true + ..\bin\x86\Release\ + TRACE + prompt + 4 + + + true + ..\bin\x64\Debug\ + DEBUG;TRACE + full + x64 + ..\bin\Debug\TcpServer.exe.CodeAnalysisLog.xml + true + GlobalSuppressions.cs + prompt + MinimumRecommendedRules.ruleset + ;D:\Program Files\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets + ;D:\Program Files\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules + + + ..\bin\x64\Release\ + TRACE + true + pdbonly + x64 + ..\bin\Release\TcpServer.exe.CodeAnalysisLog.xml + true + GlobalSuppressions.cs + prompt + MinimumRecommendedRules.ruleset + ;D:\Program Files\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets + ;D:\Program Files\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules + + + + + + + + + + + + + + + + Form + + + frmServer.cs + + + + + frmServer.cs + + + ResXFileCodeGenerator + Resources.Designer.cs + Designer + + + True + Resources.resx + True + + + SettingsSingleFileGenerator + Settings.Designer.cs + + + True + Settings.settings + True + + + + + {DFA935E2-CF37-4E26-B697-D7F3DEE19DD8} + HPSocketCS + + + + + \ No newline at end of file diff --git a/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpServer/frmServer.Designer.cs b/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpServer/frmServer.Designer.cs new file mode 100644 index 000000000..cfd0ca76d --- /dev/null +++ b/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpServer/frmServer.Designer.cs @@ -0,0 +1,169 @@ +namespace TcpServer_PFM +{ + partial class frmServer + { + /// + /// 必需的设计器变量。 + /// + private System.ComponentModel.IContainer components = null; + + /// + /// 清理所有正在使用的资源。 + /// + /// 如果应释放托管资源,为 true;否则为 false。 + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows 窗体设计器生成的代码 + + /// + /// 设计器支持所需的方法 - 不要 + /// 使用代码编辑器修改此方法的内容。 + /// + private void InitializeComponent() + { + this.lbxMsg = new System.Windows.Forms.ListBox(); + this.groupBox1 = new System.Windows.Forms.GroupBox(); + this.label1 = new System.Windows.Forms.Label(); + this.btnDisconn = new System.Windows.Forms.Button(); + this.txtDisConn = new System.Windows.Forms.TextBox(); + this.txtPort = new System.Windows.Forms.TextBox(); + this.txtIpAddress = new System.Windows.Forms.TextBox(); + this.btnStop = new System.Windows.Forms.Button(); + this.btnStart = new System.Windows.Forms.Button(); + this.groupBox1.SuspendLayout(); + this.SuspendLayout(); + // + // lbxMsg + // + this.lbxMsg.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.lbxMsg.FormattingEnabled = true; + this.lbxMsg.ItemHeight = 12; + this.lbxMsg.Location = new System.Drawing.Point(11, 62); + this.lbxMsg.Name = "lbxMsg"; + this.lbxMsg.Size = new System.Drawing.Size(465, 304); + this.lbxMsg.TabIndex = 4; + this.lbxMsg.KeyPress += new System.Windows.Forms.KeyPressEventHandler(this.lbxMsg_KeyPress); + // + // groupBox1 + // + this.groupBox1.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.groupBox1.Controls.Add(this.label1); + this.groupBox1.Controls.Add(this.btnDisconn); + this.groupBox1.Controls.Add(this.txtDisConn); + this.groupBox1.Controls.Add(this.txtPort); + this.groupBox1.Controls.Add(this.txtIpAddress); + this.groupBox1.Controls.Add(this.btnStop); + this.groupBox1.Controls.Add(this.btnStart); + this.groupBox1.Location = new System.Drawing.Point(12, 2); + this.groupBox1.Name = "groupBox1"; + this.groupBox1.Size = new System.Drawing.Size(462, 47); + this.groupBox1.TabIndex = 9; + this.groupBox1.TabStop = false; + // + // label1 + // + this.label1.AutoSize = true; + this.label1.Location = new System.Drawing.Point(132, 22); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(41, 12); + this.label1.TabIndex = 15; + this.label1.Text = "CONNID"; + // + // btnDisconn + // + this.btnDisconn.Location = new System.Drawing.Point(223, 15); + this.btnDisconn.Name = "btnDisconn"; + this.btnDisconn.Size = new System.Drawing.Size(33, 26); + this.btnDisconn.TabIndex = 14; + this.btnDisconn.Text = "Dis"; + this.btnDisconn.UseVisualStyleBackColor = true; + this.btnDisconn.Click += new System.EventHandler(this.btnDisconn_Click); + // + // txtDisConn + // + this.txtDisConn.Location = new System.Drawing.Point(178, 18); + this.txtDisConn.Name = "txtDisConn"; + this.txtDisConn.Size = new System.Drawing.Size(40, 21); + this.txtDisConn.TabIndex = 13; + this.txtDisConn.TextChanged += new System.EventHandler(this.txtDisConn_TextChanged); + // + // txtPort + // + this.txtPort.Location = new System.Drawing.Point(88, 18); + this.txtPort.Name = "txtPort"; + this.txtPort.Size = new System.Drawing.Size(40, 21); + this.txtPort.TabIndex = 12; + this.txtPort.Text = "5555"; + // + // txtIpAddress + // + this.txtIpAddress.Location = new System.Drawing.Point(11, 18); + this.txtIpAddress.Name = "txtIpAddress"; + this.txtIpAddress.Size = new System.Drawing.Size(71, 21); + this.txtIpAddress.TabIndex = 11; + this.txtIpAddress.Text = "0.0.0.0"; + // + // btnStop + // + this.btnStop.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.btnStop.Location = new System.Drawing.Point(403, 15); + this.btnStop.Name = "btnStop"; + this.btnStop.Size = new System.Drawing.Size(47, 26); + this.btnStop.TabIndex = 10; + this.btnStop.Text = "Stop"; + this.btnStop.UseVisualStyleBackColor = true; + this.btnStop.Click += new System.EventHandler(this.btnStop_Click); + // + // btnStart + // + this.btnStart.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.btnStart.Location = new System.Drawing.Point(350, 15); + this.btnStart.Name = "btnStart"; + this.btnStart.Size = new System.Drawing.Size(47, 26); + this.btnStart.TabIndex = 9; + this.btnStart.Text = "Start"; + this.btnStart.UseVisualStyleBackColor = true; + this.btnStart.Click += new System.EventHandler(this.btnStart_Click); + // + // frmServer + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(486, 377); + this.Controls.Add(this.groupBox1); + this.Controls.Add(this.lbxMsg); + this.Name = "frmServer"; + this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen; + this.Text = "Form1"; + this.FormClosed += new System.Windows.Forms.FormClosedEventHandler(this.frmServer_FormClosed); + this.Load += new System.EventHandler(this.Form1_Load); + this.groupBox1.ResumeLayout(false); + this.groupBox1.PerformLayout(); + this.ResumeLayout(false); + + } + + #endregion + + private System.Windows.Forms.ListBox lbxMsg; + private System.Windows.Forms.GroupBox groupBox1; + private System.Windows.Forms.Label label1; + private System.Windows.Forms.Button btnDisconn; + private System.Windows.Forms.TextBox txtDisConn; + private System.Windows.Forms.TextBox txtPort; + private System.Windows.Forms.Button btnStop; + private System.Windows.Forms.Button btnStart; + private System.Windows.Forms.TextBox txtIpAddress; + } +} + diff --git a/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpServer/frmServer.cs b/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpServer/frmServer.cs new file mode 100644 index 000000000..c4aa4194e --- /dev/null +++ b/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpServer/frmServer.cs @@ -0,0 +1,318 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Windows.Forms; +using System.Runtime.InteropServices; +using HPSocketCS; + +namespace TcpServer_PFM +{ + public enum AppState + { + Starting, Started, Stoping, Stoped, Error + } + + public partial class frmServer : Form + { + private AppState appState = AppState.Stoped; + + private delegate void ShowMsg(string msg); + private ShowMsg AddMsgDelegate; + + HPSocketCS.TcpServer server = new HPSocketCS.TcpServer(); + + private string title = "Echo TcpServer [ 'C' - clear list box ]"; + public frmServer() + { + InitializeComponent(); + } + + private void Form1_Load(object sender, EventArgs e) + { + try + { + + this.Text = title; + // 本机测试没必要改地址,有需求请注释或删除 + this.txtIpAddress.ReadOnly = true; + + // 加个委托显示msg,因为on系列都是在工作线程中调用的,ui不允许直接操作 + AddMsgDelegate = new ShowMsg(AddMsg); + + + // 设置回调函数 + server.SetCallback(OnPrepareListen, OnAccept, OnSend, OnReceive, OnClose, OnError, OnServerShutdown); + + SetAppState(AppState.Stoped); + } + catch (Exception ex) + { + SetAppState(AppState.Error); + AddMsg(ex.Message); + } + } + + private void btnStart_Click(object sender, EventArgs e) + { + try + { + String ip = this.txtIpAddress.Text.Trim(); + ushort port = ushort.Parse(this.txtPort.Text.Trim()); + + // 写在这个位置是上面可能会异常 + SetAppState(AppState.Starting); + + // 启动服务 + if (server.Start(ip, port)) + { + this.Text = string.Format("{2} - ({0}:{1})", ip, port, title); + SetAppState(AppState.Started); + throw new Exception(string.Format("$Server Start OK -> ({0}:{1})", ip, port)); + } + else + { + SetAppState(AppState.Stoped); + throw new Exception(string.Format("$Server Start Error -> {0}({1})", server.GetLastErrorDesc(), server.GetlastError())); + } + } + catch (Exception ex) + { + AddMsg(ex.Message); + } + } + + private void btnStop_Click(object sender, EventArgs e) + { + SetAppState(AppState.Stoping); + + // 停止服务 + AddMsg("$Server Stop"); + if (server.Stop()) + { + this.Text = title; + SetAppState(AppState.Stoped); + } + else + { + AddMsg(string.Format("$Stop Error -> {0}({1})", server.GetLastErrorDesc(), server.GetlastError())); + } + } + + private void btnDisconn_Click(object sender, EventArgs e) + { + try + { + // 未做64位判断 + IntPtr connId = (IntPtr)Convert.ToInt32(this.txtDisConn.Text.Trim()); + // 断开指定客户 + if (server.Disconnect(connId, true)) + { + AddMsg(string.Format("$({0}) Disconnect OK", connId)); + } + else + { + throw new Exception(string.Format("Disconnect({0}) Error", connId)); + } + } + catch (Exception ex) + { + AddMsg(ex.Message); + } + } + + + HandleResult OnPrepareListen(IntPtr soListen) + { + // 监听事件到达了,一般没什么用吧? + + return HandleResult.Ok; + } + + HandleResult OnAccept(IntPtr dwConnId, IntPtr pClient) + { + // 客户进入了 + + + // 获取客户端ip和端口 + string ip = string.Empty; + ushort port = 0; + if (server.GetRemoteAddress(dwConnId, ref ip, ref port)) + { + AddMsg(string.Format(" > [{0},OnAccept] -> PASS({1}:{2})", dwConnId, ip.ToString(), port)); + } + else + { + AddMsg(string.Format(" > [{0},OnAccept] -> Server_GetClientAddress() Error", dwConnId)); + } + + + // 设置附加数据 + ClientInfo ci = new ClientInfo(); + ci.ConnId = dwConnId; + ci.IpAddress = ip; + ci.Port = port; + if (server.SetConnectionExtra(dwConnId, ci) == false) + { + AddMsg(string.Format(" > [{0},OnAccept] -> SetConnectionExtra fail", dwConnId)); + } + + return HandleResult.Ok; + } + + HandleResult OnSend(IntPtr dwConnId, IntPtr pData, int iLength) + { + // 服务器发数据了 + + + AddMsg(string.Format(" > [{0},OnSend] -> ({1} bytes)", dwConnId, iLength)); + + return HandleResult.Ok; + } + + HandleResult OnReceive(IntPtr dwConnId, IntPtr pData, int iLength) + { + // 数据到达了 + try + { + // 从pData中获取字符串 + // string str = Marshal.PtrToStringAnsi(pData, iLength); + + // intptr转byte[] + // byte[] bytes = new byte[iLength]; + // Marshal.Copy(pData, bytes, 0, iLength); + + + // 获取附加数据 + IntPtr clientPtr = IntPtr.Zero; + if (server.GetConnectionExtra(dwConnId, ref clientPtr)) + { + // ci 就是accept里传入的附加数据了 + ClientInfo ci = (ClientInfo)Marshal.PtrToStructure(clientPtr, typeof(ClientInfo)); + AddMsg(string.Format(" > [{0},OnReceive] -> {1}:{2} ({3} bytes)", ci.ConnId, ci.IpAddress, ci.Port, iLength)); + } + else + { + AddMsg(string.Format(" > [{0},OnReceive] -> ({1} bytes)", dwConnId, iLength)); + } + + if (server.Send(dwConnId, pData, iLength)) + { + return HandleResult.Ok; + } + + return HandleResult.Error; + } + catch (Exception) + { + + return HandleResult.Ignore; + } + } + + HandleResult OnClose(IntPtr dwConnId) + { + // 客户离开了 + + + // 释放附加数据 + if (server.SetConnectionExtra(dwConnId, null) == false) + { + AddMsg(string.Format(" > [{0},OnClose] -> SetConnectionExtra({0}, null) fail", dwConnId)); + } + + + AddMsg(string.Format(" > [{0},OnClose]", dwConnId)); + return HandleResult.Ok; + } + + HandleResult OnError(IntPtr dwConnId, SocketOperation enOperation, int iErrorCode) + { + // 客户出错了 + + AddMsg(string.Format(" > [{0},OnError] -> OP:{1},CODE:{2}", dwConnId, enOperation, iErrorCode)); + // return HPSocketSdk.HandleResult.Ok; + + // 因为要释放附加数据,所以直接返回OnClose()了 + return OnClose(dwConnId); + } + + HandleResult OnServerShutdown() + { + // 服务关闭了 + + + AddMsg(" > [OnServerShutdown]"); + return HandleResult.Ok; + } + + + /// + /// 设置程序状态 + /// + /// + void SetAppState(AppState state) + { + appState = state; + this.btnStart.Enabled = (appState == AppState.Stoped); + this.btnStop.Enabled = (appState == AppState.Started); + this.txtIpAddress.Enabled = (appState == AppState.Stoped); + this.txtPort.Enabled = (appState == AppState.Stoped); + this.txtDisConn.Enabled = (appState == AppState.Started); + this.btnDisconn.Enabled = (appState == AppState.Started && this.txtDisConn.Text.Length > 0); + } + + /// + /// 往listbox加一条项目 + /// + /// + void AddMsg(string msg) + { + if (this.lbxMsg.InvokeRequired) + { + // 很帅的调自己 + this.lbxMsg.Invoke(AddMsgDelegate, msg); + } + else + { + if (this.lbxMsg.Items.Count > 100) + { + this.lbxMsg.Items.RemoveAt(0); + } + this.lbxMsg.Items.Add(msg); + this.lbxMsg.TopIndex = this.lbxMsg.Items.Count - (int)(this.lbxMsg.Height / this.lbxMsg.ItemHeight); + } + } + + private void txtDisConn_TextChanged(object sender, EventArgs e) + { + // CONNID框被改变事件 + this.btnDisconn.Enabled = (appState == AppState.Started && this.txtDisConn.Text.Length > 0); + } + + private void lbxMsg_KeyPress(object sender, KeyPressEventArgs e) + { + // 清理listbox + if (e.KeyChar == 'c' || e.KeyChar == 'C') + { + this.lbxMsg.Items.Clear(); + } + } + + private void frmServer_FormClosed(object sender, FormClosedEventArgs e) + { + server.Destroy(); + } + } + + [StructLayout(LayoutKind.Sequential)] + public class ClientInfo + { + public IntPtr ConnId { get; set; } + public string IpAddress { get; set; } + public ushort Port { get; set; } + } +} diff --git a/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpServer/frmServer.resx b/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpServer/frmServer.resx new file mode 100644 index 000000000..1af7de150 --- /dev/null +++ b/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/TcpServer/frmServer.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/bin/x64/Release/HPSocket4C_U.dll b/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/bin/x64/Release/HPSocket4C_U.dll new file mode 100644 index 0000000000000000000000000000000000000000..ae1871aae7346d1d459d19d16f3b6463354be6ef GIT binary patch literal 216064 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 TX<$zSdm7l&z@7$Ps|NlK46$h- literal 0 HcmV?d00001 diff --git a/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/bin/x64/Release/HPSocketCS.dll b/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/bin/x64/Release/HPSocketCS.dll new file mode 100644 index 0000000000000000000000000000000000000000..230d0dcaed8a30cb411b4dc3538796637d043dc4 GIT binary patch literal 44544 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 J0RMMz{XZ3O`b_`; literal 0 HcmV?d00001 diff --git a/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/bin/x64/Release/TcpClient.exe b/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/bin/x64/Release/TcpClient.exe new file mode 100644 index 0000000000000000000000000000000000000000..8c24ceca65d4757838650a787b79bb78894951c2 GIT binary patch literal 19456 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 Y3vA!9vE&2@?AYkf5C{a;zoXCp0v5IG0ssI2 literal 0 HcmV?d00001 diff --git a/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/bin/x64/Release/TcpProxyServer.exe b/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/bin/x64/Release/TcpProxyServer.exe new file mode 100644 index 0000000000000000000000000000000000000000..3edd151d25512e6d231bc70762828eee7e414bf8 GIT binary patch literal 18432 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 NM+gW<*8hE<{{?U2GPeK# literal 0 HcmV?d00001 diff --git a/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/bin/x64/Release/TcpPullClient.exe b/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/bin/x64/Release/TcpPullClient.exe new file mode 100644 index 0000000000000000000000000000000000000000..810c6953b6d667249ddc7fe3d4d7b6457edc3ef2 GIT binary patch literal 15360 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 NH$osdvi|ix{|B6l%d`Lh literal 0 HcmV?d00001 diff --git a/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/bin/x64/Release/TcpServer-PFM.exe b/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/bin/x64/Release/TcpServer-PFM.exe new file mode 100644 index 0000000000000000000000000000000000000000..53d68de1cd286d46157209955e8131973e1b5264 GIT binary patch literal 15360 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 Q;EIhw4}sv!`rW<$4?_h)761SM literal 0 HcmV?d00001 diff --git a/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/bin/x64/Release/TcpServer.exe b/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/bin/x64/Release/TcpServer.exe new file mode 100644 index 0000000000000000000000000000000000000000..3bca722169f606e8d1d312eb7093d7856eaac999 GIT binary patch literal 15360 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 literal 0 HcmV?d00001 diff --git a/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/bin/x86/Release/HPSocket4C_U.dll b/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/bin/x86/Release/HPSocket4C_U.dll new file mode 100644 index 0000000000000000000000000000000000000000..6bacb6a5e5eec303d411db97ab06692848ff7f61 GIT binary patch literal 181760 zcmeFa4R}=5wLd(Q49NipW`KZEqeP80ZMcdKD(S=$3^R!(A2a!wNrhyvMgM71k-uvG7d0sSU&faJ3ueH}&d+oLNUc2m$jh0l4#bU!>JZ`aU#V`FUVx``7fY{YT=Pto4s*E%@Iir^bsUxyZ))SZii#tDTi+Fwa2VS$F@+6xQDnZ_Qve zQn1pm{&SPnf-lim?AF!{>nbTPhJrh~R{sFCs1LC}*6oyr)UV7bmko66ajZWH3{(Yz zJ>!+9atIkL&Q?j$)sn@r{tyLkVf7h#^-lK@6ncbtovh4W<@2l8Qkj7aYrWH2Xa8ay z6`mJxIyyE{ni=kpEj)o0+2nNDC-qG3I2xW9OQ+mp#hg)GUGBr-@o1Y|B*iNv){Mr@ za+en_FH%~a!T7YyKC6>?XS(*dcZ4(LS{n<@l&hq;cUDlYpBbN)h0i_zATN;Q1vU|x zn~0xQNfBkH3$mfKsn+@sVx ztCEYq1UE8i=%&dM*I)jEY$%w*GLzl}{|!I`pO>KVr-$rZUQV3UJ0 zS-E7bm?fvlUYqQdP;ElX!uoFYwQ&}UJ5;!A0t*$ekJXoecSIWmS`~C1b;a}RXSEh9 zUMFfv*rwo@SZl7kbtZ_k7&+$3wNlRn_qp&?xt`FAxAAhwCWoYW`7Du;3Ur@~6wbQ>-`F?WJ0m*yQqD`Fm9B7;4Qs1#jbt zms+USK4xK3P@@dAc=ao6)d0wi+Ch9Ga1?E|Ssd+80&78PrYkNArGBx6GX%Ed)2dHe zowC=y9X)GFV51`*ZdAOv%Dql?+Nbfja&NUx&C$I8IpzJN^vCHKJa`_zj z`Q7*)kM5^p<>v`l)Qd5Sa+&IlQM9u--u^bK)Kz*Hd9exh`a@M_l7s{zAVDJ-JMiscnT|-BX1yp*t`NfEj?2} zsgqoLM5MgIXog(|WJy7M17**qD$8@_ntrtcW4Ka8RAmQJSy?}uT-9i))L6l&&4y+$ zBKWZEG8Ma*?<3vY(k4q+$Sn+I{*$=fqg z;Z0DVL~S5^&$y0?^qgQn3QuNbQb;bhv0bPFFPL52SXhNx67fPBcqFCV>6gDkon0@* zr%8y8#+-8N?2upvxqen6vB6p5h4+WVTc9*IxsC?px_(i0=FRQsYE3HybM;&unUr6j z6Um5qbBTm{rpBjbqm+D5vP1&QVy({(2;4w?+A(f4#({yEfKkc@{7NTj6H1+={ydXQ ze|P5-hzO5kE%u&NwyGa#g%qVCFDgNik#Xt|A%wL|!DM>lht|I_-k`o?buJ+$u=t|A z&Z@wZT^m!JuHX6;&*>#Up=c%4#6FVij;rs06l0zNienp|pr=*#^g(i$^rS0GaxgUY zu|hkOl%=_{r&lgh)i0raEYhn4oIp9J6OYQIK%+$$+BJPFh4SESioC3Bp~kAwX;zCS zowsrf73D^%TxY7}Wd#@!7MKFGT2Sf0iBg7<4qYb>Be_EE0$P=O?*iQM=X&iQvJThy9XQ&MIygdYIRq! z%V|X0$kN;pL=#BdO(JPG9y0E7&}yp6 zI+KB(t76p2kV9N$K*Z!&A*r&KSRn_B-!AF$&+pokzd&lO4FpNPx!v~?ev0SFsSr@W z&)IN+d=Yd7ytw3wIdVloe1XK$m1a=Hfch8->Ix@1pOa$EfO+(G?df?oRG(C9u3Hf4 zXblOlSsI=N1IB>o)? zI^JC?A+e?BPpro2-cQoh9;%1>Doa|QF+*aW%6=0?_GCuLmPXJdYw zGQZCzJJn232+{)>n3Ir+l@COuj*`9uk#M9q_h_*c?ZrUCnjzD^mv(sE%BxbG>~$#a zN1@;E(PQ2{d!%mQh-cv4BkvtM^UAzPtE;OGBpsizTq;aG6YWo32^2XQ^r~W;5_Hm} z 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
S(rU!WNYO7 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 z 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

lP>+2>C4e`cQN|IPP!bg|D_@4CM0 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 literal 0 HcmV?d00001 diff --git a/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/bin/x86/Release/HPSocketCS.dll b/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/bin/x86/Release/HPSocketCS.dll new file mode 100644 index 0000000000000000000000000000000000000000..230d0dcaed8a30cb411b4dc3538796637d043dc4 GIT binary patch literal 44544 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 literal 0 HcmV?d00001 diff --git a/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/bin/x86/Release/TcpClient.exe b/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/bin/x86/Release/TcpClient.exe new file mode 100644 index 0000000000000000000000000000000000000000..5a737fc3708ab94c127f0a66d38599f2f58ab7be GIT binary patch literal 19968 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 Kzv=&L5BwMU<3&~g literal 0 HcmV?d00001 diff --git a/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/bin/x86/Release/TcpPullServer.exe b/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/bin/x86/Release/TcpPullServer.exe new file mode 100644 index 0000000000000000000000000000000000000000..f6abd1c315b928a6a7d1839540a37716bb04486d GIT binary patch literal 16896 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 literal 0 HcmV?d00001 diff --git a/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/bin/x86/Release/TcpServer.exe b/HP-Socket/Demo/Other Languages Demos/C#/HPSocket4CS/bin/x86/Release/TcpServer.exe new file mode 100644 index 0000000000000000000000000000000000000000..f2d99e068043ec93cedb1ce8027ab5c121d36fd4 GIT binary patch literal 15872 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