代码之家  ›  专栏  ›  技术社区  ›  Mark Baijens

等待传入的TCP/IP服务器请求

  •  0
  • Mark Baijens  · 技术社区  · 6 年前

    我正在为我的应用程序构建一个与仓库系统的TCP/IP连接。沟通是这样的。

    • 我向仓库系统的TCP/IP(套接字)服务器发送消息。
    • 仓库系统以消息my local tcp/ip server响应。

    所以没有直接的响应消息。而是将每个应用程序作为自己的服务器。 然而,我希望我的应用程序等待来自另一台服务器的响应。

    所以基本上我有以下代码。

    public string ControllerFunction() {
        startLocalTcpIpServer();
        sendMessage("a message");
    
        return clientMessage;
    }
    

    这是我自己用start()函数启动的服务器

        public void Start() {
            // Start TcpServer background thread        
            tcpListenerThread = new Thread(new ThreadStart(ListenForIncommingRequests)) {
                IsBackground = true
            };
            tcpListenerThread.Start();
        }
    
        private void ListenForIncommingRequests() {
            try {
                tcpListener = new TcpListener(IPAddress.Parse(serverIp), port);
                tcpListener.Start();
                byte[] bytes = new byte[1024];
                Console.WriteLine("Server Started");
                while(true) {
                    // Get a stream object for reading 
                    using(NetworkStream stream = tcpListener.AcceptTcpClient().GetStream()) {
                        int length;
                        // Read incomming stream into byte arrary.                      
                        while((length = stream.Read(bytes, 0, bytes.Length)) != 0) {
                            byte[] incommingData = new byte[length];
                            Array.Copy(bytes, 0, incommingData, 0, length);
                            // Convert byte array to string message.                            
                            string clientMessage = Encoding.ASCII.GetString(incommingData);
                        }
                    }
                }
            }
            catch(SocketException socketException) {
                Console.WriteLine("SocketException " + socketException.ToString());
            }
        }
    

    所以我想使用结果字符串 clientMessage 再次作为我的控制器功能的返回。但是,如何以正确的方式获取数据呢?

    1 回复  |  直到 6 年前
        1
  •  1
  •   Tomas Chabada    6 年前

    因此,您需要能够等待来自应用程序中其他位置(本地服务器)的响应。将首先在那里触发响应。本地服务器应具有可订阅的事件( OnMessage 在我的例子中)。此事件将向您转发结果消息。

    可以使用TaskCompletionSource处理同步。您将创建可用于同步或异步获取结果的任务。

    像这样:

    public string ControllerFunction()
    {           
        return ControllerFunctionTask().Result;
    }
    
    public Task<string> ControllerFunctionTask()
    {            
        sendMessage("a message");
    
        var task = new TaskCompletionSource<string>();
        localServer.OnMessage = (message) =>
        {
            task.SetResult(message);
        };
    
        return task.Task;
    }
    

    如注释所述,同步等待异步任务可能导致死锁。当调用线程为 context 线程(UI、ASP)。因此,这应该是更好的方法:

    public async Task<string> ControllerFunction()
    {           
        return await ControllerFunctionTask();
    }
    
    public Task<string> ControllerFunctionTask()
    {            
        sendMessage("a message");
    
        var task = new TaskCompletionSource<string>();
        localServer.OnMessage = (message) =>
        {
            task.SetResult(message);
        };
    
        return task.Task;
    }
    


    OnMessage(打开消息) 可以这样定义:

    public event Action<string> OnMessage;
    

    然后,它将在您得到clientmessage字符串的行后立即调用:

    string clientMessage = Encoding.ASCII.GetString(incommingData);
    if (OnMessage != null)
         OnMessage(clientMessage);