gpt4 book ai didi

c# - 管理 TcpClient 连接

转载 作者:可可西里 更新时间:2023-11-01 02:43:28 24 4
gpt4 key购买 nike

我有一个设备(步进电机)通过 TCP 连接到我的 PC。对发送到设备的消息的响应可以在数秒(通常为 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);
}
}

上面的代码有两个问题:

  • 有时结果是连在一起的,而不是一个一个地读取(这真的很不一致)
  • 我找不到将已发送消息与其响应相关联的可靠方法

如何改进上面的代码以使其解决这些问题?

最佳答案

添加一个 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);

然后当接收到消息时,dequeue,就会有一个command/response对:

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

关于c# - 管理 TcpClient 连接,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34592241/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com