144 public async Task<IoResult>
ConnectAsync(CancellationToken cancellationToken =
default)
146 if (
string.IsNullOrWhiteSpace(
_options.Host))
148 return IoResult.Failure(
"The Fastech host must not be empty.");
151 if (
_options.Port is <= 0 or > 65535)
153 return IoResult.Failure($
"Invalid TCP port: {_options.Port}.");
158 return IoResult.Failure(
"The connection timeout must be greater than zero.");
161 await
_syncLock.WaitAsync(cancellationToken).ConfigureAwait(
false);
169 return IoResult.Success();
179 using var timeoutCts = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken);
180 timeoutCts.CancelAfter(
_options.ConnectTimeoutMs);
185 return IoResult.Success();
187 catch (OperationCanceledException ex)
190 return IoResult.Failure(ex.Message);
195 return IoResult.Failure(ex.Message);
319 IReadOnlyList<byte> requestFrame,
320 int receiveTimeoutMs,
321 int expectedResponseLength,
322 CancellationToken cancellationToken =
default)
324 ArgumentNullException.ThrowIfNull(requestFrame);
326 if (requestFrame.Count == 0)
328 return IoResult<byte[]>.Failure(
"The request frame must not be empty.");
331 if (receiveTimeoutMs <= 0)
333 return IoResult<byte[]>.Failure(
"The receive timeout must be greater than zero.");
336 if (expectedResponseLength < 0)
338 return IoResult<byte[]>.Failure(
"The expected response length must not be negative.");
341 await
_syncLock.WaitAsync(cancellationToken).ConfigureAwait(
false);
349 return IoResult<byte[]>.Failure(
"The Fastech TCP transport is not connected.");
352 var requestBuffer = requestFrame as
byte[] ?? requestFrame.ToArray();
354 using var timeoutCts = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken);
355 timeoutCts.CancelAfter(receiveTimeoutMs);
357 await
_stream.WriteAsync(requestBuffer, timeoutCts.Token).ConfigureAwait(
false);
358 await
_stream.FlushAsync(timeoutCts.Token).ConfigureAwait(
false);
360 var response = expectedResponseLength > 0
364 return IoResult<byte[]>.Success(response);
366 catch (OperationCanceledException ex)
368 return IoResult<byte[]>.Failure(ex.Message);
372 return IoResult<byte[]>.Failure(ex.Message);
459 NetworkStream stream,
461 CancellationToken cancellationToken)
463 var buffer =
new byte[length];
466 while (offset < buffer.Length)
468 var read = await stream.ReadAsync(
469 buffer.AsMemory(offset, buffer.Length - offset),
470 cancellationToken).ConfigureAwait(
false);
474 throw new IOException(
"The remote Fastech endpoint closed the TCP connection.");