简体   繁体   English

简单的异步等待tcp服务器设计

[英]Simple async await tcp server design

I'm designing an asynchronous TCP server using async-await approach making use of event-driven .NET environment with the following features: 我正在使用async-await方法设计一个异步TCP服务器,利用事件驱动的.NET环境,具有以下功能:

  1. Request and response functionality. 请求和响应功能。
  2. Server side initiated events. 服务器端发起的事件。

Does this server design is correct in terms of async-await approach? 这种服务器设计在异步等待方法方面是否正确?
Code below covers only basic functionality to judge whether I'm missing something or not. 以下代码仅涵盖判断我是否遗漏某些内容的基本功能。
The server uses COM Type library, which is where PRMasterAutomation class comes from. 服务器使用COM Type库,这是PRMasterAutomation类的来源。

public class AsyncServer {
    private const int BufferSize = 4096;
    private static bool ServerRunning = true;       
    private List<TcpClient> clients = new List<TcpClient>();
    private PRMasterAutomation automation;

    public AsyncServer()
    {            
        InitializeComponent();
        automation = new PRMasterAutomation();
        automation.OnMonitoringEvent += automation_OnMonitoringEvent;

        if (!automation.Login("ADMIN", "")) 
            return;            

        if (automation.GetPRMasterState() == PRMasterStateEnum.StateIdle)
            automation.StartMonitoring();

        var tcpServer = new TcpListener(IPAddress.Any, 9001);
        tcpServer.Start();
        ListenForClients(tcpServer);                       
    }

    private async void ListenForClients(TcpListener tcpServer)
    {
        while (ServerRunning)
        {
            TcpClient tcpClient = await tcpServer.AcceptTcpClientAsync();
            clients.Add(tcpClient);
            ProcessClient(tcpClient);
        }
    }

    private async void ProcessClient(TcpClient tcpClient)
    {
        var stream = tcpClient.GetStream();
        var buffer = new byte[BufferSize];
        int amountRead;
        string xml;
        while (ServerRunning)            
        {
            if ((amountRead = await stream.ReadAsync(buffer, 0, BufferSize)) > 0)
            {
                var message = Encoding.ASCII.GetString(buffer, 0, amountRead);
                xml = "";
                if (message.Equals("get_users"))
                {
                    xml = automation.GetUsersXml();                                               
                }
                else if (message.Equals("get_events"))
                {
                    xml = automation.GetEventsHistoryXml("");
                }

                if (xml.Length > 0)
                {
                    xml += "\r\n"; 
                    await stream.WriteAsync(Encoding.ASCII.GetBytes(xml), 0, xml.Length);
                }
            }
        }
    }

    async void automation_OnMonitoringEvent(DateTime date, DateTime time, int networkID, int readerID, int userID, int groupID, int eventCode, int zoneID, int TandAID, string strEvent, string strAccessPoint, string strUserSource, string strGroup, string strNetwork, string strZone, string strTandAMode)
    {
        foreach (var c in clients)
        {
            if (c != null && c.Connected)
            {
                var stream = c.GetStream();
                StringBuilder sb = new StringBuilder();
                sb.Append(date.ToString() + ";" + time.ToString() + ";" + networkID.ToString() + ";" + userID.ToString() + "\r\n");
                await stream.WriteAsync(Encoding.ASCII.GetBytes(sb.ToString()), 0, sb.Length);
            }   
        }            
    }
}

Does this server design is correct in terms of async-await approach? 这种服务器设计在异步等待方法方面是否正确?

Yes, but not in terms of sockets. 是的,但不是套接字。 ReadAsync will return any number of bytes between 1 and infinite, it will not return messages. ReadAsync将返回1和无限之间的任意数量的字节,它不会返回消息。

Stream.ReadAsync() : The result value can be less than the number of bytes requested if the number of bytes currently available is less than the requested number, or it can be 0 (zero) if the end of the stream has been reached. Stream.ReadAsync() :如果当前可用的字节数小于请求的数字,则结果值可以小于请求的字节数,如果已到达流的末尾,则结果值可以是0(零)。

You have to create a buffer and keep reading and adding to that buffer until you know you have received a whole message. 您必须创建一个缓冲区并继续读取并添加到该缓冲区,直到您知道已收到整条消息。 This means checking for \\r\\n in your case. 这意味着在您的情况下检查\\r\\n If you encounter such a delimiter, you can extract the message from the buffer and start receiving a new message. 如果遇到这样的分隔符,则可以从缓冲区中提取消息并开始接收新消息。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM