Dreamine.PLC.Mitsubishi.MC 1.0.1
Dreamine.PLC.Mitsubishi.MC 산업 자동화 및 I/O 기능을 제공합니다.
로딩중...
검색중...
일치하는것 없음
MitsubishiMcUdpSimulatorServer.cs
이 파일의 문서화 페이지로 가기
1using System.Net;
2using System.Net.Sockets;
3using Dreamine.PLC.Core.Memory;
4
6
15public sealed class MitsubishiMcUdpSimulatorServer : IAsyncDisposable
16{
43 private CancellationTokenSource? _cts;
52 private UdpClient? _udpClient;
61 private Task? _receiveTask;
62
87 : this(options, new InMemoryPlcMemory())
88 {
89 }
90
122 {
123 _options = options ?? throw new ArgumentNullException(nameof(options));
124 _protocol = new MitsubishiMcBinary3ESimulatorProtocol(memory ?? throw new ArgumentNullException(nameof(memory)), options);
125 _protocol.StatusChanged += OnProtocolStatusChanged;
126 }
127
136 public event EventHandler<string>? StatusChanged;
137
146 public bool IsRunning => _udpClient is not null;
147
171 public Task StartAsync(CancellationToken cancellationToken = default)
172 {
173 if (_udpClient is not null)
174 {
175 return Task.CompletedTask;
176 }
177
178 var address = ParseAddress(_options.Host);
179 _udpClient = new UdpClient(new IPEndPoint(address, _options.Port));
180 _cts = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken);
181 _receiveTask = Task.Run(() => ReceiveLoopAsync(_cts.Token), CancellationToken.None);
182 StatusChanged?.Invoke(this, $"MC UDP simulator server started. {_options.Host}:{_options.Port}");
183 return Task.CompletedTask;
184 }
185
202 public async Task StopAsync()
203 {
204 if (_udpClient is null)
205 {
206 return;
207 }
208
209 _cts?.Cancel();
210 _udpClient.Close();
211 _udpClient.Dispose();
212 _udpClient = null;
213
214 if (_receiveTask is not null)
215 {
216 try
217 {
218 await _receiveTask.ConfigureAwait(false);
219 }
220 catch (OperationCanceledException)
221 {
222 }
223 catch (ObjectDisposedException)
224 {
225 }
226 catch (SocketException)
227 {
228 }
229 }
230
231 _cts?.Dispose();
232 _cts = null;
233 StatusChanged?.Invoke(this, "MC UDP simulator server stopped.");
234 }
235
251 public async ValueTask DisposeAsync()
252 {
253 _protocol.StatusChanged -= OnProtocolStatusChanged;
254 await StopAsync().ConfigureAwait(false);
255 }
256
279 private async Task ReceiveLoopAsync(CancellationToken cancellationToken)
280 {
281 while (!cancellationToken.IsCancellationRequested && _udpClient is not null)
282 {
283 UdpReceiveResult request;
284 try
285 {
286 request = await _udpClient.ReceiveAsync(cancellationToken).ConfigureAwait(false);
287 }
288 catch (OperationCanceledException)
289 {
290 break;
291 }
292 catch (ObjectDisposedException)
293 {
294 break;
295 }
296 catch (SocketException)
297 {
298 break;
299 }
300
301 var response = _protocol.Execute(request.Buffer);
302 await _udpClient.SendAsync(response, response.Length, request.RemoteEndPoint).ConfigureAwait(false);
303 }
304 }
305
328 private static IPAddress ParseAddress(string host)
329 {
330 if (string.IsNullOrWhiteSpace(host) || host == "*" || host == "+")
331 {
332 return IPAddress.Any;
333 }
334
335 return IPAddress.TryParse(host, out var address) ? address : IPAddress.Any;
336 }
337
360 private void OnProtocolStatusChanged(object? sender, string e)
361 {
362 StatusChanged?.Invoke(this, e);
363 }
364}
MitsubishiMcUdpSimulatorServer(MitsubishiMcSimulatorServerOptions options, InMemoryPlcMemory memory)