private async Task <SendMessageResult> sendMessageAsync(enTCPCommandCode command, ReadOnlyMemory <byte> message, int timeout, CancellationToken cancellationToken) { SendMessageResult result = new SendMessageResult { Bytes = 0, Packets = 0, }; ReadOnlyMemory <byte> tcpMessage = buildFinsTcpMessage(command, message); try { result.Bytes += await _client.SendAsync(tcpMessage, timeout, cancellationToken); result.Packets += 1; } catch (ObjectDisposedException) { throw new OmronException("Failed to Send FINS Message to Omron PLC '" + RemoteHost + ":" + Port + "' - The underlying Socket Connection was Closed"); } catch (TimeoutException) { throw new OmronException("Failed to Send FINS Message within the Timeout Period to Omron PLC '" + RemoteHost + ":" + Port + "'"); } catch (System.Net.Sockets.SocketException e) { throw new OmronException("Failed to Send FINS Message to Omron PLC '" + RemoteHost + ":" + Port + "'", e); } return(result); }
protected override async Task <SendMessageResult> SendMessageAsync(ReadOnlyMemory <byte> message, int timeout, CancellationToken cancellationToken) { SendMessageResult result = new SendMessageResult { Bytes = 0, Packets = 0, }; try { result.Bytes += await _client.SendAsync(message, timeout, cancellationToken); result.Packets += 1; } catch (ObjectDisposedException) { throw new OmronException("Failed to Send FINS Message to Omron PLC '" + RemoteHost + ":" + Port + "' - The underlying Socket Connection has been Closed"); } catch (TimeoutException) { throw new OmronException("Failed to Send FINS Message within the Timeout Period to Omron PLC '" + RemoteHost + ":" + Port + "'"); } catch (System.Net.Sockets.SocketException e) { throw new OmronException("Failed to Send FINS Message to Omron PLC '" + RemoteHost + ":" + Port + "'", e); } return(result); }
private async Task initializeClient(int timeout, CancellationToken cancellationToken) { _client = new TcpClient(RemoteHost, Port); await _client.ConnectAsync(timeout, cancellationToken); try { // Send Auto-Assign Client Node Request SendMessageResult sendResult = await sendMessageAsync(enTCPCommandCode.NodeAddressToPLC, new byte[4], timeout, cancellationToken); // Receive Client Node ID ReceiveMessageResult receiveResult = await receiveMessageAsync(enTCPCommandCode.NodeAddressFromPLC, timeout, cancellationToken); if (receiveResult.Message.Length < 8) { throw new OmronException("Failed to Negotiate a TCP Connection with Omron PLC '" + RemoteHost + ":" + Port + "' - TCP Negotiation Message Length was too Short"); } byte[] tcpNegotiationMessage = receiveResult.Message.Slice(0, 8).ToArray(); if (tcpNegotiationMessage[3] == 0 || tcpNegotiationMessage[3] == 255) { throw new OmronException("Failed to Negotiate a TCP Connection with Omron PLC '" + RemoteHost + ":" + Port + "' - TCP Negotiation Message contained an Invalid Local Node ID"); } _localNodeId = tcpNegotiationMessage[3]; if (tcpNegotiationMessage[7] == 0 || tcpNegotiationMessage[7] == 255) { throw new OmronException("Failed to Negotiate a TCP Connection with Omron PLC '" + RemoteHost + ":" + Port + "' - TCP Negotiation Message contained an Invalid Remote Node ID"); } _remoteNodeId = tcpNegotiationMessage[7]; } catch (OmronException e) { throw new OmronException("Failed to Negotiate a TCP Connection with Omron PLC '" + RemoteHost + ":" + Port + "'", e); } }
internal async Task <ProcessRequestResult> ProcessRequestAsync(FINSRequest request, int timeout, int retries, CancellationToken cancellationToken) { int attempts = 0; Memory <byte> responseMessage = new Memory <byte>(); int bytesSent = 0; int packetsSent = 0; int bytesReceived = 0; int packetsReceived = 0; DateTime startTimestamp = DateTime.UtcNow; while (attempts <= retries) { try { if (!_semaphore.Wait(0)) { await _semaphore.WaitAsync(cancellationToken); } if (attempts > 0) { await DestroyAndInitializeClient(timeout, cancellationToken); } // Build the Request into a Message we can Send ReadOnlyMemory <byte> requestMessage = request.BuildMessage(getNextRequestId()); // Send the Message SendMessageResult sendResult = await SendMessageAsync(requestMessage, timeout, cancellationToken); bytesSent += sendResult.Bytes; packetsSent += sendResult.Packets; // Receive a Response ReceiveMessageResult receiveResult = await ReceiveMessageAsync(timeout, cancellationToken); bytesReceived += receiveResult.Bytes; packetsReceived += receiveResult.Packets; responseMessage = receiveResult.Message; break; } catch (Exception) { if (attempts >= retries) { throw; } } finally { _semaphore.Release(); } // Increment the Attempts attempts++; } try { return(new ProcessRequestResult { BytesSent = bytesSent, PacketsSent = packetsSent, BytesReceived = bytesReceived, PacketsReceived = packetsReceived, Duration = DateTime.UtcNow.Subtract(startTimestamp).TotalMilliseconds, Response = FINSResponse.CreateNew(responseMessage, request), }); } catch (FINSException e) { if (e.Message.Contains("Service ID") && responseMessage.Length >= 9 && responseMessage.Span[9] != request.ServiceID) { try { if (!_semaphore.Wait(0)) { await _semaphore.WaitAsync(cancellationToken); } await PurgeReceiveBuffer(timeout, cancellationToken); } catch { } finally { _semaphore.Release(); } } throw new OmronException("Received a FINS Error Response from Omron PLC '" + _remoteHost + ":" + _port + "'", e); } }