├── .gitignore
├── Common
└── SetMaxTCPConnection.reg
├── ITnmg.IOCPSocket.Interface
├── ISocketBufferProcess.cs
├── ITnmg.IOCPSocket.Interface.csproj
├── Properties
│ └── AssemblyInfo.cs
├── SocketBuffer.cs
├── SocketBufferQueue.cs
└── SocketProtocolTcpBase.cs
├── ITnmg.IOCPSocket.WPFServer
├── App.config
├── App.xaml
├── App.xaml.cs
├── ITnmg.IOCPSocket.WPFServer.csproj
├── MainWindow.xaml
├── MainWindow.xaml.cs
├── Properties
│ ├── AssemblyInfo.cs
│ ├── Resources.Designer.cs
│ ├── Resources.resx
│ ├── Settings.Designer.cs
│ └── Settings.settings
├── Resources
│ ├── Entypo-license.txt
│ ├── Entypo.ttf
│ ├── Icons.xaml
│ ├── IconsNonShared.xaml
│ └── WindowsIcons-license.txt
├── ViewModel
│ ├── MainViewModel.cs
│ └── ViewModelLocator.cs
└── packages.config
├── ITnmg.IOCPSocket.WinFormClient
├── App.config
├── F_Main.Designer.cs
├── F_Main.cs
├── F_Main.resx
├── ITnmg.IOCPSocket.WinFormClient.csproj
├── Program.cs
└── Properties
│ ├── AssemblyInfo.cs
│ ├── Resources.Designer.cs
│ ├── Resources.resx
│ ├── Settings.Designer.cs
│ └── Settings.settings
├── ITnmg.IOCPSocket.WinFormServer
├── App.config
├── F_Main.Designer.cs
├── F_Main.cs
├── F_Main.resx
├── ITnmg.IOCPSocket.WinFormServer.csproj
├── Program.cs
└── Properties
│ ├── AssemblyInfo.cs
│ ├── Resources.Designer.cs
│ ├── Resources.resx
│ ├── Settings.Designer.cs
│ └── Settings.settings
├── ITnmg.IOCPSocket.sln
├── ITnmg.IOCPSocket
├── ITnmg.IOCPSocket.csproj
├── Properties
│ └── AssemblyInfo.cs
├── SocketAsyncEventArgsPool.cs
├── SocketClientManager.cs
├── SocketManagerBase.cs
├── SocketServerManager.cs
├── SocketStatusChangeArgs.cs
├── SocketUserToken.cs
└── TextProtocol.cs
└── README.md
/.gitignore:
--------------------------------------------------------------------------------
1 | ## Ignore Visual Studio temporary files, build results, and
2 | ## files generated by popular Visual Studio add-ons.
3 |
4 | # User-specific files
5 | *.suo
6 | *.user
7 | *.userosscache
8 | *.sln.docstates
9 |
10 | # User-specific files (MonoDevelop/Xamarin Studio)
11 | *.userprefs
12 |
13 | # Build results
14 | [Dd]ebug/
15 | [Dd]ebugPublic/
16 | [Rr]elease/
17 | [Rr]eleases/
18 | [Xx]64/
19 | [Xx]86/
20 | [Bb]uild/
21 | bld/
22 | [Bb]in/
23 | [Oo]bj/
24 |
25 | # Visual Studio 2015 cache/options directory
26 | .vs/
27 | # Uncomment if you have tasks that create the project's static files in wwwroot
28 | #wwwroot/
29 |
30 | # MSTest test Results
31 | [Tt]est[Rr]esult*/
32 | [Bb]uild[Ll]og.*
33 |
34 | # NUNIT
35 | *.VisualState.xml
36 | TestResult.xml
37 |
38 | # Build Results of an ATL Project
39 | [Dd]ebugPS/
40 | [Rr]eleasePS/
41 | dlldata.c
42 |
43 | # DNX
44 | project.lock.json
45 | artifacts/
46 |
47 | *_i.c
48 | *_p.c
49 | *_i.h
50 | *.ilk
51 | *.meta
52 | *.obj
53 | *.pch
54 | *.pdb
55 | *.pgc
56 | *.pgd
57 | *.rsp
58 | *.sbr
59 | *.tlb
60 | *.tli
61 | *.tlh
62 | *.tmp
63 | *.tmp_proj
64 | *.log
65 | *.vspscc
66 | *.vssscc
67 | .builds
68 | *.pidb
69 | *.svclog
70 | *.scc
71 |
72 | # Chutzpah Test files
73 | _Chutzpah*
74 |
75 | # Visual C++ cache files
76 | ipch/
77 | *.aps
78 | *.ncb
79 | *.opendb
80 | *.opensdf
81 | *.sdf
82 | *.cachefile
83 | *.VC.db
84 |
85 | # Visual Studio profiler
86 | *.psess
87 | *.vsp
88 | *.vspx
89 | *.sap
90 |
91 | # TFS 2012 Local Workspace
92 | $tf/
93 |
94 | # Guidance Automation Toolkit
95 | *.gpState
96 |
97 | # ReSharper is a .NET coding add-in
98 | _ReSharper*/
99 | *.[Rr]e[Ss]harper
100 | *.DotSettings.user
101 |
102 | # JustCode is a .NET coding add-in
103 | .JustCode
104 |
105 | # TeamCity is a build add-in
106 | _TeamCity*
107 |
108 | # DotCover is a Code Coverage Tool
109 | *.dotCover
110 |
111 | # NCrunch
112 | _NCrunch_*
113 | .*crunch*.local.xml
114 | nCrunchTemp_*
115 |
116 | # MightyMoose
117 | *.mm.*
118 | AutoTest.Net/
119 |
120 | # Web workbench (sass)
121 | .sass-cache/
122 |
123 | # Installshield output folder
124 | [Ee]xpress/
125 |
126 | # DocProject is a documentation generator add-in
127 | DocProject/buildhelp/
128 | DocProject/Help/*.HxT
129 | DocProject/Help/*.HxC
130 | DocProject/Help/*.hhc
131 | DocProject/Help/*.hhk
132 | DocProject/Help/*.hhp
133 | DocProject/Help/Html2
134 | DocProject/Help/html
135 |
136 | # Click-Once directory
137 | publish/
138 |
139 | # Publish Web Output
140 | *.[Pp]ublish.xml
141 | *.azurePubxml
142 |
143 | # TODO: Un-comment the next line if you do not want to checkin
144 | # your web deploy settings because they may include unencrypted
145 | # passwords
146 | #*.pubxml
147 | *.publishproj
148 |
149 | # NuGet Packages
150 | *.nupkg
151 | # The packages folder can be ignored because of Package Restore
152 | **/packages/*
153 | # except build/, which is used as an MSBuild target.
154 | !**/packages/build/
155 | # Uncomment if necessary however generally it will be regenerated when needed
156 | #!**/packages/repositories.config
157 | # NuGet v3's project.json files produces more ignoreable files
158 | *.nuget.props
159 | *.nuget.targets
160 |
161 | # Microsoft Azure Build Output
162 | csx/
163 | *.build.csdef
164 |
165 | # Microsoft Azure Emulator
166 | ecf/
167 | rcf/
168 |
169 | # Windows Store app package directory
170 | AppPackages/
171 | BundleArtifacts/
172 |
173 | # Visual Studio cache files
174 | # files ending in .cache can be ignored
175 | *.[Cc]ache
176 | # but keep track of directories ending in .cache
177 | !*.[Cc]ache/
178 |
179 | # Others
180 | ClientBin/
181 | [Ss]tyle[Cc]op.*
182 | ~$*
183 | *~
184 | *.dbmdl
185 | *.dbproj.schemaview
186 | *.pfx
187 | *.publishsettings
188 | node_modules/
189 | orleans.codegen.cs
190 |
191 | # RIA/Silverlight projects
192 | Generated_Code/
193 |
194 | # Backup & report files from converting an old project file
195 | # to a newer Visual Studio version. Backup files are not needed,
196 | # because we have git ;-)
197 | _UpgradeReport_Files/
198 | Backup*/
199 | UpgradeLog*.XML
200 | UpgradeLog*.htm
201 |
202 | # SQL Server files
203 | *.mdf
204 | *.ldf
205 |
206 | # Business Intelligence projects
207 | *.rdl.data
208 | *.bim.layout
209 | *.bim_*.settings
210 |
211 | # Microsoft Fakes
212 | FakesAssemblies/
213 |
214 | # GhostDoc plugin setting file
215 | *.GhostDoc.xml
216 |
217 | # Node.js Tools for Visual Studio
218 | .ntvs_analysis.dat
219 |
220 | # Visual Studio 6 build log
221 | *.plg
222 |
223 | # Visual Studio 6 workspace options file
224 | *.opt
225 |
226 | # Visual Studio LightSwitch build output
227 | **/*.HTMLClient/GeneratedArtifacts
228 | **/*.DesktopClient/GeneratedArtifacts
229 | **/*.DesktopClient/ModelManifest.xml
230 | **/*.Server/GeneratedArtifacts
231 | **/*.Server/ModelManifest.xml
232 | _Pvt_Extensions
233 |
234 | # LightSwitch generated files
235 | GeneratedArtifacts/
236 | ModelManifest.xml
237 |
238 | # Paket dependency manager
239 | .paket/paket.exe
240 |
241 | # FAKE - F# Make
242 | .fake/
243 |
--------------------------------------------------------------------------------
/Common/SetMaxTCPConnection.reg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jgh004/ITnmg.IOCPSocket/aa7bda956e53184f7a830347bb342f348cd236bd/Common/SetMaxTCPConnection.reg
--------------------------------------------------------------------------------
/ITnmg.IOCPSocket.Interface/ISocketBufferProcess.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 |
7 | namespace ITnmg.IOCPSocket
8 | {
9 | ///
10 | /// Socket 协议
11 | ///
12 | public interface ISocketBufferProcess
13 | {
14 | ///
15 | /// 处理 Socket 接收到的数据, 返回处理结果, 同时输出未能处理的数据(因为粘包或数据不全等原因)
16 | ///
17 | /// 收到的数据
18 | /// buffer 中有效数据的长度
19 | /// 处理结果
20 | bool ProcessReceive( byte[] buffer, int effectiveLength );
21 |
22 | ///
23 | /// 返回下一个要发送的数据
24 | ///
25 | /// 要发送的数据, 为避免频繁创建对象影响性能, 应直接向 buffer 写入数据, 不要用 new buffer[].
26 | /// 如果 buffer 容纳不下当前要发送的数据则先写入 buffer 最大容量的数据, 其他的数据下次再发.
27 | /// buffer 中有效数据的长度
28 | void GetNextSendBuffer( ref byte[] buffer, ref int effectiveLength );
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/ITnmg.IOCPSocket.Interface/ITnmg.IOCPSocket.Interface.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | {AEFCEBA4-0E8E-429D-AD10-4ACE3BF794FF}
8 | Library
9 | Properties
10 | ITnmg.IOCPSocket
11 | ITnmg.IOCPSocket.Interface
12 | v4.6.2
13 | 512
14 |
15 |
16 |
17 | true
18 | full
19 | false
20 | bin\Debug\
21 | DEBUG;TRACE
22 | prompt
23 | 4
24 |
25 |
26 | pdbonly
27 | true
28 | bin\Release\
29 | TRACE
30 | prompt
31 | 4
32 |
33 |
34 | true
35 | bin\x64\Debug\
36 | DEBUG;TRACE
37 | full
38 | x64
39 | prompt
40 | MinimumRecommendedRules.ruleset
41 |
42 |
43 | bin\x64\Release\
44 | TRACE
45 | true
46 | pdbonly
47 | x64
48 | prompt
49 | MinimumRecommendedRules.ruleset
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
75 |
--------------------------------------------------------------------------------
/ITnmg.IOCPSocket.Interface/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // 有关程序集的一般信息由以下
6 | // 控制。更改这些特性值可修改
7 | // 与程序集关联的信息。
8 | [assembly: AssemblyTitle("SocketStressTestInterface")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("")]
12 | [assembly: AssemblyProduct("SocketStressTestInterface")]
13 | [assembly: AssemblyCopyright("Copyright © 2016")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | //将 ComVisible 设置为 false 将使此程序集中的类型
18 | //对 COM 组件不可见。 如果需要从 COM 访问此程序集中的类型,
19 | //请将此类型的 ComVisible 特性设置为 true。
20 | [assembly: ComVisible(false)]
21 |
22 | // 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID
23 | [assembly: Guid("aefceba4-0e8e-429d-ad10-4ace3bf794ff")]
24 |
25 | // 程序集的版本信息由下列四个值组成:
26 | //
27 | // 主版本
28 | // 次版本
29 | // 生成号
30 | // 修订号
31 | //
32 | //可以指定所有这些值,也可以使用“生成号”和“修订号”的默认值,
33 | // 方法是按如下所示使用“*”: :
34 | // [assembly: AssemblyVersion("1.0.*")]
35 | [assembly: AssemblyVersion("1.0.0.0")]
36 | [assembly: AssemblyFileVersion("1.0.0.0")]
37 |
--------------------------------------------------------------------------------
/ITnmg.IOCPSocket.Interface/SocketBuffer.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 |
7 | namespace ITnmg.IOCPSocket
8 | {
9 | ///
10 | /// Socket 收发数据的缓存
11 | ///
12 | public class SocketBuffer
13 | {
14 | ///
15 | /// 获取或设置缓存内容
16 | ///
17 | public byte[] Buffer
18 | {
19 | get; set;
20 | }
21 |
22 | ///
23 | /// 获取或设置缓存中有效数据的长度
24 | ///
25 | public int Length
26 | {
27 | get; set;
28 | }
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/ITnmg.IOCPSocket.Interface/SocketBufferQueue.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Concurrent;
3 | using System.Collections.Generic;
4 | using System.Linq;
5 | using System.Text;
6 | using System.Threading.Tasks;
7 |
8 | namespace ITnmg.IOCPSocket
9 | {
10 | ///
11 | /// Socket 缓存队列
12 | ///
13 | public class SocketBufferQueue
14 | {
15 | ///
16 | /// 获取或设置不完整的缓存数组中有效数据长度
17 | ///
18 | public int FragmentaryBufferLength
19 | {
20 | get; set;
21 | }
22 |
23 | ///
24 | /// 获取或设置处理过后返回的不完整的数据
25 | ///
26 | public byte[] FragmentaryBuffer
27 | {
28 | get; set;
29 | }
30 |
31 | ///
32 | /// Socket 缓存队列
33 | ///
34 | public ConcurrentQueue BufferQueue
35 | {
36 | get; set;
37 | }
38 |
39 |
40 | public SocketBufferQueue()
41 | {
42 | BufferQueue = new ConcurrentQueue();
43 | }
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/ITnmg.IOCPSocket.Interface/SocketProtocolTcpBase.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 |
7 | namespace ITnmg.IOCPSocket
8 | {
9 | public abstract class SocketBufferProcessTcpBase : ISocketBufferProcess
10 | {
11 | ///
12 | /// 接收缓存锁定用
13 | ///
14 | private object receiveLock = new object();
15 |
16 | private SocketBufferQueue receiveBufferQueue;
17 |
18 | private SocketBufferQueue sendBufferQueue;
19 |
20 |
21 | ///
22 | /// 处理接收到的数据
23 | ///
24 | ///
25 | public virtual bool ProcessReceive( byte[] buffer, int effectiveLength )
26 | {
27 | bool result = false;
28 |
29 | lock ( receiveLock )
30 | {
31 | //待发给协议处理的数据
32 | //byte[] buffer;
33 |
34 | ////如果当前缓存有效数据长度大于0
35 | //if ( receiveBufferLength > 0 )
36 | //{
37 | // //从缓存池中取一段缓存, 长度等于当前有效长度+新收到的有效长度
38 | // buffer = bufferManager.TakeBuffer( ReceiveArgs.BytesTransferred + receiveBufferLength );
39 | // //先把有当前缓存有效数据写入新的大缓存
40 | // Buffer.BlockCopy( receiveBuffer, 0, buffer, 0, receiveBufferLength );
41 | // //再将新收到的数据写入大缓存,接在之前添加的数据后
42 | // Buffer.BlockCopy( ReceiveArgs.Buffer, ReceiveArgs.Offset, buffer, receiveBufferLength, ReceiveArgs.BytesTransferred );
43 | // //归还缓冲区
44 | // bufferManager.ReturnBuffer( receiveBuffer );
45 | // //清除有效长度
46 | // receiveBufferLength = 0;
47 | //}
48 | //else
49 | //{
50 | // //申请一段能放下新收到数据的缓存
51 | // buffer = bufferManager.TakeBuffer( ReceiveArgs.BytesTransferred );
52 | // //拷贝有效数据
53 | // Buffer.BlockCopy( ReceiveArgs.Buffer, ReceiveArgs.Offset, buffer, 0, ReceiveArgs.BytesTransferred );
54 | // //归还缓冲区
55 | // bufferManager.ReturnBuffer( receiveBuffer );
56 | // //将新的缓存赋给接收缓存
57 | // receiveBuffer = buffer;
58 | // //设置有效长度
59 | // receiveBufferLength = ReceiveArgs.BytesTransferred;
60 | //}
61 |
62 |
63 | //Protocol.ProcessReceive( receiveBuffer, receiveBufferLength, out
64 | }
65 |
66 | return result;
67 | }
68 |
69 | public void GetNextSendBuffer( ref byte[] buffer, ref int effectiveLength )
70 | {
71 | throw new NotImplementedException();
72 | }
73 | }
74 | }
75 |
--------------------------------------------------------------------------------
/ITnmg.IOCPSocket.WPFServer/App.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/ITnmg.IOCPSocket.WPFServer/App.xaml:
--------------------------------------------------------------------------------
1 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
--------------------------------------------------------------------------------
/ITnmg.IOCPSocket.WPFServer/App.xaml.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Configuration;
4 | using System.Data;
5 | using System.Linq;
6 | using System.Threading.Tasks;
7 | using System.Windows;
8 |
9 | namespace ITnmg.IOCPSocket.WPFServer
10 | {
11 | ///
12 | /// App.xaml 的交互逻辑
13 | ///
14 | public partial class App : Application
15 | {
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/ITnmg.IOCPSocket.WPFServer/ITnmg.IOCPSocket.WPFServer.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | {EB08C901-88B9-44AA-AAA9-B771FEED7CB8}
8 | WinExe
9 | Properties
10 | ITnmg.IOCPSocket.WPFServer
11 | ITnmg.IOCPSocket.WPFServer
12 | v4.6.2
13 | 512
14 | {60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
15 | 4
16 | true
17 |
18 |
19 | AnyCPU
20 | true
21 | full
22 | false
23 | bin\Debug\
24 | DEBUG;TRACE
25 | prompt
26 | 4
27 |
28 |
29 | AnyCPU
30 | pdbonly
31 | true
32 | bin\Release\
33 | TRACE
34 | prompt
35 | 4
36 |
37 |
38 | true
39 | bin\x64\Debug\
40 | DEBUG;TRACE
41 | full
42 | x64
43 | prompt
44 | MinimumRecommendedRules.ruleset
45 | true
46 |
47 |
48 | bin\x64\Release\
49 | TRACE
50 | true
51 | pdbonly
52 | x64
53 | prompt
54 | MinimumRecommendedRules.ruleset
55 | true
56 |
57 |
58 |
59 | ..\packages\MvvmLightLibs.5.3.0.0\lib\net45\GalaSoft.MvvmLight.dll
60 | True
61 |
62 |
63 | ..\packages\MvvmLightLibs.5.3.0.0\lib\net45\GalaSoft.MvvmLight.Extras.dll
64 | True
65 |
66 |
67 | ..\packages\MvvmLightLibs.5.3.0.0\lib\net45\GalaSoft.MvvmLight.Platform.dll
68 | True
69 |
70 |
71 | ..\packages\MahApps.Metro.1.4.0\lib\net45\MahApps.Metro.dll
72 | True
73 |
74 |
75 | ..\packages\CommonServiceLocator.1.3\lib\portable-net4+sl5+netcore45+wpa81+wp8\Microsoft.Practices.ServiceLocation.dll
76 | True
77 |
78 |
79 |
80 |
81 | ..\packages\MvvmLightLibs.5.3.0.0\lib\net45\System.Windows.Interactivity.dll
82 | True
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 | 4.0
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 | MSBuild:Compile
100 | Designer
101 |
102 |
103 |
104 |
105 | MSBuild:Compile
106 | Designer
107 |
108 |
109 | App.xaml
110 | Code
111 |
112 |
113 | MainWindow.xaml
114 | Code
115 |
116 |
117 | MSBuild:Compile
118 | Designer
119 |
120 |
121 | MSBuild:Compile
122 | Designer
123 |
124 |
125 |
126 |
127 | Code
128 |
129 |
130 | True
131 | True
132 | Resources.resx
133 |
134 |
135 | True
136 | Settings.settings
137 | True
138 |
139 |
140 | ResXFileCodeGenerator
141 | Resources.Designer.cs
142 |
143 |
144 |
145 | SettingsSingleFileGenerator
146 | Settings.Designer.cs
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 | {aefceba4-0e8e-429d-ad10-4ace3bf794ff}
157 | ITnmg.IOCPSocket.Interface
158 |
159 |
160 | {2d636f35-8ec9-4002-8af6-71cbe237c359}
161 | ITnmg.IOCPSocket
162 |
163 |
164 |
165 |
166 |
167 |
168 |
169 |
170 |
171 |
178 |
--------------------------------------------------------------------------------
/ITnmg.IOCPSocket.WPFServer/MainWindow.xaml:
--------------------------------------------------------------------------------
1 |
13 |
14 |
19 |
23 |
27 |
31 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
--------------------------------------------------------------------------------
/ITnmg.IOCPSocket.WPFServer/MainWindow.xaml.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 | using System.Windows;
7 | using System.Windows.Controls;
8 | using System.Windows.Data;
9 | using System.Windows.Documents;
10 | using System.Windows.Input;
11 | using System.Windows.Media;
12 | using System.Windows.Media.Imaging;
13 | using System.Windows.Navigation;
14 | using System.Windows.Shapes;
15 | using MahApps.Metro.Controls;
16 |
17 | namespace ITnmg.IOCPSocket.WPFServer
18 | {
19 | ///
20 | /// MainWindow.xaml 的交互逻辑
21 | ///
22 | public partial class MainWindow : MetroWindow
23 | {
24 | public MainWindow()
25 | {
26 | InitializeComponent();
27 | }
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/ITnmg.IOCPSocket.WPFServer/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Resources;
3 | using System.Runtime.CompilerServices;
4 | using System.Runtime.InteropServices;
5 | using System.Windows;
6 |
7 | // 有关程序集的一般信息由以下
8 | // 控制。更改这些特性值可修改
9 | // 与程序集关联的信息。
10 | [assembly: AssemblyTitle( "ITnmg.IOCPSocket.WPFServer" )]
11 | [assembly: AssemblyDescription( "" )]
12 | [assembly: AssemblyConfiguration( "" )]
13 | [assembly: AssemblyCompany( "" )]
14 | [assembly: AssemblyProduct( "ITnmg.IOCPSocket.WPFServer" )]
15 | [assembly: AssemblyCopyright( "Copyright © 2017" )]
16 | [assembly: AssemblyTrademark( "" )]
17 | [assembly: AssemblyCulture( "" )]
18 |
19 | //将 ComVisible 设置为 false 将使此程序集中的类型
20 | //对 COM 组件不可见。 如果需要从 COM 访问此程序集中的类型,
21 | //请将此类型的 ComVisible 特性设置为 true。
22 | [assembly: ComVisible( false )]
23 |
24 | //若要开始生成可本地化的应用程序,请
25 | // 中的 .csproj 文件中
26 | //例如,如果您在源文件中使用的是美国英语,
27 | //使用的是美国英语,请将 设置为 en-US。 然后取消
28 | //对以下 NeutralResourceLanguage 特性的注释。 更新
29 | //以下行中的“en-US”以匹配项目文件中的 UICulture 设置。
30 |
31 | //[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)]
32 |
33 |
34 | [assembly: ThemeInfo(
35 | ResourceDictionaryLocation.None, //主题特定资源词典所处位置
36 | //(当资源未在页面
37 | //或应用程序资源字典中找到时使用)
38 | ResourceDictionaryLocation.SourceAssembly //常规资源词典所处位置
39 | //(当资源未在页面
40 | //、应用程序或任何主题专用资源字典中找到时使用)
41 | )]
42 |
43 |
44 | // 程序集的版本信息由下列四个值组成:
45 | //
46 | // 主版本
47 | // 次版本
48 | // 生成号
49 | // 修订号
50 | //
51 | //可以指定所有这些值,也可以使用“生成号”和“修订号”的默认值,
52 | // 方法是按如下所示使用“*”: :
53 | // [assembly: AssemblyVersion("1.0.*")]
54 | [assembly: AssemblyVersion( "1.0.0.0" )]
55 | [assembly: AssemblyFileVersion( "1.0.0.0" )]
56 |
--------------------------------------------------------------------------------
/ITnmg.IOCPSocket.WPFServer/Properties/Resources.Designer.cs:
--------------------------------------------------------------------------------
1 | //------------------------------------------------------------------------------
2 | //
3 | // 此代码由工具生成。
4 | // 运行时版本: 4.0.30319.42000
5 | //
6 | // 对此文件的更改可能导致不正确的行为,如果
7 | // 重新生成代码,则所做更改将丢失。
8 | //
9 | //------------------------------------------------------------------------------
10 |
11 | namespace ITnmg.IOCPSocket.WPFServer.Properties
12 | {
13 |
14 |
15 | ///
16 | /// 强类型资源类,用于查找本地化字符串等。
17 | ///
18 | // 此类是由 StronglyTypedResourceBuilder
19 | // 类通过类似于 ResGen 或 Visual Studio 的工具自动生成的。
20 | // 若要添加或删除成员,请编辑 .ResX 文件,然后重新运行 ResGen
21 | // (以 /str 作为命令选项),或重新生成 VS 项目。
22 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute( "System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0" )]
23 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
24 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
25 | internal class Resources
26 | {
27 |
28 | private static global::System.Resources.ResourceManager resourceMan;
29 |
30 | private static global::System.Globalization.CultureInfo resourceCulture;
31 |
32 | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )]
33 | internal Resources()
34 | {
35 | }
36 |
37 | ///
38 | /// 返回此类使用的缓存 ResourceManager 实例。
39 | ///
40 | [global::System.ComponentModel.EditorBrowsableAttribute( global::System.ComponentModel.EditorBrowsableState.Advanced )]
41 | internal static global::System.Resources.ResourceManager ResourceManager
42 | {
43 | get
44 | {
45 | if ( (resourceMan == null) )
46 | {
47 | global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager( "ITnmg.IOCPSocket.WPFServer.Properties.Resources", typeof( Resources ).Assembly );
48 | resourceMan = temp;
49 | }
50 | return resourceMan;
51 | }
52 | }
53 |
54 | ///
55 | /// 覆盖当前线程的 CurrentUICulture 属性
56 | /// 使用此强类型的资源类的资源查找。
57 | ///
58 | [global::System.ComponentModel.EditorBrowsableAttribute( global::System.ComponentModel.EditorBrowsableState.Advanced )]
59 | internal static global::System.Globalization.CultureInfo Culture
60 | {
61 | get
62 | {
63 | return resourceCulture;
64 | }
65 | set
66 | {
67 | resourceCulture = value;
68 | }
69 | }
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/ITnmg.IOCPSocket.WPFServer/Properties/Resources.resx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 | text/microsoft-resx
107 |
108 |
109 | 2.0
110 |
111 |
112 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
113 |
114 |
115 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
116 |
117 |
--------------------------------------------------------------------------------
/ITnmg.IOCPSocket.WPFServer/Properties/Settings.Designer.cs:
--------------------------------------------------------------------------------
1 | //------------------------------------------------------------------------------
2 | //
3 | // This code was generated by a tool.
4 | // Runtime Version:4.0.30319.42000
5 | //
6 | // Changes to this file may cause incorrect behavior and will be lost if
7 | // the code is regenerated.
8 | //
9 | //------------------------------------------------------------------------------
10 |
11 | namespace ITnmg.IOCPSocket.WPFServer.Properties
12 | {
13 |
14 |
15 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
16 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute( "Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0" )]
17 | internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase
18 | {
19 |
20 | private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized( new Settings() )));
21 |
22 | public static Settings Default
23 | {
24 | get
25 | {
26 | return defaultInstance;
27 | }
28 | }
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/ITnmg.IOCPSocket.WPFServer/Properties/Settings.settings:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/ITnmg.IOCPSocket.WPFServer/Resources/Entypo-license.txt:
--------------------------------------------------------------------------------
1 | Entypo (http://www.entypo.com/) is created by Daniel Bruce and released under the Creative Commons, Share Alike/Attribution license.
2 |
3 | http://creativecommons.org/licenses/by-sa/3.0/
--------------------------------------------------------------------------------
/ITnmg.IOCPSocket.WPFServer/Resources/Entypo.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jgh004/ITnmg.IOCPSocket/aa7bda956e53184f7a830347bb342f348cd236bd/ITnmg.IOCPSocket.WPFServer/Resources/Entypo.ttf
--------------------------------------------------------------------------------
/ITnmg.IOCPSocket.WPFServer/Resources/WindowsIcons-license.txt:
--------------------------------------------------------------------------------
1 | # License
2 |
3 | Please carefully understand the license and download the latest icons at ModernUIIcons.com.
4 |
5 | ## Understand Your Rights
6 | No Attribution and No Derived Works
7 | http://creativecommons.org/licenses/by-nd/3.0/ *
8 |
9 | - If your project is open source include this license file in the source.
10 | - Nothing is needed in the front facing project (UNLESS you
11 | are using any of the icons listed below in the attribution section).
12 | - Commercial use is not only allowed but encouraged. If it is an icon
13 | in the attribution list below, you still need to attribute those!
14 | - Do not distribute the entire package (I've allowed this dozens of
15 | times for open source projects, but email me first).
16 |
17 | ## Creator
18 | - Austin Andrews (@templarian)
19 |
20 | ## Contributor**
21 | - Jay Zawrotny (@JayZawrotny)
22 | - A Bunch
23 | - Oren Nachman
24 | - appbar.chevron.down
25 | - appbar.chevron.up
26 | - appbar.chevron.left
27 | - appbar.chevron.right
28 |
29 | ## Derived Works
30 | - Alex Peattie
31 | - Social: http://www.alexpeattie.com/projects/justvector_icons/
32 |
33 | ## Attribution***
34 | - Kris Vandermotten (@kvandermotten)
35 | - appbar.medical.pulse
36 | - Constantin Kichinsky (@kichinsky)
37 | - appbar.currency.rubles
38 | - appbar.currency.grivna
39 | - Massimo Savazzi (@msavazzi)
40 | - List of missing exported icons
41 | - Proletkult Graphik, from The Noun Project
42 | - appbar.draw.pen (inspired)
43 | - Olivier Guin, from The Noun Project
44 | - appbar.draw.marker
45 | - Gibran Bisio, from The Noun Project
46 | - appbar.draw.bucket
47 | Andrew Forrester, from The Noun Project
48 | - appbar.fingerprint
49 |
50 | * The license is for attribution, but this is not required.
51 | ** Developers and designers that emailed Templarian the source .design icons to be added into the package. PNGs also accepted, but may take longer to be added.
52 | *** Icons I've copied so closely you want to attribute them and are also under the CC license.
53 |
54 | Contact
55 | - http://templarian.com/
56 | - admin[@]templarian[.]com
57 |
58 | * Does not apply to copyrighted logos
59 | - Skype
60 | - Facebook
61 | - Twitter
62 | - etc...
63 |
--------------------------------------------------------------------------------
/ITnmg.IOCPSocket.WPFServer/ViewModel/MainViewModel.cs:
--------------------------------------------------------------------------------
1 | using GalaSoft.MvvmLight;
2 |
3 | namespace ITnmg.IOCPSocket.WPFServer.ViewModel
4 | {
5 | ///
6 | /// This class contains properties that the main View can data bind to.
7 | ///
8 | /// Use the mvvminpc snippet to add bindable properties to this ViewModel.
9 | ///
10 | ///
11 | /// You can also use Blend to data bind with the tool's support.
12 | ///
13 | ///
14 | /// See http://www.galasoft.ch/mvvm
15 | ///
16 | ///
17 | public class MainViewModel : ViewModelBase
18 | {
19 | ///
20 | /// Initializes a new instance of the MainViewModel class.
21 | ///
22 | public MainViewModel()
23 | {
24 | ////if (IsInDesignMode)
25 | ////{
26 | //// // Code runs in Blend --> create design time data.
27 | ////}
28 | ////else
29 | ////{
30 | //// // Code runs "for real"
31 | ////}
32 | }
33 | }
34 | }
--------------------------------------------------------------------------------
/ITnmg.IOCPSocket.WPFServer/ViewModel/ViewModelLocator.cs:
--------------------------------------------------------------------------------
1 | /*
2 | In App.xaml:
3 |
4 |
6 |
7 |
8 | In the View:
9 | DataContext="{Binding Source={StaticResource Locator}, Path=ViewModelName}"
10 |
11 | You can also use Blend to do all this with the tool's support.
12 | See http://www.galasoft.ch/mvvm
13 | */
14 |
15 | using GalaSoft.MvvmLight;
16 | using GalaSoft.MvvmLight.Ioc;
17 | using Microsoft.Practices.ServiceLocation;
18 |
19 | namespace ITnmg.IOCPSocket.WPFServer.ViewModel
20 | {
21 | ///
22 | /// This class contains static references to all the view models in the
23 | /// application and provides an entry point for the bindings.
24 | ///
25 | public class ViewModelLocator
26 | {
27 | ///
28 | /// Initializes a new instance of the ViewModelLocator class.
29 | ///
30 | public ViewModelLocator()
31 | {
32 | ServiceLocator.SetLocatorProvider(() => SimpleIoc.Default);
33 |
34 | ////if (ViewModelBase.IsInDesignModeStatic)
35 | ////{
36 | //// // Create design time view services and models
37 | //// SimpleIoc.Default.Register();
38 | ////}
39 | ////else
40 | ////{
41 | //// // Create run time view services and models
42 | //// SimpleIoc.Default.Register();
43 | ////}
44 |
45 | SimpleIoc.Default.Register();
46 | }
47 |
48 | public MainViewModel Main
49 | {
50 | get
51 | {
52 | return ServiceLocator.Current.GetInstance();
53 | }
54 | }
55 |
56 | public static void Cleanup()
57 | {
58 | // TODO Clear the ViewModels
59 | }
60 | }
61 | }
--------------------------------------------------------------------------------
/ITnmg.IOCPSocket.WPFServer/packages.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/ITnmg.IOCPSocket.WinFormClient/App.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/ITnmg.IOCPSocket.WinFormClient/F_Main.Designer.cs:
--------------------------------------------------------------------------------
1 | namespace ITnmg.IOCPSocket.WinFormClient
2 | {
3 | partial class F_Main
4 | {
5 | ///
6 | /// 必需的设计器变量。
7 | ///
8 | private System.ComponentModel.IContainer components = null;
9 |
10 | ///
11 | /// 清理所有正在使用的资源。
12 | ///
13 | /// 如果应释放托管资源,为 true;否则为 false。
14 | protected override void Dispose( bool disposing )
15 | {
16 | if ( disposing && (components != null) )
17 | {
18 | components.Dispose();
19 | }
20 | base.Dispose( disposing );
21 | }
22 |
23 | #region Windows 窗体设计器生成的代码
24 |
25 | ///
26 | /// 设计器支持所需的方法 - 不要修改
27 | /// 使用代码编辑器修改此方法的内容。
28 | ///
29 | private void InitializeComponent()
30 | {
31 | System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(F_Main));
32 | this.toolStrip1 = new System.Windows.Forms.ToolStrip();
33 | this.ts_Settings = new System.Windows.Forms.ToolStripButton();
34 | this.ts_SendData = new System.Windows.Forms.ToolStripButton();
35 | this.panel1 = new System.Windows.Forms.Panel();
36 | this.bt_Init = new System.Windows.Forms.Button();
37 | this.bt_Stop = new System.Windows.Forms.Button();
38 | this.bt_Start = new System.Windows.Forms.Button();
39 | this.label3 = new System.Windows.Forms.Label();
40 | this.tb_ConnectionCount = new System.Windows.Forms.TextBox();
41 | this.label2 = new System.Windows.Forms.Label();
42 | this.tb_Port = new System.Windows.Forms.TextBox();
43 | this.label1 = new System.Windows.Forms.Label();
44 | this.tb_DomainOrIP = new System.Windows.Forms.TextBox();
45 | this.panel2 = new System.Windows.Forms.Panel();
46 | this.splitContainer1 = new System.Windows.Forms.SplitContainer();
47 | this.textBox1 = new System.Windows.Forms.TextBox();
48 | this.tb_Console = new System.Windows.Forms.TextBox();
49 | this.toolStrip1.SuspendLayout();
50 | this.panel1.SuspendLayout();
51 | this.panel2.SuspendLayout();
52 | ((System.ComponentModel.ISupportInitialize)(this.splitContainer1)).BeginInit();
53 | this.splitContainer1.Panel1.SuspendLayout();
54 | this.splitContainer1.Panel2.SuspendLayout();
55 | this.splitContainer1.SuspendLayout();
56 | this.SuspendLayout();
57 | //
58 | // toolStrip1
59 | //
60 | this.toolStrip1.ImageScalingSize = new System.Drawing.Size(20, 20);
61 | this.toolStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
62 | this.ts_Settings,
63 | this.ts_SendData});
64 | this.toolStrip1.Location = new System.Drawing.Point(0, 0);
65 | this.toolStrip1.Name = "toolStrip1";
66 | this.toolStrip1.Size = new System.Drawing.Size(1182, 27);
67 | this.toolStrip1.TabIndex = 0;
68 | //
69 | // ts_Settings
70 | //
71 | this.ts_Settings.Image = ((System.Drawing.Image)(resources.GetObject("ts_Settings.Image")));
72 | this.ts_Settings.ImageTransparentColor = System.Drawing.Color.Magenta;
73 | this.ts_Settings.Name = "ts_Settings";
74 | this.ts_Settings.Size = new System.Drawing.Size(93, 24);
75 | this.ts_Settings.Text = "Settings";
76 | //
77 | // ts_SendData
78 | //
79 | this.ts_SendData.Image = ((System.Drawing.Image)(resources.GetObject("ts_SendData.Image")));
80 | this.ts_SendData.ImageTransparentColor = System.Drawing.Color.Magenta;
81 | this.ts_SendData.Name = "ts_SendData";
82 | this.ts_SendData.Size = new System.Drawing.Size(103, 24);
83 | this.ts_SendData.Text = "SendData";
84 | //
85 | // panel1
86 | //
87 | this.panel1.Controls.Add(this.bt_Init);
88 | this.panel1.Controls.Add(this.bt_Stop);
89 | this.panel1.Controls.Add(this.bt_Start);
90 | this.panel1.Controls.Add(this.label3);
91 | this.panel1.Controls.Add(this.tb_ConnectionCount);
92 | this.panel1.Controls.Add(this.label2);
93 | this.panel1.Controls.Add(this.tb_Port);
94 | this.panel1.Controls.Add(this.label1);
95 | this.panel1.Controls.Add(this.tb_DomainOrIP);
96 | this.panel1.Dock = System.Windows.Forms.DockStyle.Top;
97 | this.panel1.Location = new System.Drawing.Point(0, 27);
98 | this.panel1.Margin = new System.Windows.Forms.Padding(3, 4, 3, 4);
99 | this.panel1.Name = "panel1";
100 | this.panel1.Size = new System.Drawing.Size(1182, 54);
101 | this.panel1.TabIndex = 1;
102 | //
103 | // bt_Init
104 | //
105 | this.bt_Init.Location = new System.Drawing.Point(770, 9);
106 | this.bt_Init.Margin = new System.Windows.Forms.Padding(3, 4, 3, 4);
107 | this.bt_Init.Name = "bt_Init";
108 | this.bt_Init.Size = new System.Drawing.Size(84, 31);
109 | this.bt_Init.TabIndex = 106;
110 | this.bt_Init.Text = "Init";
111 | this.bt_Init.UseVisualStyleBackColor = true;
112 | this.bt_Init.Click += new System.EventHandler(this.bt_Init_Click);
113 | //
114 | // bt_Stop
115 | //
116 | this.bt_Stop.Location = new System.Drawing.Point(988, 7);
117 | this.bt_Stop.Margin = new System.Windows.Forms.Padding(3, 4, 3, 4);
118 | this.bt_Stop.Name = "bt_Stop";
119 | this.bt_Stop.Size = new System.Drawing.Size(84, 34);
120 | this.bt_Stop.TabIndex = 7;
121 | this.bt_Stop.Text = "Stop";
122 | this.bt_Stop.UseVisualStyleBackColor = true;
123 | this.bt_Stop.Click += new System.EventHandler(this.bt_Stop_Click);
124 | //
125 | // bt_Start
126 | //
127 | this.bt_Start.Location = new System.Drawing.Point(879, 7);
128 | this.bt_Start.Margin = new System.Windows.Forms.Padding(3, 4, 3, 4);
129 | this.bt_Start.Name = "bt_Start";
130 | this.bt_Start.Size = new System.Drawing.Size(84, 34);
131 | this.bt_Start.TabIndex = 6;
132 | this.bt_Start.Text = "Start";
133 | this.bt_Start.UseVisualStyleBackColor = true;
134 | this.bt_Start.Click += new System.EventHandler(this.bt_Start_Click);
135 | //
136 | // label3
137 | //
138 | this.label3.AutoSize = true;
139 | this.label3.Location = new System.Drawing.Point(467, 14);
140 | this.label3.Name = "label3";
141 | this.label3.Size = new System.Drawing.Size(145, 20);
142 | this.label3.TabIndex = 5;
143 | this.label3.Text = "Connection Count:";
144 | //
145 | // tb_ConnectionCount
146 | //
147 | this.tb_ConnectionCount.Location = new System.Drawing.Point(618, 11);
148 | this.tb_ConnectionCount.Margin = new System.Windows.Forms.Padding(3, 4, 3, 4);
149 | this.tb_ConnectionCount.Name = "tb_ConnectionCount";
150 | this.tb_ConnectionCount.Size = new System.Drawing.Size(128, 27);
151 | this.tb_ConnectionCount.TabIndex = 4;
152 | this.tb_ConnectionCount.Text = "2";
153 | //
154 | // label2
155 | //
156 | this.label2.AutoSize = true;
157 | this.label2.Location = new System.Drawing.Point(296, 14);
158 | this.label2.Name = "label2";
159 | this.label2.Size = new System.Drawing.Size(44, 20);
160 | this.label2.TabIndex = 3;
161 | this.label2.Text = "Port:";
162 | //
163 | // tb_Port
164 | //
165 | this.tb_Port.Location = new System.Drawing.Point(346, 11);
166 | this.tb_Port.Margin = new System.Windows.Forms.Padding(3, 4, 3, 4);
167 | this.tb_Port.Name = "tb_Port";
168 | this.tb_Port.Size = new System.Drawing.Size(82, 27);
169 | this.tb_Port.TabIndex = 2;
170 | this.tb_Port.Text = "9000";
171 | //
172 | // label1
173 | //
174 | this.label1.AutoSize = true;
175 | this.label1.Location = new System.Drawing.Point(12, 14);
176 | this.label1.Name = "label1";
177 | this.label1.Size = new System.Drawing.Size(26, 20);
178 | this.label1.TabIndex = 1;
179 | this.label1.Text = "IP:";
180 | //
181 | // tb_DomainOrIP
182 | //
183 | this.tb_DomainOrIP.Location = new System.Drawing.Point(44, 11);
184 | this.tb_DomainOrIP.Margin = new System.Windows.Forms.Padding(3, 4, 3, 4);
185 | this.tb_DomainOrIP.Name = "tb_DomainOrIP";
186 | this.tb_DomainOrIP.Size = new System.Drawing.Size(213, 27);
187 | this.tb_DomainOrIP.TabIndex = 0;
188 | this.tb_DomainOrIP.Text = "127.0.0.1";
189 | //
190 | // panel2
191 | //
192 | this.panel2.Controls.Add(this.splitContainer1);
193 | this.panel2.Dock = System.Windows.Forms.DockStyle.Fill;
194 | this.panel2.Location = new System.Drawing.Point(0, 81);
195 | this.panel2.Margin = new System.Windows.Forms.Padding(3, 4, 3, 4);
196 | this.panel2.Name = "panel2";
197 | this.panel2.Size = new System.Drawing.Size(1182, 552);
198 | this.panel2.TabIndex = 2;
199 | //
200 | // splitContainer1
201 | //
202 | this.splitContainer1.Dock = System.Windows.Forms.DockStyle.Fill;
203 | this.splitContainer1.FixedPanel = System.Windows.Forms.FixedPanel.Panel2;
204 | this.splitContainer1.Location = new System.Drawing.Point(0, 0);
205 | this.splitContainer1.Name = "splitContainer1";
206 | this.splitContainer1.Orientation = System.Windows.Forms.Orientation.Horizontal;
207 | //
208 | // splitContainer1.Panel1
209 | //
210 | this.splitContainer1.Panel1.Controls.Add(this.textBox1);
211 | //
212 | // splitContainer1.Panel2
213 | //
214 | this.splitContainer1.Panel2.Controls.Add(this.tb_Console);
215 | this.splitContainer1.Size = new System.Drawing.Size(1182, 552);
216 | this.splitContainer1.SplitterDistance = 360;
217 | this.splitContainer1.TabIndex = 108;
218 | //
219 | // textBox1
220 | //
221 | this.textBox1.Location = new System.Drawing.Point(59, 26);
222 | this.textBox1.Name = "textBox1";
223 | this.textBox1.Size = new System.Drawing.Size(119, 27);
224 | this.textBox1.TabIndex = 104;
225 | //
226 | // tb_Console
227 | //
228 | this.tb_Console.BackColor = System.Drawing.Color.Black;
229 | this.tb_Console.Dock = System.Windows.Forms.DockStyle.Fill;
230 | this.tb_Console.ForeColor = System.Drawing.Color.White;
231 | this.tb_Console.Location = new System.Drawing.Point(0, 0);
232 | this.tb_Console.Multiline = true;
233 | this.tb_Console.Name = "tb_Console";
234 | this.tb_Console.ScrollBars = System.Windows.Forms.ScrollBars.Vertical;
235 | this.tb_Console.Size = new System.Drawing.Size(1182, 188);
236 | this.tb_Console.TabIndex = 0;
237 | //
238 | // F_Main
239 | //
240 | this.AutoScaleDimensions = new System.Drawing.SizeF(9F, 20F);
241 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
242 | this.ClientSize = new System.Drawing.Size(1182, 633);
243 | this.Controls.Add(this.panel2);
244 | this.Controls.Add(this.panel1);
245 | this.Controls.Add(this.toolStrip1);
246 | this.Font = new System.Drawing.Font("微软雅黑", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
247 | this.Margin = new System.Windows.Forms.Padding(3, 4, 3, 4);
248 | this.Name = "F_Main";
249 | this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
250 | this.Text = "Socket Stress Test";
251 | this.Load += new System.EventHandler(this.F_Main_Load);
252 | this.toolStrip1.ResumeLayout(false);
253 | this.toolStrip1.PerformLayout();
254 | this.panel1.ResumeLayout(false);
255 | this.panel1.PerformLayout();
256 | this.panel2.ResumeLayout(false);
257 | this.splitContainer1.Panel1.ResumeLayout(false);
258 | this.splitContainer1.Panel1.PerformLayout();
259 | this.splitContainer1.Panel2.ResumeLayout(false);
260 | this.splitContainer1.Panel2.PerformLayout();
261 | ((System.ComponentModel.ISupportInitialize)(this.splitContainer1)).EndInit();
262 | this.splitContainer1.ResumeLayout(false);
263 | this.ResumeLayout(false);
264 | this.PerformLayout();
265 |
266 | }
267 |
268 | #endregion
269 |
270 | private System.Windows.Forms.ToolStrip toolStrip1;
271 | private System.Windows.Forms.Panel panel1;
272 | private System.Windows.Forms.ToolStripButton ts_Settings;
273 | private System.Windows.Forms.Button bt_Start;
274 | private System.Windows.Forms.Label label3;
275 | private System.Windows.Forms.TextBox tb_ConnectionCount;
276 | private System.Windows.Forms.Label label2;
277 | private System.Windows.Forms.TextBox tb_Port;
278 | private System.Windows.Forms.Label label1;
279 | private System.Windows.Forms.TextBox tb_DomainOrIP;
280 | private System.Windows.Forms.Button bt_Stop;
281 | private System.Windows.Forms.Panel panel2;
282 | private System.Windows.Forms.ToolStripButton ts_SendData;
283 | private System.Windows.Forms.Button bt_Init;
284 | private System.Windows.Forms.SplitContainer splitContainer1;
285 | private System.Windows.Forms.TextBox textBox1;
286 | private System.Windows.Forms.TextBox tb_Console;
287 | }
288 | }
289 |
290 |
--------------------------------------------------------------------------------
/ITnmg.IOCPSocket.WinFormClient/F_Main.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.ComponentModel;
4 | using System.Data;
5 | using System.Drawing;
6 | using System.Linq;
7 | using System.Text;
8 | using System.Threading;
9 | using System.Threading.Tasks;
10 | using System.Windows.Forms;
11 |
12 | namespace ITnmg.IOCPSocket.WinFormClient
13 | {
14 | public partial class F_Main : Form
15 | {
16 | private SynchronizationContext sync;
17 | SocketClientManager clientManager;
18 | bool isInit = false;
19 |
20 | public F_Main()
21 | {
22 | InitializeComponent();
23 | }
24 |
25 | private void F_Main_Load( object sender, EventArgs e )
26 | {
27 | this.sync = SynchronizationContext.Current;
28 | clientManager = new SocketClientManager();
29 | clientManager.ErrorEvent += ClientManager_ErrorEvent;
30 | clientManager.ClientManagerStatusChangeEvent += ClientManager_ClientManagerStatusChangeEvent;
31 | clientManager.ConnectedStatusChangeEvent += ClientManager_ConnectedStatusChangeEvent;
32 | ;
33 | }
34 |
35 | private void bt_Init_Click( object sender, EventArgs e )
36 | {
37 | InitAsync();
38 | }
39 |
40 | private void bt_Start_Click( object sender, EventArgs e )
41 | {
42 | StartAsync();
43 | }
44 |
45 | private void bt_Stop_Click( object sender, EventArgs e )
46 | {
47 | try
48 | {
49 | SetBtns( false );
50 | clientManager.StopAsync();
51 | }
52 | catch ( Exception ex )
53 | {
54 | SetBtns( false );
55 | }
56 | }
57 |
58 | private async Task InitAsync()
59 | {
60 | var max = Convert.ToInt32( this.tb_ConnectionCount.Text.Trim() );
61 | await clientManager.InitAsync( max, max, new TextProtocol(), 4 * 1024, 10000, 10000 ).ContinueWith( f =>
62 | {
63 | if ( f.Exception == null )
64 | {
65 | this.isInit = true;
66 | }
67 | else
68 | {
69 | this.ShowMessageBox( "初始化失败: " + f.Exception.GetBaseException().Message );
70 | }
71 |
72 | this.AsyncPost( k =>
73 | {
74 | this.bt_Init.Enabled = true;
75 | }, "" );
76 | } );
77 | }
78 |
79 | private async Task StartAsync()
80 | {
81 | try
82 | {
83 | if ( !isInit )
84 | {
85 | await InitAsync();
86 | }
87 |
88 | SetBtns( true );
89 | await clientManager.StartAsync( this.tb_DomainOrIP.Text.Trim(), Convert.ToInt32( this.tb_Port.Text.Trim() ) ).ContinueWith( f =>
90 | {
91 | if ( !f.IsCompleted )
92 | {
93 | SetBtns( false );
94 | }
95 | } );
96 |
97 | }
98 | catch ( Exception ex )
99 | {
100 | if ( clientManager != null )
101 | {
102 | await clientManager.StopAsync();
103 | }
104 |
105 | SetBtns( true );
106 | }
107 | }
108 |
109 | private void ClientManager_ErrorEvent( object sender, Exception e )
110 | {
111 | WriteConsole( $"Error: {e.Message}" );
112 | }
113 |
114 | private void ClientManager_ClientManagerStatusChangeEvent( object sender, bool e )
115 | {
116 | this.SetBtns( e );
117 | WriteConsole( $"Server: {(e ? "启动" : "停止")}" );
118 | }
119 |
120 | private void ClientManager_ConnectedStatusChangeEvent( object sender, SocketStatusChangeArgs e )
121 | {
122 | AsyncPost( f =>
123 | {
124 | this.textBox1.Text = e.ConnectedCount.ToString();
125 | }, e );
126 |
127 | if ( e.Error != null )
128 | {
129 | WriteConsole( $"UserTokenId:{e.UserTokenId}, Status:{e.Status}, ConnCount:{e.ConnectedCount}, Error:{e.Error}" );
130 | }
131 | }
132 |
133 |
134 | private void SetBtns( bool start )
135 | {
136 | this.bt_Init.Enabled = !start;
137 | this.bt_Start.Enabled = !start;
138 | this.bt_Stop.Enabled = start;
139 | }
140 |
141 | private void ShowMessageBox( string msg )
142 | {
143 | this.AsyncPost( f =>
144 | {
145 | MessageBox.Show( msg );
146 | }, msg );
147 | }
148 |
149 | private void AsyncPost( Action method, T state )
150 | {
151 | if ( this.sync != null )
152 | {
153 | this.sync.Post( f =>
154 | {
155 | method( (T)f );
156 | }, state );
157 | }
158 | }
159 |
160 | private void WriteConsole( string s )
161 | {
162 | this.AsyncPost( f =>
163 | {
164 | if ( this.tb_Console.Lines.Length > 20000 )
165 | {
166 | this.tb_Console.Text = "";
167 | }
168 |
169 | this.tb_Console.Text += (this.tb_Console.Text.Length > 0 ? "\r\n" : "") + s;
170 | this.tb_Console.SelectionStart = this.tb_Console.Text.Length;
171 | }, s );
172 | }
173 | }
174 | }
175 |
--------------------------------------------------------------------------------
/ITnmg.IOCPSocket.WinFormClient/F_Main.resx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 | text/microsoft-resx
110 |
111 |
112 | 2.0
113 |
114 |
115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
116 |
117 |
118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
119 |
120 |
121 | 17, 17
122 |
123 |
124 |
125 |
126 | iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
127 | YQUAAAAJcEhZcwAAEnQAABJ0Ad5mH3gAAAIDSURBVDhPpZLrS5NhGMb3j4SWh0oRQVExD4gonkDpg4hG
128 | YKxG6WBogkMZKgPNCEVJFBGdGETEvgwyO9DJE5syZw3PIlPEE9pgBCLZ5XvdMB8Ew8gXbl54nuf63dd9
129 | 0OGSnwCahxbPRNPAPMw9Xpg6ZmF46kZZ0xSKzJPIrhpDWsVnpBhGkKx3nAX8Pv7z1zg8OoY/cITdn4fw
130 | bf/C0kYAN3Ma/w3gWfZL5kzTKBxjWyK2DftwI9tyMYCZKXbNHaD91bLYJrDXsYbrWfUKwJrPE9M2M1Oc
131 | VzOOpHI7Jr376Hi9ogHqFIANO0/MmmmbmSmm9a8ze+I4MrNWAdjtoJgWcx+PSzg166yZZ8xM8XvXDix9
132 | c4jIqFYAjoriBV9AhEPv1mH/sonogha0afbZMMZz+yreTGyhpusHwtNNCsA5U1zS4BLxzJIfg299qO32
133 | Ir7UJtZfftyATqeT+8o2D8JSjQrAJblrncYL7ZJ2+bfaFnC/1S1NjL3diRat7qrO7wLRP3HjWsojBeCo
134 | mDEo5mNjuweFGvjWg2EBhCbpkW78htSHHwRyNdmgAFzPEee2iFkzayy2OLXzT4gr6UdUnlXrullsxxQ+
135 | kx0g8BTA3aZlButjSTyjODq/WcQcW/B/Je4OQhLvKQDnzN1mp0nnkvAhR8VuMzNrpm1mpjgkoVwB/v8D
136 | TgDQASA1MVpwzwAAAABJRU5ErkJggg==
137 |
138 |
139 |
140 |
141 | iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
142 | YQUAAAAJcEhZcwAAEnQAABJ0Ad5mH3gAAAIDSURBVDhPpZLrS5NhGMb3j4SWh0oRQVExD4gonkDpg4hG
143 | YKxG6WBogkMZKgPNCEVJFBGdGETEvgwyO9DJE5syZw3PIlPEE9pgBCLZ5XvdMB8Ew8gXbl54nuf63dd9
144 | 0OGSnwCahxbPRNPAPMw9Xpg6ZmF46kZZ0xSKzJPIrhpDWsVnpBhGkKx3nAX8Pv7z1zg8OoY/cITdn4fw
145 | bf/C0kYAN3Ma/w3gWfZL5kzTKBxjWyK2DftwI9tyMYCZKXbNHaD91bLYJrDXsYbrWfUKwJrPE9M2M1Oc
146 | VzOOpHI7Jr376Hi9ogHqFIANO0/MmmmbmSmm9a8ze+I4MrNWAdjtoJgWcx+PSzg166yZZ8xM8XvXDix9
147 | c4jIqFYAjoriBV9AhEPv1mH/sonogha0afbZMMZz+yreTGyhpusHwtNNCsA5U1zS4BLxzJIfg299qO32
148 | Ir7UJtZfftyATqeT+8o2D8JSjQrAJblrncYL7ZJ2+bfaFnC/1S1NjL3diRat7qrO7wLRP3HjWsojBeCo
149 | mDEo5mNjuweFGvjWg2EBhCbpkW78htSHHwRyNdmgAFzPEee2iFkzayy2OLXzT4gr6UdUnlXrullsxxQ+
150 | kx0g8BTA3aZlButjSTyjODq/WcQcW/B/Je4OQhLvKQDnzN1mp0nnkvAhR8VuMzNrpm1mpjgkoVwB/v8D
151 | TgDQASA1MVpwzwAAAABJRU5ErkJggg==
152 |
153 |
154 |
--------------------------------------------------------------------------------
/ITnmg.IOCPSocket.WinFormClient/ITnmg.IOCPSocket.WinFormClient.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | {F2F6CF86-CF94-40CC-A4E0-48230AC989B7}
8 | WinExe
9 | Properties
10 | ITnmg.IOCPSocket.WinFormClient
11 | ITnmg.IOCPSocket.WinFormClient
12 | v4.6.2
13 | 512
14 | true
15 |
16 |
17 |
18 | AnyCPU
19 | true
20 | full
21 | false
22 | bin\Debug\
23 | DEBUG;TRACE
24 | prompt
25 | 4
26 |
27 |
28 | AnyCPU
29 | pdbonly
30 | true
31 | bin\Release\
32 | TRACE
33 | prompt
34 | 4
35 |
36 |
37 | true
38 | bin\x64\Debug\
39 | DEBUG;TRACE
40 | full
41 | x64
42 | prompt
43 | MinimumRecommendedRules.ruleset
44 | true
45 |
46 |
47 | bin\x64\Release\
48 | TRACE
49 | true
50 | pdbonly
51 | x64
52 | prompt
53 | MinimumRecommendedRules.ruleset
54 | true
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 | Form
71 |
72 |
73 | F_Main.cs
74 |
75 |
76 |
77 |
78 | F_Main.cs
79 |
80 |
81 | ResXFileCodeGenerator
82 | Resources.Designer.cs
83 | Designer
84 |
85 |
86 | True
87 | Resources.resx
88 | True
89 |
90 |
91 | SettingsSingleFileGenerator
92 | Settings.Designer.cs
93 |
94 |
95 | True
96 | Settings.settings
97 | True
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 | {aefceba4-0e8e-429d-ad10-4ace3bf794ff}
106 | ITnmg.IOCPSocket.Interface
107 |
108 |
109 | {2d636f35-8ec9-4002-8af6-71cbe237c359}
110 | ITnmg.IOCPSocket
111 |
112 |
113 |
114 |
121 |
--------------------------------------------------------------------------------
/ITnmg.IOCPSocket.WinFormClient/Program.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Threading.Tasks;
5 | using System.Windows.Forms;
6 |
7 | namespace ITnmg.IOCPSocket.WinFormClient
8 | {
9 | static class Program
10 | {
11 | ///
12 | /// 应用程序的主入口点。
13 | ///
14 | [STAThread]
15 | static void Main()
16 | {
17 | Application.EnableVisualStyles();
18 | Application.SetCompatibleTextRenderingDefault( false );
19 | Application.Run( new F_Main() );
20 | }
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/ITnmg.IOCPSocket.WinFormClient/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // 有关程序集的一般信息由以下
6 | // 控制。更改这些特性值可修改
7 | // 与程序集关联的信息。
8 | [assembly: AssemblyTitle( "SocketStressTestTools" )]
9 | [assembly: AssemblyDescription( "" )]
10 | [assembly: AssemblyConfiguration( "" )]
11 | [assembly: AssemblyCompany( "" )]
12 | [assembly: AssemblyProduct( "SocketStressTestTools" )]
13 | [assembly: AssemblyCopyright( "Copyright © 2016" )]
14 | [assembly: AssemblyTrademark( "" )]
15 | [assembly: AssemblyCulture( "" )]
16 |
17 | //将 ComVisible 设置为 false 将使此程序集中的类型
18 | //对 COM 组件不可见。 如果需要从 COM 访问此程序集中的类型,
19 | //请将此类型的 ComVisible 特性设置为 true。
20 | [assembly: ComVisible( false )]
21 |
22 | // 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID
23 | [assembly: Guid( "f2f6cf86-cf94-40cc-a4e0-48230ac989b7" )]
24 |
25 | // 程序集的版本信息由下列四个值组成:
26 | //
27 | // 主版本
28 | // 次版本
29 | // 生成号
30 | // 修订号
31 | //
32 | //可以指定所有这些值,也可以使用“生成号”和“修订号”的默认值,
33 | // 方法是按如下所示使用“*”: :
34 | // [assembly: AssemblyVersion("1.0.*")]
35 | [assembly: AssemblyVersion( "1.0.0.0" )]
36 | [assembly: AssemblyFileVersion( "1.0.0.0" )]
37 |
--------------------------------------------------------------------------------
/ITnmg.IOCPSocket.WinFormClient/Properties/Resources.Designer.cs:
--------------------------------------------------------------------------------
1 | //------------------------------------------------------------------------------
2 | //
3 | // 此代码由工具生成。
4 | // 运行时版本:4.0.30319.42000
5 | //
6 | // 对此文件的更改可能会导致不正确的行为,并且如果
7 | // 重新生成代码,这些更改将会丢失。
8 | //
9 | //------------------------------------------------------------------------------
10 |
11 | namespace ITnmg.IOCPSocket.WinFormClient.Properties {
12 | using System;
13 |
14 |
15 | ///
16 | /// 一个强类型的资源类,用于查找本地化的字符串等。
17 | ///
18 | // 此类是由 StronglyTypedResourceBuilder
19 | // 类通过类似于 ResGen 或 Visual Studio 的工具自动生成的。
20 | // 若要添加或移除成员,请编辑 .ResX 文件,然后重新运行 ResGen
21 | // (以 /str 作为命令选项),或重新生成 VS 项目。
22 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
23 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
24 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
25 | internal class Resources {
26 |
27 | private static global::System.Resources.ResourceManager resourceMan;
28 |
29 | private static global::System.Globalization.CultureInfo resourceCulture;
30 |
31 | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
32 | internal Resources() {
33 | }
34 |
35 | ///
36 | /// 返回此类使用的缓存的 ResourceManager 实例。
37 | ///
38 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
39 | internal static global::System.Resources.ResourceManager ResourceManager {
40 | get {
41 | if (object.ReferenceEquals(resourceMan, null)) {
42 | global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("ITnmg.IOCPSocket.WinFormClient.Properties.Resources", typeof(Resources).Assembly);
43 | resourceMan = temp;
44 | }
45 | return resourceMan;
46 | }
47 | }
48 |
49 | ///
50 | /// 使用此强类型资源类,为所有资源查找
51 | /// 重写当前线程的 CurrentUICulture 属性。
52 | ///
53 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
54 | internal static global::System.Globalization.CultureInfo Culture {
55 | get {
56 | return resourceCulture;
57 | }
58 | set {
59 | resourceCulture = value;
60 | }
61 | }
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/ITnmg.IOCPSocket.WinFormClient/Properties/Resources.resx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 | text/microsoft-resx
107 |
108 |
109 | 2.0
110 |
111 |
112 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
113 |
114 |
115 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
116 |
117 |
--------------------------------------------------------------------------------
/ITnmg.IOCPSocket.WinFormClient/Properties/Settings.Designer.cs:
--------------------------------------------------------------------------------
1 | //------------------------------------------------------------------------------
2 | //
3 | // 此代码由工具生成。
4 | // 运行时版本:4.0.30319.42000
5 | //
6 | // 对此文件的更改可能会导致不正确的行为,并且如果
7 | // 重新生成代码,这些更改将会丢失。
8 | //
9 | //------------------------------------------------------------------------------
10 |
11 | namespace ITnmg.IOCPSocket.WinFormClient.Properties {
12 |
13 |
14 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
15 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "14.0.0.0")]
16 | internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
17 |
18 | private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
19 |
20 | public static Settings Default {
21 | get {
22 | return defaultInstance;
23 | }
24 | }
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/ITnmg.IOCPSocket.WinFormClient/Properties/Settings.settings:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/ITnmg.IOCPSocket.WinFormServer/App.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/ITnmg.IOCPSocket.WinFormServer/F_Main.Designer.cs:
--------------------------------------------------------------------------------
1 | namespace ITnmg.IOCPSocket.WinFormServer
2 | {
3 | partial class F_Main
4 | {
5 | ///
6 | /// 必需的设计器变量。
7 | ///
8 | private System.ComponentModel.IContainer components = null;
9 |
10 | ///
11 | /// 清理所有正在使用的资源。
12 | ///
13 | /// 如果应释放托管资源,为 true;否则为 false。
14 | protected override void Dispose( bool disposing )
15 | {
16 | if ( disposing && (components != null) )
17 | {
18 | components.Dispose();
19 | }
20 | base.Dispose( disposing );
21 | }
22 |
23 | #region Windows 窗体设计器生成的代码
24 |
25 | ///
26 | /// 设计器支持所需的方法 - 不要修改
27 | /// 使用代码编辑器修改此方法的内容。
28 | ///
29 | private void InitializeComponent()
30 | {
31 | this.tb_MaxConnection = new System.Windows.Forms.TextBox();
32 | this.bt_Start = new System.Windows.Forms.Button();
33 | this.label1 = new System.Windows.Forms.Label();
34 | this.tb_DomainOrIP = new System.Windows.Forms.TextBox();
35 | this.label2 = new System.Windows.Forms.Label();
36 | this.tb_Port = new System.Windows.Forms.TextBox();
37 | this.label3 = new System.Windows.Forms.Label();
38 | this.bt_Stop = new System.Windows.Forms.Button();
39 | this.label4 = new System.Windows.Forms.Label();
40 | this.cob_FirsIPType = new System.Windows.Forms.ComboBox();
41 | this.textBox1 = new System.Windows.Forms.TextBox();
42 | this.bt_Init = new System.Windows.Forms.Button();
43 | this.panel1 = new System.Windows.Forms.Panel();
44 | this.splitContainer1 = new System.Windows.Forms.SplitContainer();
45 | this.tb_Console = new System.Windows.Forms.TextBox();
46 | this.panel1.SuspendLayout();
47 | ((System.ComponentModel.ISupportInitialize)(this.splitContainer1)).BeginInit();
48 | this.splitContainer1.Panel1.SuspendLayout();
49 | this.splitContainer1.Panel2.SuspendLayout();
50 | this.splitContainer1.SuspendLayout();
51 | this.SuspendLayout();
52 | //
53 | // tb_MaxConnection
54 | //
55 | this.tb_MaxConnection.Location = new System.Drawing.Point(724, 18);
56 | this.tb_MaxConnection.Margin = new System.Windows.Forms.Padding(3, 4, 3, 4);
57 | this.tb_MaxConnection.Name = "tb_MaxConnection";
58 | this.tb_MaxConnection.Size = new System.Drawing.Size(56, 27);
59 | this.tb_MaxConnection.TabIndex = 3;
60 | this.tb_MaxConnection.Text = "10000";
61 | //
62 | // bt_Start
63 | //
64 | this.bt_Start.Location = new System.Drawing.Point(903, 16);
65 | this.bt_Start.Margin = new System.Windows.Forms.Padding(3, 4, 3, 4);
66 | this.bt_Start.Name = "bt_Start";
67 | this.bt_Start.Size = new System.Drawing.Size(84, 31);
68 | this.bt_Start.TabIndex = 100;
69 | this.bt_Start.Text = "Start";
70 | this.bt_Start.UseVisualStyleBackColor = true;
71 | this.bt_Start.Click += new System.EventHandler(this.bt_Start_Click);
72 | //
73 | // label1
74 | //
75 | this.label1.AutoSize = true;
76 | this.label1.Location = new System.Drawing.Point(13, 21);
77 | this.label1.Name = "label1";
78 | this.label1.Size = new System.Drawing.Size(108, 20);
79 | this.label1.TabIndex = 3;
80 | this.label1.Text = "Domain Or IP:";
81 | //
82 | // tb_DomainOrIP
83 | //
84 | this.tb_DomainOrIP.Location = new System.Drawing.Point(122, 18);
85 | this.tb_DomainOrIP.Name = "tb_DomainOrIP";
86 | this.tb_DomainOrIP.Size = new System.Drawing.Size(119, 27);
87 | this.tb_DomainOrIP.TabIndex = 1;
88 | this.tb_DomainOrIP.Text = "localhost";
89 | //
90 | // label2
91 | //
92 | this.label2.AutoSize = true;
93 | this.label2.Location = new System.Drawing.Point(267, 21);
94 | this.label2.Name = "label2";
95 | this.label2.Size = new System.Drawing.Size(44, 20);
96 | this.label2.TabIndex = 5;
97 | this.label2.Text = "Port:";
98 | //
99 | // tb_Port
100 | //
101 | this.tb_Port.Location = new System.Drawing.Point(314, 18);
102 | this.tb_Port.Name = "tb_Port";
103 | this.tb_Port.Size = new System.Drawing.Size(56, 27);
104 | this.tb_Port.TabIndex = 2;
105 | this.tb_Port.Text = "9000";
106 | //
107 | // label3
108 | //
109 | this.label3.AutoSize = true;
110 | this.label3.Location = new System.Drawing.Point(588, 21);
111 | this.label3.Name = "label3";
112 | this.label3.Size = new System.Drawing.Size(132, 20);
113 | this.label3.TabIndex = 7;
114 | this.label3.Text = "Max Connection:";
115 | //
116 | // bt_Stop
117 | //
118 | this.bt_Stop.Location = new System.Drawing.Point(1007, 16);
119 | this.bt_Stop.Margin = new System.Windows.Forms.Padding(3, 4, 3, 4);
120 | this.bt_Stop.Name = "bt_Stop";
121 | this.bt_Stop.Size = new System.Drawing.Size(84, 31);
122 | this.bt_Stop.TabIndex = 101;
123 | this.bt_Stop.Text = "Stop";
124 | this.bt_Stop.UseVisualStyleBackColor = true;
125 | this.bt_Stop.Click += new System.EventHandler(this.bt_Stop_Click);
126 | //
127 | // label4
128 | //
129 | this.label4.AutoSize = true;
130 | this.label4.Location = new System.Drawing.Point(402, 21);
131 | this.label4.Name = "label4";
132 | this.label4.Size = new System.Drawing.Size(101, 20);
133 | this.label4.TabIndex = 102;
134 | this.label4.Text = "First IP Type:";
135 | //
136 | // cob_FirsIPType
137 | //
138 | this.cob_FirsIPType.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
139 | this.cob_FirsIPType.FormattingEnabled = true;
140 | this.cob_FirsIPType.Items.AddRange(new object[] {
141 | "IPv4",
142 | "IPv6"});
143 | this.cob_FirsIPType.Location = new System.Drawing.Point(507, 17);
144 | this.cob_FirsIPType.Name = "cob_FirsIPType";
145 | this.cob_FirsIPType.Size = new System.Drawing.Size(56, 28);
146 | this.cob_FirsIPType.TabIndex = 103;
147 | //
148 | // textBox1
149 | //
150 | this.textBox1.Location = new System.Drawing.Point(59, 26);
151 | this.textBox1.Name = "textBox1";
152 | this.textBox1.Size = new System.Drawing.Size(119, 27);
153 | this.textBox1.TabIndex = 104;
154 | //
155 | // bt_Init
156 | //
157 | this.bt_Init.Location = new System.Drawing.Point(799, 16);
158 | this.bt_Init.Margin = new System.Windows.Forms.Padding(3, 4, 3, 4);
159 | this.bt_Init.Name = "bt_Init";
160 | this.bt_Init.Size = new System.Drawing.Size(84, 31);
161 | this.bt_Init.TabIndex = 105;
162 | this.bt_Init.Text = "Init";
163 | this.bt_Init.UseVisualStyleBackColor = true;
164 | this.bt_Init.Click += new System.EventHandler(this.bt_Init_Click);
165 | //
166 | // panel1
167 | //
168 | this.panel1.Controls.Add(this.tb_DomainOrIP);
169 | this.panel1.Controls.Add(this.bt_Init);
170 | this.panel1.Controls.Add(this.tb_MaxConnection);
171 | this.panel1.Controls.Add(this.bt_Start);
172 | this.panel1.Controls.Add(this.cob_FirsIPType);
173 | this.panel1.Controls.Add(this.label1);
174 | this.panel1.Controls.Add(this.label4);
175 | this.panel1.Controls.Add(this.label2);
176 | this.panel1.Controls.Add(this.bt_Stop);
177 | this.panel1.Controls.Add(this.tb_Port);
178 | this.panel1.Controls.Add(this.label3);
179 | this.panel1.Dock = System.Windows.Forms.DockStyle.Top;
180 | this.panel1.Location = new System.Drawing.Point(0, 0);
181 | this.panel1.Name = "panel1";
182 | this.panel1.Size = new System.Drawing.Size(1182, 67);
183 | this.panel1.TabIndex = 106;
184 | //
185 | // splitContainer1
186 | //
187 | this.splitContainer1.Dock = System.Windows.Forms.DockStyle.Fill;
188 | this.splitContainer1.FixedPanel = System.Windows.Forms.FixedPanel.Panel2;
189 | this.splitContainer1.Location = new System.Drawing.Point(0, 67);
190 | this.splitContainer1.Name = "splitContainer1";
191 | this.splitContainer1.Orientation = System.Windows.Forms.Orientation.Horizontal;
192 | //
193 | // splitContainer1.Panel1
194 | //
195 | this.splitContainer1.Panel1.Controls.Add(this.textBox1);
196 | //
197 | // splitContainer1.Panel2
198 | //
199 | this.splitContainer1.Panel2.Controls.Add(this.tb_Console);
200 | this.splitContainer1.Size = new System.Drawing.Size(1182, 566);
201 | this.splitContainer1.SplitterDistance = 360;
202 | this.splitContainer1.TabIndex = 107;
203 | //
204 | // tb_Console
205 | //
206 | this.tb_Console.BackColor = System.Drawing.Color.Black;
207 | this.tb_Console.Dock = System.Windows.Forms.DockStyle.Fill;
208 | this.tb_Console.ForeColor = System.Drawing.Color.White;
209 | this.tb_Console.Location = new System.Drawing.Point(0, 0);
210 | this.tb_Console.Multiline = true;
211 | this.tb_Console.Name = "tb_Console";
212 | this.tb_Console.ScrollBars = System.Windows.Forms.ScrollBars.Vertical;
213 | this.tb_Console.Size = new System.Drawing.Size(1182, 202);
214 | this.tb_Console.TabIndex = 0;
215 | //
216 | // F_Main
217 | //
218 | this.AutoScaleDimensions = new System.Drawing.SizeF(9F, 20F);
219 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
220 | this.ClientSize = new System.Drawing.Size(1182, 633);
221 | this.Controls.Add(this.splitContainer1);
222 | this.Controls.Add(this.panel1);
223 | this.Font = new System.Drawing.Font("微软雅黑", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
224 | this.Margin = new System.Windows.Forms.Padding(3, 4, 3, 4);
225 | this.Name = "F_Main";
226 | this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
227 | this.Text = "Socket Server";
228 | this.Load += new System.EventHandler(this.F_Main_Load);
229 | this.panel1.ResumeLayout(false);
230 | this.panel1.PerformLayout();
231 | this.splitContainer1.Panel1.ResumeLayout(false);
232 | this.splitContainer1.Panel1.PerformLayout();
233 | this.splitContainer1.Panel2.ResumeLayout(false);
234 | this.splitContainer1.Panel2.PerformLayout();
235 | ((System.ComponentModel.ISupportInitialize)(this.splitContainer1)).EndInit();
236 | this.splitContainer1.ResumeLayout(false);
237 | this.ResumeLayout(false);
238 |
239 | }
240 |
241 | #endregion
242 |
243 | private System.Windows.Forms.TextBox tb_MaxConnection;
244 | private System.Windows.Forms.Button bt_Start;
245 | private System.Windows.Forms.Label label1;
246 | private System.Windows.Forms.TextBox tb_DomainOrIP;
247 | private System.Windows.Forms.Label label2;
248 | private System.Windows.Forms.TextBox tb_Port;
249 | private System.Windows.Forms.Label label3;
250 | private System.Windows.Forms.Button bt_Stop;
251 | private System.Windows.Forms.Label label4;
252 | private System.Windows.Forms.ComboBox cob_FirsIPType;
253 | private System.Windows.Forms.TextBox textBox1;
254 | private System.Windows.Forms.Button bt_Init;
255 | private System.Windows.Forms.Panel panel1;
256 | private System.Windows.Forms.SplitContainer splitContainer1;
257 | private System.Windows.Forms.TextBox tb_Console;
258 | }
259 | }
260 |
261 |
--------------------------------------------------------------------------------
/ITnmg.IOCPSocket.WinFormServer/F_Main.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.ComponentModel;
4 | using System.Data;
5 | using System.Drawing;
6 | using System.Linq;
7 | using System.Net.Sockets;
8 | using System.Text;
9 | using System.Threading;
10 | using System.Threading.Tasks;
11 | using System.Windows.Forms;
12 |
13 | namespace ITnmg.IOCPSocket.WinFormServer
14 | {
15 | public partial class F_Main : Form
16 | {
17 | SynchronizationContext sync;
18 | SocketServerManager server;
19 | bool isInit = false;
20 |
21 | public F_Main()
22 | {
23 | InitializeComponent();
24 | }
25 |
26 | private void F_Main_Load( object sender, EventArgs e )
27 | {
28 | sync = SynchronizationContext.Current;
29 | this.cob_FirsIPType.SelectedIndex = 0;
30 | this.server = new SocketServerManager();
31 | this.server.ErrorEvent += Server_ErrorEvent;
32 | this.server.ServerStatusChangeEvent += Server_ServerStateChangeEvent;
33 | this.server.ConnectedStatusChangeEvent += Server_ConnectedStatusChangeEvent;
34 | }
35 |
36 | private void bt_Init_Click( object sender, EventArgs e )
37 | {
38 | InitAsync();
39 | }
40 |
41 | private void bt_Start_Click( object sender, EventArgs e )
42 | {
43 | StartAsync();
44 | }
45 |
46 | private void bt_Stop_Click( object sender, EventArgs e )
47 | {
48 | try
49 | {
50 | SetBtns( false );
51 | server.StopAsync();
52 | }
53 | catch ( Exception ex )
54 | {
55 | SetBtns( false );
56 | }
57 | }
58 |
59 | private async Task InitAsync()
60 | {
61 | this.bt_Init.Enabled = false;
62 | int maxCount = Convert.ToInt32( this.tb_MaxConnection.Text.Trim() );
63 |
64 | await this.server.InitAsync( maxCount, maxCount, new TextProtocol(), 4 * 1024, 100000, 100000 ).ContinueWith( f =>
65 | {
66 | if ( f.Exception == null )
67 | {
68 | this.isInit = true;
69 | }
70 | else
71 | {
72 | this.ShowMessageBox( "初始化失败: " + f.Exception.GetBaseException().Message );
73 | }
74 |
75 | this.AsyncPost( k =>
76 | {
77 | this.bt_Init.Enabled = true;
78 | }, "" );
79 | } );
80 | }
81 |
82 | private async Task StartAsync()
83 | {
84 | try
85 | {
86 | if ( !isInit )
87 | {
88 | await InitAsync();
89 | }
90 |
91 | SetBtns( true );
92 | string ip = this.tb_DomainOrIP.Text.Trim();
93 | int port = Convert.ToInt32( this.tb_Port.Text.Trim() );
94 | int maxConn = Convert.ToInt32( this.tb_MaxConnection.Text.Trim() );
95 | bool firstIPType = this.cob_FirsIPType.SelectedIndex == 0;
96 |
97 | await server.StartAsync( ip, port, firstIPType ).ContinueWith( f =>
98 | {
99 | if ( f.IsCompleted )
100 | {
101 | this.AsyncPost( k =>
102 | {
103 | this.tb_DomainOrIP.Text = k == null ? "" : k.Address.ToString();
104 | SetBtns( true );
105 | }, f.Result );
106 | }
107 | else
108 | {
109 | SetBtns( false );
110 | }
111 | } );
112 | }
113 | catch ( Exception ex )
114 | {
115 | if ( server != null )
116 | {
117 | await server.StopAsync();
118 | }
119 |
120 | SetBtns( true );
121 | }
122 | }
123 |
124 | private void Server_ErrorEvent( object sender, Exception e )
125 | {
126 | WriteConsole( $"Error: {e.Message}" );
127 | }
128 |
129 | private void Server_ServerStateChangeEvent( object sender, bool e )
130 | {
131 | this.SetBtns( e );
132 | WriteConsole( $"Server: {(e ? "启动" : "停止")}" );
133 | }
134 |
135 | private void Server_ConnectedStatusChangeEvent( object sender, SocketStatusChangeArgs e )
136 | {
137 | AsyncPost( f =>
138 | {
139 | this.textBox1.Text = e.ConnectedCount.ToString();
140 | }, e );
141 |
142 | if ( e.Error != null )
143 | {
144 | WriteConsole( $"UserTokenId:{e.UserTokenId}, Status:{e.Status}, ConnCount:{e.ConnectedCount}, Error:{e.Error}" );
145 | }
146 | }
147 |
148 |
149 | private void SetBtns( bool start )
150 | {
151 | this.bt_Init.Enabled = !start;
152 | this.bt_Start.Enabled = !start;
153 | this.bt_Stop.Enabled = start;
154 | }
155 |
156 | private void ShowMessageBox( string msg )
157 | {
158 | this.AsyncPost( f =>
159 | {
160 | MessageBox.Show( msg );
161 | }, msg );
162 | }
163 |
164 | private void AsyncPost( Action method, T state )
165 | {
166 | if ( this.sync != null )
167 | {
168 | this.sync.Post( f =>
169 | {
170 | method( (T)f );
171 | }, state );
172 | }
173 | }
174 |
175 | private void WriteConsole( string s )
176 | {
177 | this.AsyncPost( f =>
178 | {
179 | if ( this.tb_Console.Lines.Length > 20000 )
180 | {
181 | this.tb_Console.Text = "";
182 | }
183 |
184 | this.tb_Console.Text += (this.tb_Console.Text.Length > 0 ? "\r\n" : "") + s;
185 | this.tb_Console.SelectionStart = this.tb_Console.Text.Length;
186 | }, s );
187 | }
188 | }
189 | }
190 |
--------------------------------------------------------------------------------
/ITnmg.IOCPSocket.WinFormServer/F_Main.resx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 | text/microsoft-resx
110 |
111 |
112 | 2.0
113 |
114 |
115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
116 |
117 |
118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
119 |
120 |
--------------------------------------------------------------------------------
/ITnmg.IOCPSocket.WinFormServer/ITnmg.IOCPSocket.WinFormServer.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | {ED26CB42-B533-4823-872B-164FC0425905}
8 | WinExe
9 | Properties
10 | ITnmg.IOCPSocket.WinFormServer
11 | ITnmg.IOCPSocket.WinFormServer
12 | v4.6.2
13 | 512
14 | true
15 |
16 |
17 |
18 | x64
19 | true
20 | full
21 | false
22 | bin\Debug\
23 | DEBUG;TRACE
24 | prompt
25 | 4
26 |
27 |
28 | x64
29 | pdbonly
30 | true
31 | bin\Release\
32 | TRACE
33 | prompt
34 | 4
35 |
36 |
37 | true
38 | bin\x64\Debug\
39 | DEBUG;TRACE
40 | full
41 | x64
42 | prompt
43 | MinimumRecommendedRules.ruleset
44 | true
45 |
46 |
47 | bin\x64\Release\
48 | TRACE
49 | true
50 | pdbonly
51 | x64
52 | prompt
53 | MinimumRecommendedRules.ruleset
54 | true
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 | Form
71 |
72 |
73 | F_Main.cs
74 |
75 |
76 |
77 |
78 | F_Main.cs
79 |
80 |
81 | ResXFileCodeGenerator
82 | Resources.Designer.cs
83 | Designer
84 |
85 |
86 | True
87 | Resources.resx
88 | True
89 |
90 |
91 | SettingsSingleFileGenerator
92 | Settings.Designer.cs
93 |
94 |
95 | True
96 | Settings.settings
97 | True
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 | {aefceba4-0e8e-429d-ad10-4ace3bf794ff}
106 | ITnmg.IOCPSocket.Interface
107 |
108 |
109 | {2D636F35-8EC9-4002-8AF6-71CBE237C359}
110 | ITnmg.IOCPSocket
111 |
112 |
113 |
114 |
121 |
--------------------------------------------------------------------------------
/ITnmg.IOCPSocket.WinFormServer/Program.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Threading.Tasks;
5 | using System.Windows.Forms;
6 |
7 | namespace ITnmg.IOCPSocket.WinFormServer
8 | {
9 | static class Program
10 | {
11 | ///
12 | /// 应用程序的主入口点。
13 | ///
14 | [STAThread]
15 | static void Main()
16 | {
17 | Application.EnableVisualStyles();
18 | Application.SetCompatibleTextRenderingDefault( false );
19 | Application.Run( new F_Main() );
20 | }
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/ITnmg.IOCPSocket.WinFormServer/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // 有关程序集的一般信息由以下
6 | // 控制。更改这些特性值可修改
7 | // 与程序集关联的信息。
8 | [assembly: AssemblyTitle( "SocketServer" )]
9 | [assembly: AssemblyDescription( "" )]
10 | [assembly: AssemblyConfiguration( "" )]
11 | [assembly: AssemblyCompany( "" )]
12 | [assembly: AssemblyProduct( "SocketServer" )]
13 | [assembly: AssemblyCopyright( "Copyright © 2016" )]
14 | [assembly: AssemblyTrademark( "" )]
15 | [assembly: AssemblyCulture( "" )]
16 |
17 | //将 ComVisible 设置为 false 将使此程序集中的类型
18 | //对 COM 组件不可见。 如果需要从 COM 访问此程序集中的类型,
19 | //请将此类型的 ComVisible 特性设置为 true。
20 | [assembly: ComVisible( false )]
21 |
22 | // 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID
23 | [assembly: Guid( "ed26cb42-b533-4823-872b-164fc0425905" )]
24 |
25 | // 程序集的版本信息由下列四个值组成:
26 | //
27 | // 主版本
28 | // 次版本
29 | // 生成号
30 | // 修订号
31 | //
32 | //可以指定所有这些值,也可以使用“生成号”和“修订号”的默认值,
33 | // 方法是按如下所示使用“*”: :
34 | // [assembly: AssemblyVersion("1.0.*")]
35 | [assembly: AssemblyVersion( "1.0.0.0" )]
36 | [assembly: AssemblyFileVersion( "1.0.0.0" )]
37 |
--------------------------------------------------------------------------------
/ITnmg.IOCPSocket.WinFormServer/Properties/Resources.Designer.cs:
--------------------------------------------------------------------------------
1 | //------------------------------------------------------------------------------
2 | //
3 | // 此代码由工具生成。
4 | // 运行时版本:4.0.30319.42000
5 | //
6 | // 对此文件的更改可能会导致不正确的行为,并且如果
7 | // 重新生成代码,这些更改将会丢失。
8 | //
9 | //------------------------------------------------------------------------------
10 |
11 | namespace ITnmg.IOCPSocket.WinFormServer.Properties {
12 | using System;
13 |
14 |
15 | ///
16 | /// 一个强类型的资源类,用于查找本地化的字符串等。
17 | ///
18 | // 此类是由 StronglyTypedResourceBuilder
19 | // 类通过类似于 ResGen 或 Visual Studio 的工具自动生成的。
20 | // 若要添加或移除成员,请编辑 .ResX 文件,然后重新运行 ResGen
21 | // (以 /str 作为命令选项),或重新生成 VS 项目。
22 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
23 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
24 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
25 | internal class Resources {
26 |
27 | private static global::System.Resources.ResourceManager resourceMan;
28 |
29 | private static global::System.Globalization.CultureInfo resourceCulture;
30 |
31 | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
32 | internal Resources() {
33 | }
34 |
35 | ///
36 | /// 返回此类使用的缓存的 ResourceManager 实例。
37 | ///
38 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
39 | internal static global::System.Resources.ResourceManager ResourceManager {
40 | get {
41 | if (object.ReferenceEquals(resourceMan, null)) {
42 | global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("ITnmg.IOCPSocket.WinFormServer.Properties.Resources", typeof(Resources).Assembly);
43 | resourceMan = temp;
44 | }
45 | return resourceMan;
46 | }
47 | }
48 |
49 | ///
50 | /// 使用此强类型资源类,为所有资源查找
51 | /// 重写当前线程的 CurrentUICulture 属性。
52 | ///
53 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
54 | internal static global::System.Globalization.CultureInfo Culture {
55 | get {
56 | return resourceCulture;
57 | }
58 | set {
59 | resourceCulture = value;
60 | }
61 | }
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/ITnmg.IOCPSocket.WinFormServer/Properties/Resources.resx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 | text/microsoft-resx
107 |
108 |
109 | 2.0
110 |
111 |
112 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
113 |
114 |
115 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
116 |
117 |
--------------------------------------------------------------------------------
/ITnmg.IOCPSocket.WinFormServer/Properties/Settings.Designer.cs:
--------------------------------------------------------------------------------
1 | //------------------------------------------------------------------------------
2 | //
3 | // 此代码由工具生成。
4 | // 运行时版本:4.0.30319.42000
5 | //
6 | // 对此文件的更改可能会导致不正确的行为,并且如果
7 | // 重新生成代码,这些更改将会丢失。
8 | //
9 | //------------------------------------------------------------------------------
10 |
11 | namespace ITnmg.IOCPSocket.WinFormServer.Properties {
12 |
13 |
14 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
15 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "14.0.0.0")]
16 | internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
17 |
18 | private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
19 |
20 | public static Settings Default {
21 | get {
22 | return defaultInstance;
23 | }
24 | }
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/ITnmg.IOCPSocket.WinFormServer/Properties/Settings.settings:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/ITnmg.IOCPSocket.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 15
4 | VisualStudioVersion = 15.0.26403.3
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ITnmg.IOCPSocket", "ITnmg.IOCPSocket\ITnmg.IOCPSocket.csproj", "{2D636F35-8EC9-4002-8AF6-71CBE237C359}"
7 | EndProject
8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ITnmg.IOCPSocket.Interface", "ITnmg.IOCPSocket.Interface\ITnmg.IOCPSocket.Interface.csproj", "{AEFCEBA4-0E8E-429D-AD10-4ACE3BF794FF}"
9 | EndProject
10 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ITnmg.IOCPSocket.WinFormClient", "ITnmg.IOCPSocket.WinFormClient\ITnmg.IOCPSocket.WinFormClient.csproj", "{F2F6CF86-CF94-40CC-A4E0-48230AC989B7}"
11 | EndProject
12 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ITnmg.IOCPSocket.WinFormServer", "ITnmg.IOCPSocket.WinFormServer\ITnmg.IOCPSocket.WinFormServer.csproj", "{ED26CB42-B533-4823-872B-164FC0425905}"
13 | EndProject
14 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ITnmg.IOCPSocket.WPFServer", "ITnmg.IOCPSocket.WPFServer\ITnmg.IOCPSocket.WPFServer.csproj", "{EB08C901-88B9-44AA-AAA9-B771FEED7CB8}"
15 | EndProject
16 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Common", "Common", "{390C4640-69A6-42CA-946D-117D78D5ADF7}"
17 | ProjectSection(SolutionItems) = preProject
18 | README.md = README.md
19 | Common\SetMaxTCPConnection.reg = Common\SetMaxTCPConnection.reg
20 | EndProjectSection
21 | EndProject
22 | Global
23 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
24 | Debug|x64 = Debug|x64
25 | Release|x64 = Release|x64
26 | EndGlobalSection
27 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
28 | {2D636F35-8EC9-4002-8AF6-71CBE237C359}.Debug|x64.ActiveCfg = Debug|Any CPU
29 | {2D636F35-8EC9-4002-8AF6-71CBE237C359}.Debug|x64.Build.0 = Debug|Any CPU
30 | {2D636F35-8EC9-4002-8AF6-71CBE237C359}.Release|x64.ActiveCfg = Release|Any CPU
31 | {2D636F35-8EC9-4002-8AF6-71CBE237C359}.Release|x64.Build.0 = Release|Any CPU
32 | {AEFCEBA4-0E8E-429D-AD10-4ACE3BF794FF}.Debug|x64.ActiveCfg = Debug|Any CPU
33 | {AEFCEBA4-0E8E-429D-AD10-4ACE3BF794FF}.Debug|x64.Build.0 = Debug|Any CPU
34 | {AEFCEBA4-0E8E-429D-AD10-4ACE3BF794FF}.Release|x64.ActiveCfg = Release|Any CPU
35 | {AEFCEBA4-0E8E-429D-AD10-4ACE3BF794FF}.Release|x64.Build.0 = Release|Any CPU
36 | {F2F6CF86-CF94-40CC-A4E0-48230AC989B7}.Debug|x64.ActiveCfg = Debug|x64
37 | {F2F6CF86-CF94-40CC-A4E0-48230AC989B7}.Debug|x64.Build.0 = Debug|x64
38 | {F2F6CF86-CF94-40CC-A4E0-48230AC989B7}.Release|x64.ActiveCfg = Release|x64
39 | {F2F6CF86-CF94-40CC-A4E0-48230AC989B7}.Release|x64.Build.0 = Release|x64
40 | {ED26CB42-B533-4823-872B-164FC0425905}.Debug|x64.ActiveCfg = Debug|x64
41 | {ED26CB42-B533-4823-872B-164FC0425905}.Debug|x64.Build.0 = Debug|x64
42 | {ED26CB42-B533-4823-872B-164FC0425905}.Release|x64.ActiveCfg = Release|x64
43 | {ED26CB42-B533-4823-872B-164FC0425905}.Release|x64.Build.0 = Release|x64
44 | {EB08C901-88B9-44AA-AAA9-B771FEED7CB8}.Debug|x64.ActiveCfg = Debug|x64
45 | {EB08C901-88B9-44AA-AAA9-B771FEED7CB8}.Debug|x64.Build.0 = Debug|x64
46 | {EB08C901-88B9-44AA-AAA9-B771FEED7CB8}.Release|x64.ActiveCfg = Release|x64
47 | {EB08C901-88B9-44AA-AAA9-B771FEED7CB8}.Release|x64.Build.0 = Release|x64
48 | EndGlobalSection
49 | GlobalSection(SolutionProperties) = preSolution
50 | HideSolutionNode = FALSE
51 | EndGlobalSection
52 | EndGlobal
53 |
--------------------------------------------------------------------------------
/ITnmg.IOCPSocket/ITnmg.IOCPSocket.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | {2D636F35-8EC9-4002-8AF6-71CBE237C359}
8 | Library
9 | Properties
10 | ITnmg.IOCPSocket
11 | ITnmg.IOCPSocket
12 | v4.6.2
13 | 512
14 |
15 |
16 |
17 | true
18 | full
19 | false
20 | bin\Debug\
21 | DEBUG;TRACE
22 | prompt
23 | 4
24 | x64
25 |
26 |
27 | pdbonly
28 | true
29 | bin\Release\
30 | TRACE
31 | prompt
32 | 4
33 | x64
34 |
35 |
36 | true
37 | bin\x64\Debug\
38 | DEBUG;TRACE
39 | full
40 | x64
41 | prompt
42 | MinimumRecommendedRules.ruleset
43 |
44 |
45 | bin\x64\Release\
46 | TRACE
47 | true
48 | pdbonly
49 | x64
50 | prompt
51 | MinimumRecommendedRules.ruleset
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 | {aefceba4-0e8e-429d-ad10-4ace3bf794ff}
78 | ITnmg.IOCPSocket.Interface
79 |
80 |
81 |
82 |
89 |
--------------------------------------------------------------------------------
/ITnmg.IOCPSocket/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // 有关程序集的一般信息由以下
6 | // 控制。更改这些特性值可修改
7 | // 与程序集关联的信息。
8 | [assembly: AssemblyTitle("SocketServer")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("")]
12 | [assembly: AssemblyProduct("SocketServer")]
13 | [assembly: AssemblyCopyright("Copyright © 2016")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | //将 ComVisible 设置为 false 将使此程序集中的类型
18 | //对 COM 组件不可见。 如果需要从 COM 访问此程序集中的类型,
19 | //请将此类型的 ComVisible 特性设置为 true。
20 | [assembly: ComVisible(false)]
21 |
22 | // 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID
23 | [assembly: Guid("2d636f35-8ec9-4002-8af6-71cbe237c359")]
24 |
25 | // 程序集的版本信息由下列四个值组成:
26 | //
27 | // 主版本
28 | // 次版本
29 | // 生成号
30 | // 修订号
31 | //
32 | //可以指定所有这些值,也可以使用“生成号”和“修订号”的默认值,
33 | // 方法是按如下所示使用“*”: :
34 | // [assembly: AssemblyVersion("1.0.*")]
35 | [assembly: AssemblyVersion("1.0.0.0")]
36 | [assembly: AssemblyFileVersion("1.0.0.0")]
37 |
--------------------------------------------------------------------------------
/ITnmg.IOCPSocket/SocketAsyncEventArgsPool.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Concurrent;
3 | using System.Collections.Generic;
4 | using System.Linq;
5 | using System.Net.Sockets;
6 | using System.ServiceModel.Channels;
7 | using System.Text;
8 | using System.Threading.Tasks;
9 |
10 | namespace ITnmg.IOCPSocket
11 | {
12 | ///
13 | /// SocketAsyncEventArgs 管理池
14 | ///
15 | public class SocketAsyncEventArgsPool : IDisposable
16 | {
17 | ///
18 | /// SocketAsyncEventArgs 池
19 | ///
20 | private ConcurrentStack pool;
21 |
22 | ///
23 | /// 缓存管理
24 | ///
25 | private BufferManager bufferManager;
26 |
27 | ///
28 | /// SocketAsyncEventArgs 完成时的方法
29 | ///
30 | private EventHandler socketAsyncCompleted;
31 |
32 | ///
33 | /// SocketAsyncEventArgs 缓存最大字节数
34 | ///
35 | private int singleMaxBufferSize;
36 |
37 |
38 | ///
39 | /// 获取池中 SocketAsyncEventArgs 的数量
40 | ///
41 | public int Count
42 | {
43 | get
44 | {
45 | return pool == null ? 0 : pool.Count;
46 | }
47 | }
48 |
49 |
50 |
51 | ///
52 | /// 初始化 SocketAsyncEventArgs 池, 并设置 SocketAsyncEventArgs.Buffer 缓存.
53 | ///
54 | /// 初始状态容量大小
55 | /// SocketAsyncEventArgs.Completed 事件执行的方法
56 | /// SocketAsyncEventArgs.Buffer 的最大 Length, 默认为8K
57 | public SocketAsyncEventArgsPool( int capacity, EventHandler completed, int singleBufferMaxSize = 8 * 1024 )
58 | {
59 | socketAsyncCompleted = completed;
60 | singleMaxBufferSize = singleBufferMaxSize;
61 | //缓存池大小与SocketAsyncEventArgs池大小相同,因为每个SocketAsyncEventArgs只用一个缓存
62 | bufferManager = BufferManager.CreateBufferManager( singleBufferMaxSize * capacity, singleBufferMaxSize );
63 | pool = new ConcurrentStack();
64 |
65 | for ( int i = 0; i < capacity; i++ )
66 | {
67 | SocketAsyncEventArgs arg = TryCreateNew();
68 |
69 | if ( arg == null )
70 | {
71 | break;
72 | }
73 |
74 | pool.Push( arg );
75 | }
76 | }
77 |
78 | ///
79 | /// 初始化 SocketAsyncEventArgs 池, 并设置 SocketAsyncEventArgs.Buffer 缓存.
80 | ///
81 | /// 初始状态容量大小
82 | /// SocketAsyncEventArgs.Buffer 的最大 Length, 默认为32K
83 | public SocketAsyncEventArgsPool( int capacity, int singleMaxBufferSize = 32 * 1024 )
84 | : this( capacity, null, singleMaxBufferSize )
85 | {
86 | }
87 |
88 |
89 |
90 | ///
91 | /// 入栈
92 | ///
93 | /// SocketAsyncEventArgs 实例, 不可为null
94 | public void Push( SocketAsyncEventArgs item )
95 | {
96 | if ( item == null )
97 | {
98 | throw new ArgumentNullException( "item" );
99 | }
100 |
101 | lock ( this )
102 | {
103 | item.AcceptSocket = null;
104 | item.RemoteEndPoint = null;
105 | item.UserToken = null;
106 | item.DisconnectReuseSocket = true;
107 | }
108 |
109 | pool.Push( item );
110 | }
111 |
112 | ///
113 | /// 出栈, 如果为空则创建新的 SocketAsyncEventArgs 并设置初始值返回
114 | ///
115 | /// SocketAsyncEventArgs 实例
116 | public SocketAsyncEventArgs Pop()
117 | {
118 | SocketAsyncEventArgs result;
119 |
120 | if ( !pool.TryPop( out result ) )
121 | {
122 | lock ( this )
123 | {
124 | result = TryCreateNew();
125 | }
126 | }
127 |
128 | return result;
129 | }
130 |
131 | ///
132 | /// 清空堆栈
133 | ///
134 | public void Clear()
135 | {
136 | if ( pool != null )
137 | {
138 | pool.Clear();
139 | }
140 |
141 | if ( bufferManager != null )
142 | {
143 | bufferManager.Clear();
144 | }
145 | }
146 |
147 | ///
148 | /// 释放资源
149 | ///
150 | public void Dispose()
151 | {
152 | this.Clear();
153 | this.pool = null;
154 |
155 | if ( this.bufferManager != null )
156 | {
157 | this.bufferManager.Clear();
158 | this.bufferManager = null;
159 | }
160 |
161 | GC.SuppressFinalize( this );
162 | }
163 |
164 |
165 |
166 | ///
167 | /// 创建新 SocketAsyncEventArgs
168 | ///
169 | ///
170 | private SocketAsyncEventArgs TryCreateNew()
171 | {
172 | SocketAsyncEventArgs item = null;
173 | var buffer = bufferManager.TakeBuffer( singleMaxBufferSize );
174 |
175 | if ( buffer != null )
176 | {
177 | item = new SocketAsyncEventArgs();
178 | item.DisconnectReuseSocket = true;
179 | item.SetBuffer( buffer, 0, buffer.Length );
180 |
181 | if ( socketAsyncCompleted != null )
182 | {
183 | item.Completed += socketAsyncCompleted;
184 | }
185 | }
186 |
187 | return item;
188 | }
189 | }
190 | }
191 |
--------------------------------------------------------------------------------
/ITnmg.IOCPSocket/SocketClientManager.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections;
3 | using System.Collections.Concurrent;
4 | using System.Collections.Generic;
5 | using System.Linq;
6 | using System.Net;
7 | using System.Net.Sockets;
8 | using System.Text;
9 | using System.Threading;
10 | using System.Threading.Tasks;
11 |
12 | namespace ITnmg.IOCPSocket
13 | {
14 | ///
15 | /// Socket压力测试客户端
16 | ///
17 | public class SocketClientManager : SocketManagerBase
18 | {
19 | private IPEndPoint serverPoint;
20 |
21 | ///
22 | /// 客户端运行状态变化事件
23 | ///
24 | public event EventHandler ClientManagerStatusChangeEvent;
25 |
26 |
27 |
28 | ///
29 | /// 构造函数
30 | ///
31 | public SocketClientManager()
32 | {
33 | }
34 |
35 |
36 |
37 | ///
38 | /// 启动客户端任务
39 | ///
40 | public async Task StartAsync( string domainOrIP, int port, bool preferredIPv4 = true )
41 | {
42 | serverPoint = await GetIPEndPoint( domainOrIP, port, preferredIPv4 );
43 |
44 | Parallel.For( 0, maxConnCount, i =>
45 | {
46 | SocketAsyncEventArgs args = saePool.Pop();
47 | args.RemoteEndPoint = serverPoint;
48 | args.Completed += ConnectArgs_Completed;
49 |
50 | try
51 | {
52 | if ( !Socket.ConnectAsync( SocketType.Stream, ProtocolType.Tcp, args ) )
53 | {
54 | ConnectArgs_Completed( serverPoint, args );
55 | }
56 | }
57 | catch ( Exception ex )
58 | {
59 | OnError( this, ex );
60 | }
61 | } );
62 |
63 | OnClientManagerStatusChange( this, true );
64 | }
65 |
66 | ///
67 | /// 停止客户端任务
68 | ///
69 | ///
70 | public async Task StopAsync()
71 | {
72 | await CloseConnectList();
73 | OnClientManagerStatusChange( this, false );
74 | }
75 |
76 |
77 | ///
78 | /// 收到新连接
79 | ///
80 | ///
81 | ///
82 | private void ConnectArgs_Completed( object sender, SocketAsyncEventArgs e )
83 | {
84 | if ( e.SocketError == SocketError.Success )
85 | {
86 | e.UserToken = ToConnCompletedSuccess( e.ConnectSocket );
87 | }
88 | else
89 | {
90 | ToConnCompletedError( e.ConnectSocket, e.SocketError, e.UserToken as SocketUserToken );
91 | }
92 |
93 | //监听下一个请求
94 | e.UserToken = null;
95 | e.Dispose();
96 | e = null;
97 | }
98 |
99 | ///
100 | /// 引发 ClientManagerStatusChangeEvent 事件
101 | ///
102 | ///
103 | ///
104 | protected virtual void OnClientManagerStatusChange( object sender, bool e )
105 | {
106 | if ( ClientManagerStatusChangeEvent != null )
107 | {
108 | ClientManagerStatusChangeEvent( sender, e );
109 | }
110 | }
111 | }
112 | }
113 |
114 |
--------------------------------------------------------------------------------
/ITnmg.IOCPSocket/SocketManagerBase.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Concurrent;
3 | using System.Collections.Generic;
4 | using System.Linq;
5 | using System.Net;
6 | using System.Net.Sockets;
7 | using System.Text;
8 | using System.Threading;
9 | using System.Threading.Tasks;
10 |
11 | namespace ITnmg.IOCPSocket
12 | {
13 | ///
14 | /// IPCP Socket 服务端,客户端通用管理基类
15 | ///
16 | public abstract class SocketManagerBase
17 | {
18 | ///
19 | /// SocketAsyncEventArgs 池
20 | ///
21 | protected SocketAsyncEventArgsPool saePool;
22 |
23 | ///
24 | /// userToken 缓存集合
25 | ///
26 | protected ConcurrentStack entityPool;
27 |
28 | ///
29 | /// 允许的最大连接数量
30 | ///
31 | protected int maxConnCount;
32 |
33 | ///
34 | /// 启动时初始化多少个连接的资源
35 | ///
36 | protected int initConnectionResourceCount;
37 |
38 | ///
39 | /// 一次读写socket的最大缓存字节数
40 | ///
41 | protected int singleBufferMaxSize;
42 |
43 | ///
44 | /// 发送超时时间, 以毫秒为单位.
45 | ///
46 | protected int sendTimeOut;
47 |
48 | ///
49 | /// 接收超时时间, 以毫秒为单位.
50 | ///
51 | protected int receiveTimeOut;
52 |
53 | ///
54 | /// 信号量,初始设为 maxConnCount
55 | ///
56 | protected Semaphore semaphore;
57 |
58 | ///
59 | /// 已连接的集合
60 | ///
61 | protected ConcurrentDictionary connectedEntityList;
62 |
63 |
64 | ///
65 | /// 异常事件
66 | ///
67 | public event EventHandler ErrorEvent;
68 |
69 | ///
70 | /// Socket 连接状态改变事件
71 | ///
72 | public event EventHandler ConnectedStatusChangeEvent;
73 |
74 |
75 | ///
76 | /// 获取已连接的连接数
77 | ///
78 | public int TotalConnectedCount
79 | {
80 | get
81 | {
82 | return this.connectedEntityList.Count;
83 | }
84 | }
85 |
86 | ///
87 | /// 获取总连接数
88 | ///
89 | public int TotalCount
90 | {
91 | get
92 | {
93 | return this.maxConnCount;
94 | }
95 | }
96 |
97 | ///
98 | /// 获取 Socket 数据处理对象
99 | ///
100 | public ISocketBufferProcess BufferProcess
101 | {
102 | get;
103 | protected set;
104 | }
105 |
106 |
107 |
108 | ///
109 | /// 创建服务端实例
110 | ///
111 | public SocketManagerBase()
112 | {
113 | }
114 |
115 |
116 |
117 | ///
118 | /// 初始化管理
119 | ///
120 | /// 允许的最大连接数
121 | /// 启动时初始化多少个连接的资源
122 | /// 每个 socket 读写缓存最大字节数, 默认为8k
123 | /// socket 发送超时时长, 以毫秒为单位
124 | /// socket 接收超时时长, 以毫秒为单位
125 | public virtual async Task InitAsync( int maxConnectionCount, int initConnectionResourceCount, ISocketBufferProcess bufferProcess, int singleBufferMaxSize = 8 * 1024
126 | , int sendTimeOut = 10000, int receiveTimeOut = 10000 )
127 | {
128 | this.maxConnCount = maxConnectionCount;
129 | this.initConnectionResourceCount = initConnectionResourceCount;
130 | this.singleBufferMaxSize = singleBufferMaxSize;
131 | this.sendTimeOut = sendTimeOut;
132 | this.receiveTimeOut = receiveTimeOut;
133 |
134 | await Task.Run( () =>
135 | {
136 | this.semaphore = new Semaphore( this.maxConnCount, this.maxConnCount );
137 | //设置初始线程数为cpu核数*2
138 | this.connectedEntityList = new ConcurrentDictionary( Environment.ProcessorCount * 2, this.maxConnCount );
139 | //读写分离, 每个socket连接需要2个SocketAsyncEventArgs.
140 | saePool = new SocketAsyncEventArgsPool( this.initConnectionResourceCount * 2, SendAndReceiveArgs_Completed, this.singleBufferMaxSize );
141 |
142 | this.entityPool = new ConcurrentStack();
143 |
144 | Parallel.For( 0, initConnectionResourceCount, i =>
145 | {
146 | SocketUserToken token = new SocketUserToken( bufferProcess, singleBufferMaxSize );
147 | token.ReceiveArgs = saePool.Pop();
148 | token.SendArgs = saePool.Pop();
149 | this.entityPool.Push( token );
150 | } );
151 | } );
152 | }
153 |
154 |
155 |
156 | ///
157 | /// 引发 Error 事件
158 | ///
159 | ///
160 | ///
161 | protected virtual void OnError( object sender, Exception e )
162 | {
163 | if ( this.ErrorEvent != null )
164 | {
165 | this.ErrorEvent( sender, e );
166 | }
167 | }
168 |
169 | ///
170 | /// 引发 ConnectedStatusChangeEvent 事件
171 | ///
172 | ///
173 | ///
174 | ///
175 | ///
176 | protected virtual void OnConnectedStatusChange( object sender, int tokenId, bool status, SocketError? error )
177 | {
178 | if ( this.ConnectedStatusChangeEvent != null )
179 | {
180 | var arg = new SocketStatusChangeArgs();
181 | arg.UserTokenId = tokenId;
182 | arg.Status = status;
183 | arg.Error = error;
184 | arg.ConnectedCount = this.connectedEntityList.Count;
185 | this.ConnectedStatusChangeEvent( sender, arg );
186 | }
187 | }
188 |
189 |
190 |
191 | ///
192 | /// 分析ip或域名,返回 IPEndPoint 实例
193 | ///
194 | /// 要监听的域名或IP
195 | /// 端口
196 | /// 如果用域名初始化,可能返回多个ipv4和ipv6地址,指定是否首选ipv4地址.
197 | /// 返回 IPEndPoint 实例
198 | protected virtual async Task GetIPEndPoint( string domainOrIP, int port, bool preferredIPv4 = true )
199 | {
200 | IPEndPoint result = null;
201 |
202 | if ( !string.IsNullOrWhiteSpace( domainOrIP ) )
203 | {
204 | string ip = domainOrIP.Trim();
205 | IPAddress ipAddr = null;
206 |
207 | if ( !IPAddress.TryParse( ip, out ipAddr ) )
208 | {
209 | var addrs = await Dns.GetHostAddressesAsync( ip );
210 |
211 | if ( addrs == null || addrs.Length == 0 )
212 | {
213 | throw new Exception( "域名或ip地址不正确,未能解析." );
214 | }
215 |
216 | ipAddr = addrs.FirstOrDefault( k => k.AddressFamily == (preferredIPv4 ? AddressFamily.InterNetwork : AddressFamily.InterNetworkV6) );
217 | ipAddr = ipAddr ?? addrs.First();
218 | }
219 |
220 | result = new IPEndPoint( ipAddr, port );
221 | }
222 | else
223 | {
224 | result = new IPEndPoint( preferredIPv4 ? IPAddress.Any : IPAddress.IPv6Any, port );
225 | }
226 |
227 | return result;
228 | }
229 |
230 | ///
231 | /// 执行 socket 连接成功时的处理
232 | ///
233 | ///
234 | /// 返回 userToken
235 | protected virtual SocketUserToken ToConnCompletedSuccess( Socket s )
236 | {
237 | SocketUserToken result = null;
238 |
239 | try
240 | {
241 | //等待3秒,如果有空余资源,接收连接,否则断开socket.
242 | if ( semaphore.WaitOne( 3000 ) )
243 | {
244 | result = GetUserToken();
245 | result.CurrentSocket = s;
246 | result.Id = (int)s.Handle;
247 | result.ReceiveArgs.UserToken = result;
248 | result.SendArgs.UserToken = result;
249 |
250 | if ( connectedEntityList.TryAdd( result.Id, result ) )
251 | {
252 | if ( !result.CurrentSocket.ReceiveAsync( result.ReceiveArgs ) )
253 | {
254 | SendAndReceiveArgs_Completed( this, result.ReceiveArgs );
255 | }
256 |
257 | if ( !result.CurrentSocket.SendAsync( result.SendArgs ) )
258 | {
259 | SendAndReceiveArgs_Completed( this, result.SendArgs );
260 | }
261 |
262 | //SocketError.Success 状态回传null, 表示没有异常
263 | OnConnectedStatusChange( this, result.Id, true, null );
264 | }
265 | else
266 | {
267 | FreeUserToken( result );
268 | semaphore.Release();
269 | }
270 | }
271 | else
272 | {
273 | CloseSocket( s );
274 | }
275 | }
276 | catch ( Exception ex )
277 | {
278 | CloseSocket( s );
279 | OnError( this, ex );
280 | }
281 |
282 | return result;
283 | }
284 |
285 | ///
286 | /// 执行 socket 连接异常时的处理
287 | ///
288 | protected virtual void ToConnCompletedError( Socket s, SocketError error, SocketUserToken token )
289 | {
290 | try
291 | {
292 | FreeUserToken( RemoveUserToken( token ) );
293 | }
294 | catch ( Exception ex )
295 | {
296 | OnError( this, ex );
297 | }
298 | finally
299 | {
300 | CloseSocket( s );
301 | }
302 | }
303 |
304 | ///
305 | /// Socket 发送与接收完成事件执行的方法
306 | ///
307 | ///
308 | ///
309 | protected virtual void SendAndReceiveArgs_Completed( object sender, SocketAsyncEventArgs e )
310 | {
311 | var token = e.UserToken as SocketUserToken;
312 |
313 | if ( e.SocketError == SocketError.Success )
314 | {
315 | switch ( e.LastOperation )
316 | {
317 | case SocketAsyncOperation.Receive:
318 | if ( token != null )
319 | {
320 | //读取数据大于0,说明连接正常
321 | if ( token.ReceiveArgs.BytesTransferred > 0 )
322 | {
323 | try
324 | {
325 | token.ProcessReceive();
326 | }
327 | catch ( Exception ex )
328 | {
329 | FreeUserToken( RemoveUserToken( token ) );
330 | }
331 | }
332 | else //否则关闭连接,释放资源
333 | {
334 | FreeUserToken( RemoveUserToken( token ) );
335 | }
336 | }
337 | break;
338 | case SocketAsyncOperation.Send:
339 | if ( token != null )
340 | {
341 | try
342 | {
343 | token.ProcessSend();
344 | }
345 | catch ( Exception ex )
346 | {
347 | //否则关闭连接,释放资源
348 | FreeUserToken( RemoveUserToken( token ) );
349 | }
350 | }
351 | break;
352 | default:
353 | FreeUserToken( RemoveUserToken( token ) );
354 | break;
355 | }
356 | }
357 | else
358 | {
359 | FreeUserToken( RemoveUserToken( token ) );
360 | }
361 | }
362 |
363 | ///
364 | /// 获取一个 userToken 资源
365 | ///
366 | ///
367 | protected virtual SocketUserToken GetUserToken()
368 | {
369 | SocketUserToken result = null;
370 |
371 | if ( !entityPool.TryPop( out result ) )
372 | {
373 | result = new SocketUserToken( BufferProcess, singleBufferMaxSize );
374 | result.ReceiveArgs = saePool.Pop();
375 | result.SendArgs = saePool.Pop();
376 | }
377 |
378 | return result;
379 | }
380 |
381 | ///
382 | /// 释放 token 资源, 将 token 放回池
383 | ///
384 | /// 要释放的 token
385 | protected virtual void FreeUserToken( SocketUserToken token )
386 | {
387 | if ( token != null )
388 | {
389 | CloseSocket( token.CurrentSocket );
390 | token.Reset();
391 | entityPool.Push( token );
392 | }
393 | }
394 |
395 | ///
396 | /// 从已连接集合中移除指定的 token
397 | ///
398 | ///
399 | ///
400 | protected virtual SocketUserToken RemoveUserToken( SocketUserToken token )
401 | {
402 | SocketUserToken result = null;
403 |
404 | if ( token != null )
405 | {
406 | if ( connectedEntityList.TryRemove( token.Id, out result ) )
407 | {
408 | semaphore.Release();
409 | OnConnectedStatusChange( this, token.Id, false, null );
410 | }
411 | }
412 |
413 | return result;
414 | }
415 |
416 | ///
417 | /// 关闭已连接 socket 集合
418 | ///
419 | ///
420 | protected virtual async Task CloseConnectList()
421 | {
422 | await Task.Run( () =>
423 | {
424 | if ( this.connectedEntityList != null )
425 | {
426 | connectedEntityList.AsParallel().ForAll( f =>
427 | {
428 | FreeUserToken( RemoveUserToken( f.Value ) );
429 | } );
430 |
431 | this.connectedEntityList.Clear();
432 | }
433 | } );
434 | }
435 |
436 | ///
437 | /// 关闭 socket
438 | ///
439 | ///
440 | protected virtual void CloseSocket( Socket s )
441 | {
442 | if ( s != null )
443 | {
444 | try
445 | {
446 | s.Shutdown( SocketShutdown.Both );
447 | }
448 | catch ( Exception ex )
449 | {
450 | }
451 |
452 | //s.DisconnectAsync( true );
453 | s.Close();
454 | s.Dispose();
455 | s = null;
456 | }
457 | }
458 | }
459 | }
460 |
--------------------------------------------------------------------------------
/ITnmg.IOCPSocket/SocketServerManager.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Concurrent;
3 | using System.Collections.Generic;
4 | using System.Linq;
5 | using System.Net;
6 | using System.Net.Sockets;
7 | using System.Text;
8 | using System.Threading;
9 | using System.Threading.Tasks;
10 |
11 | namespace ITnmg.IOCPSocket
12 | {
13 | ///
14 | /// Socket服务端
15 | ///
16 | public class SocketServerManager : SocketManagerBase
17 | {
18 | ///
19 | /// 监听用的 socket
20 | ///
21 | protected Socket listenSocket;
22 |
23 | ///
24 | /// 服务端运行状态变化事件
25 | ///
26 | public event EventHandler ServerStatusChangeEvent;
27 |
28 |
29 |
30 | ///
31 | /// 创建服务端实例
32 | ///
33 | public SocketServerManager()
34 | {
35 | }
36 |
37 |
38 |
39 | ///
40 | /// 开始监听连接
41 | ///
42 | /// 要监听的域名或IP
43 | /// 端口
44 | /// 如果用域名初始化,可能返回多个ipv4和ipv6地址,指定是否首选ipv4地址.
45 | /// 用于监听的 socket 等待队列
46 | /// 返回实际监听的 EndPoint
47 | public virtual async Task StartAsync( string domainOrIP, int port, bool preferredIPv4 = true, int listenQueue = 200 )
48 | {
49 | IPEndPoint result = null;
50 |
51 | try
52 | {
53 | if ( this.listenSocket == null )
54 | {
55 | result = await GetIPEndPoint( domainOrIP, port, preferredIPv4 );
56 | this.listenSocket = new Socket( result.AddressFamily, SocketType.Stream, ProtocolType.Tcp );
57 | this.listenSocket.SendTimeout = this.sendTimeOut;
58 | this.listenSocket.ReceiveTimeout = this.receiveTimeOut;
59 | this.listenSocket.SendBufferSize = this.singleBufferMaxSize;
60 | this.listenSocket.ReceiveBufferSize = this.singleBufferMaxSize;
61 | this.listenSocket.Bind( result );
62 | this.listenSocket.Listen( listenQueue );
63 |
64 | SocketAsyncEventArgs args = new SocketAsyncEventArgs();
65 | args.SetBuffer( new byte[this.singleBufferMaxSize], 0, this.singleBufferMaxSize );
66 | args.DisconnectReuseSocket = true;
67 | args.Completed += AcceptArgs_Completed;
68 |
69 | if ( !this.listenSocket.AcceptAsync( args ) )
70 | {
71 | AcceptArgs_Completed( this.listenSocket, args );
72 | }
73 |
74 | OnServerStateChange( this, true );
75 | }
76 | else
77 | {
78 | result = this.listenSocket.LocalEndPoint as IPEndPoint;
79 | OnError( this, new Exception( "服务端已在运行" ) );
80 | }
81 | }
82 | catch ( Exception ex )
83 | {
84 | await this.StopAsync();
85 | this.OnError( this, ex );
86 | }
87 |
88 | return result;
89 | }
90 |
91 | ///
92 | /// 关闭监听
93 | ///
94 | public virtual async Task StopAsync()
95 | {
96 | if ( this.listenSocket != null )
97 | {
98 | try
99 | {
100 | await CloseConnectList();
101 | CloseSocket( this.listenSocket );
102 | OnServerStateChange( this, false );
103 | }
104 | catch ( Exception ex )
105 | {
106 | OnError( this, ex );
107 | }
108 | finally
109 | {
110 | this.listenSocket = null;
111 | }
112 | }
113 | }
114 |
115 |
116 | ///
117 | /// 监听 socket 接收到新连接
118 | ///
119 | ///
120 | ///
121 | protected virtual void AcceptArgs_Completed( object sender, SocketAsyncEventArgs e )
122 | {
123 | if ( e.SocketError == SocketError.Success )
124 | {
125 | //等待3秒,如果有空余资源,接收连接,否则断开socket.
126 | if ( semaphore.WaitOne( 3000 ) )
127 | {
128 | var result = GetUserToken();
129 | result.CurrentSocket = e.AcceptSocket;
130 | result.Id = (int)e.AcceptSocket.Handle;
131 | result.ReceiveArgs.UserToken = result;
132 | result.SendArgs.UserToken = result;
133 |
134 | if ( connectedEntityList.TryAdd( result.Id, result ) )
135 | {
136 | if ( !result.CurrentSocket.ReceiveAsync( result.ReceiveArgs ) )
137 | {
138 | SendAndReceiveArgs_Completed( this, result.ReceiveArgs );
139 | }
140 |
141 | if ( !result.CurrentSocket.SendAsync( result.SendArgs ) )
142 | {
143 | SendAndReceiveArgs_Completed( this, result.SendArgs );
144 | }
145 |
146 | //SocketError.Success 状态回传null, 表示没有异常
147 | OnConnectedStatusChange( this, result.Id, true, null );
148 | }
149 | else
150 | {
151 | FreeUserToken( result );
152 | semaphore.Release();
153 | }
154 | }
155 | else
156 | {
157 | CloseSocket( e.AcceptSocket );
158 | }
159 |
160 | //e.UserToken = ToConnCompletedSuccess( e.AcceptSocket );
161 | }
162 | else
163 | {
164 | ToConnCompletedError( e.AcceptSocket, e.SocketError, e.UserToken as SocketUserToken );
165 | }
166 |
167 | //监听下一个请求
168 | e.AcceptSocket = null;
169 | e.UserToken = null;
170 |
171 | if ( e.SocketError != SocketError.OperationAborted && this.listenSocket != null && !this.listenSocket.AcceptAsync( e ) )
172 | {
173 | AcceptArgs_Completed( this.listenSocket, e );
174 | }
175 | }
176 |
177 | ///
178 | /// 引发 ServerStateChange 事件
179 | ///
180 | ///
181 | ///
182 | protected virtual void OnServerStateChange( object sender, bool e )
183 | {
184 | if ( ServerStatusChangeEvent != null )
185 | {
186 | ServerStatusChangeEvent( sender, e );
187 | }
188 | }
189 | }
190 | }
191 |
--------------------------------------------------------------------------------
/ITnmg.IOCPSocket/SocketStatusChangeArgs.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Net.Sockets;
5 | using System.Text;
6 | using System.Threading.Tasks;
7 |
8 | namespace ITnmg.IOCPSocket
9 | {
10 | ///
11 | /// Socket 连接状态变更事件参数
12 | ///
13 | public class SocketStatusChangeArgs : EventArgs
14 | {
15 | ///
16 | /// 获取引发事件的 SocketUserToken Id
17 | ///
18 | public int UserTokenId
19 | {
20 | get;
21 | internal set;
22 | }
23 |
24 | ///
25 | /// 获取 Socket 当前状态
26 | ///
27 | public bool Status
28 | {
29 | get;
30 | internal set;
31 | }
32 |
33 | ///
34 | /// 获取 Socket 异常信息
35 | ///
36 | public SocketError? Error
37 | {
38 | get;
39 | internal set;
40 | }
41 |
42 | ///
43 | /// 获取当前已连接 Socket 数量
44 | ///
45 | public int ConnectedCount
46 | {
47 | get;
48 | internal set;
49 | }
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/ITnmg.IOCPSocket/SocketUserToken.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Concurrent;
3 | using System.Collections.Generic;
4 | using System.Collections.Specialized;
5 | using System.Linq;
6 | using System.Net.Sockets;
7 | using System.ServiceModel.Channels;
8 | using System.Text;
9 | using System.Threading.Tasks;
10 |
11 | namespace ITnmg.IOCPSocket
12 | {
13 | ///
14 | /// 异步 socket 关联的用户程序对象
15 | ///
16 | public class SocketUserToken
17 | {
18 | ///
19 | /// 缓存管理
20 | ///
21 | private BufferManager bufferManager;
22 |
23 |
24 | ///
25 | /// 获取或设置唯一Id
26 | ///
27 | public int Id
28 | {
29 | get; set;
30 | }
31 |
32 | ///
33 | /// 获取或设置当前 socket 连接
34 | ///
35 | public Socket CurrentSocket
36 | {
37 | get; set;
38 | }
39 |
40 | ///
41 | /// 获取或设置发送数据用的SocketAsyncEventArgs
42 | ///
43 | public SocketAsyncEventArgs ReceiveArgs
44 | {
45 | get; set;
46 | }
47 |
48 | ///
49 | /// 获取或设置接收数据用的SocketAsyncEventArgs
50 | ///
51 | public SocketAsyncEventArgs SendArgs
52 | {
53 | get; set;
54 | }
55 |
56 | ///
57 | /// 获取缓存数据处理对象
58 | ///
59 | public ISocketBufferProcess BufferProcess
60 | {
61 | get;
62 | private set;
63 | }
64 |
65 |
66 |
67 | ///
68 | /// 初始化 SocketUserToken 实例
69 | ///
70 | public SocketUserToken( ISocketBufferProcess bufferProcess, int singleBufferMaxSize )
71 | {
72 | this.BufferProcess = bufferProcess ?? throw new ArgumentNullException( "bufferProcess" );
73 | this.bufferManager = BufferManager.CreateBufferManager( 2, singleBufferMaxSize );
74 | this.Reset();
75 | }
76 |
77 |
78 |
79 | ///
80 | /// 重置为初始值
81 | ///
82 | public void Reset()
83 | {
84 | this.Id = -1;
85 | this.CurrentSocket = null;
86 | }
87 |
88 | ///
89 | /// 处理接收到的数据
90 | ///
91 | public void ProcessReceive()
92 | {
93 | BufferProcess.ProcessReceive( ReceiveArgs.Buffer, ReceiveArgs.BytesTransferred );
94 | }
95 |
96 | public void ProcessSend()
97 | {
98 | }
99 | }
100 | }
101 |
--------------------------------------------------------------------------------
/ITnmg.IOCPSocket/TextProtocol.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 |
7 | namespace ITnmg.IOCPSocket
8 | {
9 | public class TextProtocol : ISocketBufferProcess
10 | {
11 | public void GetNextSendBuffer( ref byte[] buffer, ref int effectiveLength )
12 | {
13 | }
14 |
15 | public bool ProcessReceive( byte[] buffer, int effectiveLength )
16 | {
17 | return true;
18 | }
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # ITnmg.IOCPSocket
2 |
3 | IOCP Socket Library & Socket Stress Test Tools
4 |
5 | 开发中...
6 |
--------------------------------------------------------------------------------