FazBrowse GitHub Viewer
|
Trending
|
URL:
|
Home
Tools:
[Download Repo ZIP]
[View Raw Code]
[Original HTTPS Page]
NETCoreServer/source/NETCoreServer/TcpServer.cs at master · etheaven/NETCoreServer · GitHub
etheaven
NETCoreServer
Repository navigation
Code
Pull requests
Actions
Projects
Security and quality
Insights
Expand file tree
Breadcrumbs
NETCoreServer
/
source
/
NETCoreServer
/
TcpServer.cs
Copy path
More file actions
More file actions
Latest commit
History
History
History
261 lines (216 loc) · 7.81 KB
Breadcrumbs
NETCoreServer
/
source
/
NETCoreServer
/
TcpServer.cs
Copy path
File metadata and controls
261 lines (216 loc) · 7.81 KB
Raw
Copy raw file
Download raw file
Open symbols panel
Edit and raw actions
1
2
3
4
5
6
7
8
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
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
59
60
61
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
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
using
System
.
Diagnostics
;
using
System
.
Net
;
using
System
.
Net
.
Sockets
;
using
System
.
Threading
;
namespace
NETCoreServer
{
/// <summary>
/// TCP server is used to connect, disconnect and manage TCP sessions
/// </summary>
public
class
TcpServer
{
/// <summary>
/// Initialize TCP server with a given IP address and port number
/// </summary>
/// <param name="address">IP address</param>
/// <param name="port">Port number</param>
public
TcpServer
(
IPAddress
address
,
int
port
)
:
this
(
new
IPEndPoint
(
address
,
port
)
)
{
}
/// <summary>
/// Initialize TCP server with a given IP address and port number
/// </summary>
/// <param name="address">IP address</param>
/// <param name="port">Port number</param>
public
TcpServer
(
string
address
,
int
port
)
:
this
(
new
IPEndPoint
(
IPAddress
.
Parse
(
address
)
,
port
)
)
{
}
/// <summary>
/// Initialize TCP server with a given IP endpoint
/// </summary>
/// <param name="endpoint">IP endpoint</param>
public
TcpServer
(
IPEndPoint
endpoint
)
{
Endpoint
=
endpoint
;
}
/// <summary>
/// IP endpoint
/// </summary>
public
IPEndPoint
Endpoint
{
get
;
internal
set
;
}
/// <summary>
/// Number of sessions connected to the server
/// </summary>
public
long
ConnectedSessions
{
get
;
internal
set
;
}
/// <summary>
/// Number of bytes pending sent by the server
/// </summary>
public
long
BytesPending
{
get
;
internal
set
;
}
/// <summary>
/// Number of bytes sent by the server
/// </summary>
public
long
BytesSent
{
get
;
internal
set
;
}
/// <summary>
/// Number of bytes received by the server
/// </summary>
public
long
BytesReceived
{
get
;
internal
set
;
}
/// <summary>
/// Option: keep alive
/// </summary>
/// <remarks>
/// This option will setup SO_KEEPALIVE if the OS support this feature
/// </remarks>
public
bool
OptionKeepAlive
{
get
;
set
;
}
/// <summary>
/// Option: no delay
/// </summary>
/// <remarks>
/// This option will enable/disable Nagle's algorithm for TCP protocol
/// </remarks>
public
bool
OptionNoDelay
{
get
;
set
;
}
/// <summary>
/// Option: reuse address
/// </summary>
/// <remarks>
/// This option will enable/disable SO_REUSEADDR if the OS support this feature
/// </remarks>
public
bool
OptionReuseAddress
{
get
;
set
;
}
/// <summary>
/// Option: reuse port
/// </summary>
/// <remarks>
/// This option will enable/disable SO_REUSEPORT if the OS support this feature
/// </remarks>
public
bool
OptionReusePort
{
get
;
set
;
}
#region Start/Stop server
private
int
_acceptorBacklog
=
1024
;
private
Socket
_acceptorSocket
;
private
SocketAsyncEventArgs
_acceptorEventArg
;
/// <summary>
/// Is the server started?
/// </summary>
public
bool
IsStarted
{
get
;
private
set
;
}
/// <summary>
/// Is the server accepting new clients?
/// </summary>
public
bool
IsAccepting
{
get
;
private
set
;
}
/// <summary>
/// Start the server
/// </summary>
/// <returns>'true' if the server was successfully started, 'false' if the server failed to start</returns>
public
bool
Start
(
)
{
Debug
.
Assert
(
!
IsStarted
,
"TCP server is already started!"
)
;
if
(
IsStarted
)
return
false
;
// Create a new acceptor socket
_acceptorSocket
=
new
Socket
(
Endpoint
.
AddressFamily
,
SocketType
.
Stream
,
ProtocolType
.
Tcp
)
;
// Bind the acceptor socket to the IP endpoint
_acceptorSocket
.
Bind
(
Endpoint
)
;
// Start listen to the acceptor socket with the given accepting backlog size
_acceptorSocket
.
Listen
(
_acceptorBacklog
)
;
// Reset statistic
BytesPending
=
0
;
BytesSent
=
0
;
BytesReceived
=
0
;
// Update the started flag
IsStarted
=
true
;
// Call the server started handler
OnStarted
(
)
;
// Perform the first server accept
IsAccepting
=
true
;
_acceptorEventArg
=
new
SocketAsyncEventArgs
(
)
;
_acceptorEventArg
.
Completed
+=
AcceptorEventArg_Completed
;
StartAccept
(
_acceptorEventArg
)
;
return
true
;
}
/// <summary>
/// Stop the server
/// </summary>
/// <returns>'true' if the server was successfully stopped, 'false' if the server is already stopped</returns>
public
bool
Stop
(
)
{
Debug
.
Assert
(
IsStarted
,
"TCP server is not started!"
)
;
if
(
!
IsStarted
)
return
false
;
// Stop accepting new clients
IsAccepting
=
false
;
// Close the acceptor socket
_acceptorSocket
.
Close
(
)
;
// Disconnect all sessions
DisconnectAll
(
)
;
// Update the started flag
IsStarted
=
false
;
// Clear multicast buffer
ClearBuffers
(
)
;
// Call the server stopped handler
OnStopped
(
)
;
return
true
;
}
/// <summary>
/// Restart the server
/// </summary>
/// <returns>'true' if the server was successfully restarted, 'false' if the server failed to restart</returns>
public
bool
Restart
(
)
{
if
(
!
Stop
(
)
)
return
false
;
while
(
IsStarted
)
Thread
.
Yield
(
)
;
return
Start
(
)
;
}
/// <summary>
/// Handle server started notification
/// </summary>
protected
virtual
void
OnStarted
(
)
{
}
/// <summary>
/// Handle server stopped notification
/// </summary>
protected
virtual
void
OnStopped
(
)
{
}
/// <summary>
/// Handle error notification
/// </summary>
/// <param name="error">Socket error code</param>
protected
virtual
void
OnError
(
SocketError
error
)
{
}
#endregion
#region Accepting clients
/// <summary>
/// Start accept a new client connection
/// </summary>
private
void
StartAccept
(
SocketAsyncEventArgs
e
)
{
// Socket must be cleared since the context object is being reused
e
.
AcceptSocket
=
null
;
if
(
!
_acceptorSocket
.
AcceptAsync
(
e
)
)
ProcessAccept
(
e
)
;
}
/// <summary>
/// Process accepted client connection
/// </summary>
private
void
ProcessAccept
(
SocketAsyncEventArgs
e
)
{
// Accept the next client connection
if
(
IsAccepting
)
StartAccept
(
e
)
;
}
/// <summary>
/// This method is the callback method associated with Socket.AcceptAsync()
/// operations and is invoked when an accept operation is complete
/// </summary>
private
void
AcceptorEventArg_Completed
(
object
sender
,
SocketAsyncEventArgs
e
)
{
ProcessAccept
(
e
)
;
}
#endregion
#region Multicasting
/// <summary>
/// Clear multicast buffer
/// </summary>
private
void
ClearBuffers
(
)
{
}
#endregion
#region Session management
/// <summary>
/// Disconnect all connected sessions
/// </summary>
/// <returns>'true' if all sessions were successfully disconnected, 'false' if the server is not started</returns>
public
bool
DisconnectAll
(
)
{
return
true
;
}
#endregion
}
}
Back
|
FazBrowse Home
|
New Git URL