NetUdpServer.cs
11.7 KB
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
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
using HslCommunication.Core.Net;
using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
namespace HslCommunication.Enthernet
{
/// <summary>
/// Udp网络的服务器端类
/// </summary>
public class NetUdpServer : NetworkServerBase
{
/// <summary>
/// 获取或设置一次接收时的数据长度,默认2KB数据长度
/// </summary>
public int ReceiveCacheLength { get; set; } = 2048;
/// <summary>
/// 根据指定的端口启动Upd侦听
/// </summary>
/// <param name="port">端口号信息</param>
public override void ServerStart(int port)
{
if (!IsStarted)
{
CoreSocket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
//绑定网络地址
CoreSocket.Bind(new IPEndPoint(IPAddress.Any, port));
RefreshReceive();
LogNet?.WriteInfo(ToString(), StringResources.Language.NetEngineStart);
IsStarted = true;
}
}
/// <summary>
/// 关闭引擎的操作
/// </summary>
protected override void CloseAction()
{
AcceptString = null;
AcceptByte = null;
base.CloseAction();
}
/// <summary>
/// 重新开始接收数据
/// </summary>
/// <exception cref="ArgumentNullException"></exception>
private void RefreshReceive()
{
AppSession session = new AppSession();
session.WorkSocket = CoreSocket;
session.UdpEndPoint = new IPEndPoint(IPAddress.Any, 0);
session.BytesContent = new byte[ReceiveCacheLength];
// WorkSocket.BeginReceiveFrom(state.BytesHead, 0, 8, SocketFlags.None, ref state.UdpEndPoint, new AsyncCallback(ReceiveAsyncCallback), state);
CoreSocket.BeginReceiveFrom(session.BytesContent, 0, ReceiveCacheLength, SocketFlags.None, ref session.UdpEndPoint, new AsyncCallback(AsyncCallback), session);
}
private void AsyncCallback(IAsyncResult ar)
{
if (ar.AsyncState is AppSession session)
{
try
{
int received = session.WorkSocket.EndReceiveFrom(ar, ref session.UdpEndPoint);
// 释放连接关联
// session.WorkSocket = null;
// 马上开始重新接收,提供性能保障
RefreshReceive();
// 处理数据
if (received >= HslProtocol.HeadByteLength)
{
// 检测令牌
if (CheckRemoteToken(session.BytesContent))
{
session.IpEndPoint = (IPEndPoint)session.UdpEndPoint;
int contentLength = BitConverter.ToInt32(session.BytesContent, HslProtocol.HeadByteLength - 4);
if (contentLength == received - HslProtocol.HeadByteLength)
{
byte[] head = new byte[HslProtocol.HeadByteLength];
byte[] content = new byte[contentLength];
Array.Copy(session.BytesContent, 0, head, 0, HslProtocol.HeadByteLength);
if (contentLength > 0)
{
Array.Copy(session.BytesContent, 32, content, 0, contentLength);
}
// 解析内容
content = HslProtocol.CommandAnalysis(head, content);
int protocol = BitConverter.ToInt32(head, 0);
int customer = BitConverter.ToInt32(head, 4);
// 丢给数据中心处理
DataProcessingCenter(session, protocol, customer, content);
}
else
{
// 否则记录到日志
LogNet?.WriteWarn(ToString(), $"Should Rece:{(BitConverter.ToInt32(session.BytesContent, 4) + 8)} Actual:{received}");
}
}
else
{
LogNet?.WriteWarn(ToString(), StringResources.Language.TokenCheckFailed);
}
}
else
{
LogNet?.WriteWarn(ToString(), $"Receive error, Actual:{received}");
}
}
catch (ObjectDisposedException)
{
//主程序退出的时候触发
}
catch (Exception ex)
{
LogNet?.WriteException(ToString(), StringResources.Language.SocketEndReceiveException, ex);
//重新接收,此处已经排除掉了对象释放的异常
RefreshReceive();
}
finally
{
//state = null;
}
}
}
/***********************************************************************************************************
*
* 无法使用如下的字节头接收来确认网络传输,总是报错为最小
*
***********************************************************************************************************/
//private void ReceiveAsyncCallback(IAsyncResult ar)
//{
// if (ar.AsyncState is AsyncStateOne state)
// {
// try
// {
// state.AlreadyReceivedHead += state.WorkSocket.EndReceiveFrom(ar, ref state.UdpEndPoint);
// if (state.AlreadyReceivedHead < state.HeadLength)
// {
// //接续接收头数据
// WorkSocket.BeginReceiveFrom(state.BytesHead, state.AlreadyReceivedHead, state.HeadLength - state.AlreadyReceivedHead, SocketFlags.None,
// ref state.UdpEndPoint, new AsyncCallback(ReceiveAsyncCallback), state);
// }
// else
// {
// //开始接收内容
// int ReceiveLenght = BitConverter.ToInt32(state.BytesHead, 4);
// if (ReceiveLenght > 0)
// {
// state.BytesContent = new byte[ReceiveLenght];
// WorkSocket.BeginReceiveFrom(state.BytesContent, state.AlreadyReceivedContent, state.BytesContent.Length - state.AlreadyReceivedContent,
// SocketFlags.None, ref state.UdpEndPoint, new AsyncCallback(ContentReceiveAsyncCallback), state);
// }
// else
// {
// //没有内容了
// ThreadDealWithReveice(state, BitConverter.ToInt32(state.BytesHead, 0), state.BytesContent);
// state = null;
// RefreshReceive();
// }
// }
// }
// catch(Exception ex)
// {
// LogHelper.SaveError(StringResources.Language.异步数据结束挂起发送出错, ex);
// }
// }
//}
//private void ContentReceiveAsyncCallback(IAsyncResult ar)
//{
// if (ar.AsyncState is AsyncStateOne state)
// {
// try
// {
// state.AlreadyReceivedContent += state.WorkSocket.EndReceiveFrom(ar, ref state.UdpEndPoint);
// if (state.AlreadyReceivedContent < state.BytesContent.Length)
// {
// //还需要继续接收
// WorkSocket.BeginReceiveFrom(state.BytesContent, state.AlreadyReceivedContent, state.BytesContent.Length - state.AlreadyReceivedContent,
// SocketFlags.None, ref state.UdpEndPoint, new AsyncCallback(ContentReceiveAsyncCallback), state);
// }
// else
// {
// //接收完成了
// ThreadDealWithReveice(state, BitConverter.ToInt32(state.BytesHead, 0), new byte[0]);
// state = null;
// RefreshReceive();
// }
// }
// catch (Exception ex)
// {
// LogHelper.SaveError(StringResources.Language.异步数据结束挂起发送出错, ex);
// }
// }
//}
#region Data Process Center
/// <summary>
/// 数据处理中心
/// </summary>
/// <param name="receive"></param>
/// <param name="protocol"></param>
/// <param name="customer"></param>
/// <param name="content"></param>
internal override void DataProcessingCenter(AppSession receive, int protocol, int customer, byte[] content)
{
if (protocol == HslProtocol.ProtocolUserBytes)
{
AcceptByte?.Invoke(receive, customer, content);
}
else if (protocol == HslProtocol.ProtocolUserString)
{
// 接收到文本数据
string str = Encoding.Unicode.GetString(content);
AcceptString?.Invoke(receive, customer, str);
}
}
/// <summary>
/// 向指定的通信对象发送字符串数据
/// </summary>
/// <param name="session">通信对象</param>
/// <param name="customer">用户的指令头</param>
/// <param name="str">实际发送的字符串数据</param>
public void SendMessage(AppSession session, int customer, string str)
{
SendBytesAsync(session, HslProtocol.CommandBytes(customer, Token, str));
}
/// <summary>
/// 向指定的通信对象发送字节数据
/// </summary>
/// <param name="session">连接对象</param>
/// <param name="customer">用户的指令头</param>
/// <param name="bytes">实际的数据</param>
public void SendMessage(AppSession session, int customer, byte[] bytes)
{
SendBytesAsync(session, HslProtocol.CommandBytes(customer, Token, bytes));
}
private new void SendBytesAsync(AppSession session, byte[] data)
{
try
{
session.WorkSocket.SendTo(data, data.Length, SocketFlags.None, session.UdpEndPoint);
}
catch (Exception ex)
{
LogNet?.WriteException("SendMessage", ex);
}
}
#endregion
#region Event Handle
/// <summary>
/// 当接收到文本数据的时候,触发此事件
/// </summary>
public event Action<AppSession, NetHandle, string> AcceptString;
/// <summary>
/// 当接收到字节数据的时候,触发此事件
/// </summary>
public event Action<AppSession, NetHandle, byte[]> AcceptByte;
#endregion
#region Object Override
/// <summary>
/// 获取本对象的字符串表示形式
/// </summary>
/// <returns></returns>
public override string ToString()
{
return "NetUdpServer";
}
#endregion
}
}