我有一台设备(步进电机)通过TCP
连接到我的电脑。对发送到设备的消息的响应可以在几秒钟后返回(通常为3到15秒)
为了与设备通信,经过大量阅读后,我提出了以下class
:
public class TcpUtil : IDisposable
{
public event Action<TcpResponse> OnTcpMessage;
private int _port;
private string _ip;
private TcpClient _client;
private NetworkStream _stream;
public TcpUtil(string ip, int port)
{
_ip = ip;
_port = port;
_client = new TcpClient();
//connect with timeout
var connectResult = _client.BeginConnect(ip, port, null, null);
var success = connectResult.AsyncWaitHandle.WaitOne(3000);
if (!success)
{
throw new Exception("Connection timeout at " + ip);
}
// _stream is used for the duration of the object and cannot be used in a using block
_stream = _client.GetStream();
//start listening to incoming messages
Task.Factory.StartNew(() => Listen(_client));
}
private void Listen(TcpClient clientToUse)
{
while (clientToUse.Connected)
{
try
{
byte[] bytes = new byte[1024];
int bytesRead = _stream.Read(bytes, 0, bytes.Length);
string response = Encoding.ASCII.GetString(bytes, 0, bytesRead)
.Replace(Environment.NewLine, "");
if (OnTcpMessage != null && !string.IsNullOrWhiteSpace(response))
{
var message = new TcpResponse(response, _ip);
OnTcpMessage(message);
}
}
catch (Exception ex)
{
if (_client.Connected)
{
Debug.WriteLine("Listener error: " + ex.Message);
throw;
}
}
}
}
public void SendCommand(string command)
{
//device requirement - add a newline at the end of a message
if (!command.EndsWith(Environment.NewLine))
command = command + Environment.NewLine;
byte[] msg = Encoding.ASCII.GetBytes(command);
_stream.Write(msg, 0, msg.Length);
}
protected virtual void Dispose(bool disposing)
{
if (disposing)
{
if (_client != null)
{
_stream.Dispose();
_client.Close();
}
}
}
public void Dispose()
{
Dispose(true);
}
}
上面的代码有2个问题:
如何改进上述代码以解决这些问题?
答案 0 :(得分:0)
向您的类添加StreamReader
对象和消息队列:
private StreamReader _reader;
private ConcurrentQueue<string> _sentCommands;
按如下方式初始化变量:
_stream = _client.GetStream();
_reader = new StreamReader(_stream, Encoding.ASCII);
_sentCommands = new ConcurrentQueue<string>();
在SendMessage
消息中,跟踪发送的每条消息:
_sentCommands.Enqueue(command);
var msg = Encoding.ASCII.GetBytes(command);
_stream.Write(msg, 0, msg.Length);
然后在接收消息时,出队,你将有一个命令/响应对:
try
{
var response = _reader.ReadLine();
string command;
var result = _sentCommands.TryDequeue(out command);
if (OnTcpMessage != null && !string.IsNullOrWhiteSpace(response))
{
// Do something here to take advantage of the command variable
}
}
//... Rest of code here