C# 异步 TCP 侦听器

时间:2021-07-01 18:36:24

标签: c# asynchronous tcp

我有一个 Windows 控制台应用程序,旨在侦听 TCP 消息并将它们传递给处理程序。 我的问题是当处理程序忙于处理时。它阻止 TCP 侦听器接收新消息。我希望侦听器可以管理许多并发消息并且不会被任何其他处理阻塞。有没有办法让监听器异步。

TCP 监听器

using Abp.Dependency;
using Abp.Reflection.Extensions;
using Erx.Middleware.Configuration;
using Erx.Middleware.TCPCommunicator.Handlers;
using Microsoft.Extensions.Configuration;
using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace Erx.Middleware.TCPCommunicator.Executer
{
    public class TcpListenerExecuter : ITransientDependency
    {
        private readonly Log _log;
        private readonly IConfigurationRoot _appConfiguration;
        TcpListener tcpListener = null;
        TcpPLCClientExecuter _tcpPLCClientExecuter;
        MessageHandler _messageHandler;

        public TcpListenerExecuter(
            Log log, TcpPLCClientExecuter tcpPLCClientExecuter,
             MessageHandler messageHandler)
        {
            _log = log;
            _messageHandler = messageHandler;
            _tcpPLCClientExecuter = tcpPLCClientExecuter;
            _appConfiguration = AppConfigurations.Get(
              typeof(TcpCommunicatorModule).GetAssembly().GetDirectoryPathOrNull()
          );
        }

        public void Run()
        {
            var port = _appConfiguration.GetValue<string>("ServerDetails:Port");
            var localAddr = IPAddress.Parse(_appConfiguration.GetValue<string>("ServerDetails:IpAddress"));
            tcpListener = new TcpListener(localAddr, Convert.ToInt32(port));
            tcpListener.Start();
            StartListener();
        }

        public void StartListener()
        {
            try
            {
                while (true)
                {
                    _log.Write("Waiting for a connection...");
                    TcpClient client = tcpListener.AcceptTcpClient();
                    _log.Write("Connected!");
                    Thread t = new Thread(new ParameterizedThreadStart(HandleDeivce));
                    t.Start(client);
                }
            }
            catch (Exception e)
            {
                _log.Error(e.Message);
                _log.Error(e.StackTrace);
            }
            finally
            {
                // Stop listening for new clients.
                tcpListener.Stop();
            }

            Console.Read();
        }

        public void HandleDeivce(object obj)
        {
            var client = (TcpClient)obj;
            var stream = client.GetStream();
            byte[] bytes = new byte[256];
            int i;
            try
            {
                while ((i = stream.Read(bytes, 0, bytes.Length)) != 0)
                {
                    string data = Encoding.ASCII.GetString(bytes, 0, i);
                    _log.Write("Received:" + data + " thread:" + Thread.CurrentThread.ManagedThreadId);

                    var response = _messageHandler.ValidateMessage(data);
                    byte[] reply = Encoding.ASCII.GetBytes(response + " - " + data);
                    stream.Write(reply, 0, reply.Length);
                    _log.Write("Sent:" + response + ":" + data + " thread:" + Thread.CurrentThread.ManagedThreadId);

                    if (response == "OK")
                    {
                        _messageHandler.HandleMessages(data).GetAwaiter().GetResult();
                    }                  

                }
            }
            catch (Exception e) //TODO : FIX THIS ERROR HANDLE
            {
                _log.Error(e.Message);
                _log.Error(e.StackTrace);
                //client.Close();
                //client.Close();
            }

        }

    }


}

处理程序 - ASYNC AWAIT 函数正在阻塞侦听器

using Abp.Dependency;
using Abp.Events.Bus;
using Abp.Reflection.Extensions;
using Abp.Timing;
using Erx.Middleware.Configuration;
using Erx.Middleware.TCPCommunicator.Domain;
using Erx.Middleware.TCPCommunicator.Executer;
using Erx.Middleware.TCPCommunicator.Messages;
using Erx.Middleware.TCPCommunicator.Models;
using Microsoft.Extensions.Configuration;
using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace Erx.Middleware.TCPCommunicator.Handlers
{
    public class MessageHandler : ITransientDependency
    {
        public bool IsSystemStopped { get; set; } = false;
        public bool IsPSystemStopped { get; set; } = false;
        public bool IsDestackerStopped { get; set; } = false;
        public bool IsPDestackerStopped { get; set; } = false;
        public bool IsInitError { get; set; } = false;

        private readonly Log _log;
        private readonly IConfigurationRoot _appConfiguration;
        TcpPLCClientExecuter _tcpPLCClientExecuter;
        PLCMessages _PlcMessages;
        WorkItemManager _workItemManager;
        PrinterManager _printerManager;
        PdCommunicationsManager _pdCommunicationsManager;
        TcpMEKAExecuter _tcpMEKAExecuter;
        MKItemManager _mKItemManager;
        RDLCommunicationsManager _rdlManager;

        public IEventBus EventBus { get; set; }


        public MessageHandler(
            Log log,
            TcpPLCClientExecuter tcpPLCClientExecuter,
            PLCMessages PlcMessages,
            WorkItemManager workItemManager,
            PrinterManager printerManager,
            PdCommunicationsManager pdCommunicationsManager,
            TcpMEKAExecuter tcpMEKAExecuter,
            MKItemManager mKItemManager,
             RDLCommunicationsManager rdlManager)
        {
            _log = log;
            _tcpPLCClientExecuter = tcpPLCClientExecuter;
            _PlcMessages = PlcMessages;
            _workItemManager = workItemManager;
            _printerManager = printerManager;
            _pdCommunicationsManager = pdCommunicationsManager;
            _tcpMEKAExecuter = tcpMEKAExecuter;
            _mKItemManager = mKItemManager;
            _rdlManager = rdlManager;
            EventBus = NullEventBus.Instance;
            _appConfiguration = AppConfigurations.Get(
              typeof(TcpCommunicatorModule).GetAssembly().GetDirectoryPathOrNull()
          );
        }
        public string ValidateMessage(string message)
        {
            var length1 = 4 + MiddlewareConsts.NullBarcodeString.Length;
            var length2 = 31 + MiddlewareConsts.NullBarcodeString.Length;

            if (message.Length != length1)
            {
                return "Invalid Message Length";
            }

            if (message.Length > length1 && message.Length != length2)
            {
                return "Invalid Message Length";
            }

            return "OK";
        }

        async Task PutTaskDelay(int delay)
        {
            await Task.Delay(delay);
        }


        public async Task HandleMessages(string message)
        {
            try
            {
                var code = message.Substring(0, 2);
                var barcode = message.Substring(2, MiddlewareConsts.NullBarcodeString.Length);
                var pos = 3 + MiddlewareConsts.NullBarcodeString.Length;
                var pos2 = 2 + MiddlewareConsts.NullBarcodeString.Length;
                var rule = message.Substring(pos, 1);
                var type = message.Substring(pos2, 1);
                var isError = false;
                var msg = "";

                switch (code)
                {
                   
                    case "BA": 
                    
                      
                                    await _rdlManager.SendMessage(barcode, false);
                                    await _pdCommunicationsManager.SendPDUpdate("PICKING", barcode);
                                    await _printerManager.ConvertImages(barcode);                                   
                                    msg = "BA" + barcode + "!0";
                                    await _PlcMessages.SendMessage(msg);

                        break;
                    case "BB":  //Printer 1
                     
                         await _printerManager.PrintReceiptLabel(barcode);
                     
                        break;
                   

                    default:
                        msg = code + MiddlewareConsts.NullBarcodeString + "E0";
                        await _PlcMessages.SendMessage(msg);
                        break;
                }
            }
            catch (Exception e)
            {
                var msg = "AA" + MiddlewareConsts.NullBarcodeString + "E0";
                await _PlcMessages.SendMessage(msg);
            }


        }

    }


}

0 个答案:

没有答案