You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将本地TCP/IP服务器收到的响应返回给ControllerFunction?

解决TCP服务器消息传递给控制器方法的问题

你的问题本质是要搞定跨线程的数据同步:后台跑的TCP监听线程收到仓储系统的消息后,怎么把消息传给主线程的ControllerFunction,还要让主线程等着,直到消息收到再返回。当前代码里后台线程的clientMessage是局部变量,主线程发完消息就直接返回,完全没等回复,肯定拿不到正确结果。

下面是修改后的完整实现,我给你加了线程同步和安全存储的逻辑:

using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;

public class WarehouseTcpHandler
{
    // 替换成你的本地监听IP和端口
    private readonly string _localIp = "127.0.0.1";
    private readonly int _localPort = 8888;
    // 替换成仓储系统的IP和端口
    private readonly string _warehouseIp = "仓储系统IP地址";
    private readonly int _warehousePort = 仓储系统端口号;

    private Thread _listenerThread;
    private TcpListener _tcpListener;
    // 标记服务器是否已启动,避免重复开线程
    private bool _isServerRunning;

    // 用于通知主线程"消息已收到"的同步信号
    private readonly ManualResetEventSlim _messageReceivedSignal = new ManualResetEventSlim(false);
    // 存储收到的消息,用锁保证多线程读写安全
    private string _receivedMessage;
    private readonly object _messageLock = new object();

    public void StartLocalServer()
    {
        if (_isServerRunning) return;

        _listenerThread = new Thread(ListenForWarehouseResponses)
        {
            IsBackground = true,
            Name = "WarehouseTcpListener"
        };
        _listenerThread.Start();
        _isServerRunning = true;
        Console.WriteLine("本地TCP服务器已启动,等待仓储系统回复...");
    }

    private void ListenForWarehouseResponses()
    {
        try
        {
            _tcpListener = new TcpListener(IPAddress.Parse(_localIp), _localPort);
            _tcpListener.Start();
            var buffer = new byte[1024];

            while (_isServerRunning)
            {
                // 等待仓储系统的连接
                using var client = _tcpListener.AcceptTcpClient();
                using var stream = client.GetStream();

                int bytesRead;
                // 读取流中的数据
                while ((bytesRead = stream.Read(buffer, 0, buffer.Length)) != 0)
                {
                    var incomingData = new byte[bytesRead];
                    Array.Copy(buffer, incomingData, bytesRead);
                    var message = Encoding.ASCII.GetString(incomingData);

                    // 线程安全地更新收到的消息
                    lock (_messageLock)
                    {
                        _receivedMessage = message;
                    }
                    // 发信号告诉主线程:消息到了!
                    _messageReceivedSignal.Set();
                }
            }
        }
        catch (SocketException ex)
        {
            Console.WriteLine($"TCP监听异常: {ex.Message}");
            _isServerRunning = false;
        }
    }

    public string ControllerFunction()
    {
        // 重置状态,准备接收新的消息
        _messageReceivedSignal.Reset();
        lock (_messageLock)
        {
            _receivedMessage = null;
        }

        // 启动本地服务器(如果还没启动)
        StartLocalServer();

        // 向仓储系统发送消息
        SendMessageToWarehouse("a message");

        // 等待仓储系统回复,设置30秒超时,防止无限阻塞
        if (_messageReceivedSignal.Wait(TimeSpan.FromSeconds(30)))
        {
            lock (_messageLock)
            {
                return _receivedMessage;
            }
        }
        else
        {
            throw new TimeoutException("超过30秒未收到仓储系统的回复,请检查连接");
        }
    }

    private void SendMessageToWarehouse(string message)
    {
        try
        {
            using var client = new TcpClient(_warehouseIp, _warehousePort);
            using var stream = client.GetStream();
            var data = Encoding.ASCII.GetBytes(message);
            stream.Write(data, 0, data.Length);
            Console.WriteLine($"已向仓储系统发送消息: {message}");
        }
        catch (SocketException ex)
        {
            throw new InvalidOperationException("无法连接到仓储系统服务器", ex);
        }
    }
}

关键逻辑说明:

  1. ManualResetEventSlim同步信号:这是主线程和后台监听线程的"通信工具"。后台线程收到消息后调用Set()触发信号,主线程用Wait()等着,直到信号触发或者超时。
  2. 线程安全的消息存储:用lock和私有锁对象_messageLock保护_receivedMessage,避免多线程同时读写导致的数据错乱。
  3. 服务器启动控制:加了_isServerRunning标志,防止多次调用ControllerFunction时重复启动监听线程。
  4. 超时机制:Wait(30秒)避免主线程无限等待,万一仓储系统没响应,也能及时抛出异常提示。

注意事项:

  • 如果是在ASP.NET这类Web应用中使用,要注意后台线程的生命周期,避免应用池回收导致线程终止。
  • 可以根据实际业务调整超时时间,比如改成10秒或者60秒。
  • 要确保_warehouseIp和_warehousePort配置正确,否则发消息会失败。

内容的提问来源于stack exchange,提问作者Mark Baijens

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 09:54:15