You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

92 lines
2.5 KiB

using System.Net.Sockets;
using System.Text;
namespace Housing.Services;
public sealed class TcpScpiClient : IScpiClient
{
private readonly TcpClient _tcpClient;
private readonly NetworkStream _stream;
private readonly int _timeoutMilliseconds;
private TcpScpiClient(TcpClient tcpClient, int timeoutMilliseconds)
{
_tcpClient = tcpClient;
_stream = _tcpClient.GetStream();
_timeoutMilliseconds = timeoutMilliseconds;
}
public static async Task<TcpScpiClient> ConnectAsync(string host, int port, int timeoutMilliseconds)
{
var tcpClient = new TcpClient();
using var cancellation = new CancellationTokenSource(timeoutMilliseconds);
try
{
await tcpClient.ConnectAsync(host, port, cancellation.Token);
}
catch (OperationCanceledException)
{
tcpClient.Dispose();
throw new TimeoutException($"{host}:{port} 장비 연결 시간이 초과되었습니다.");
}
catch
{
tcpClient.Dispose();
throw;
}
return new TcpScpiClient(tcpClient, timeoutMilliseconds);
}
public async Task SendAsync(string command)
{
using var cancellation = new CancellationTokenSource(_timeoutMilliseconds);
var bytes = Encoding.ASCII.GetBytes(command.Trim() + "\n");
await _stream.WriteAsync(bytes, cancellation.Token);
await _stream.FlushAsync(cancellation.Token);
}
public async Task<string> QueryAsync(string command)
{
await SendAsync(command);
using var cancellation = new CancellationTokenSource(_timeoutMilliseconds);
var buffer = new byte[1024];
var response = new StringBuilder();
while (true)
{
int bytesRead;
try
{
bytesRead = await _stream.ReadAsync(buffer, cancellation.Token);
}
catch (OperationCanceledException)
{
throw new TimeoutException($"{command} 응답 시간이 초과되었습니다.");
}
if (bytesRead == 0)
{
break;
}
var chunk = Encoding.ASCII.GetString(buffer, 0, bytesRead);
response.Append(chunk);
if (chunk.Contains('\n'))
{
break;
}
}
return response.ToString().Trim();
}
public void Dispose()
{
_stream.Dispose();
_tcpClient.Dispose();
}
}