首页 > 解决方案 > NetMQ 路由器套接字(服务器)可以检测请求套接字(客户端)是否已达到超时?

问题描述

我正在使用 NetMQ v3.3.3.4 开发一个简单的服务器(RouterSocket)-客户端(RequestSocket)场景。它按预期工作,除了一件事。

有时服务器需要很长时间才能返回响应,并且客户端会超时。这种行为是需要的。这里的问题是服务器没有检测到客户端已经离开并且它继续处理请求。在某些时候处理完成并且服务器尝试返回响应。服务器永远不会意识到客户端不再监听并认为响应已成功传递。这会导致误导性的用户反馈和错误的日志文件条目。

服务器是否可以检测客户端是否仍在等待响应?

服务器

        private void Listen()
        {
            using (var poller = new NetMQPoller())
            using (var responseSocket = new RouterSocket())
            using (var poisonedSocket = new ResponseSocket())
            {
                responseSocket.Bind(_bindServerString);
                poisonedSocket.Bind(_bindTerminationString);

                var keepAliveTimer = new NetMQTimer(KeepAliveInterval);
                keepAliveTimer.Elapsed += (s, a) =>
                {
                    _monitorPublisher.Status["KeepAlive"] = Application.LocalDateTime.Now.ToString();
                    _monitorPublisher.SendStatus();
                };

                poisonedSocket.ReceiveReady += (s, a) =>
                {
                    a.Socket.ReceiveFrameBytes();
                    poller.Stop();
                };

                responseSocket.ReceiveReady += (s, a) =>
                {
                    try
                    {
                        bool header = true;
                        byte[] response = null;
                        while (a.Socket.TryReceiveFrameBytes(out byte[] message))
                        {
                            // Using a ROUTER socket...
                            if (header)
                            {
                                // We have to first, wait for the first frame,
                                // which is the address (header) of the REQ socket.
                                // Afterwards, we have to wait for the second frame,
                                // which is 0 and act as a delimiter between the REQ address
                                // and the actual body of the request.
                                a.Socket.SendFrame(message, true);

                                // Once we have the header delimiter, we can be sure that
                                // the next frame is the actual request.
                                header = !(message.Length == 0);
                            }
                            else
                            {
                                // Parse the request and return a response
                                BridgeRequestReceived?.Invoke(message, out response);
                                a.Socket.SendFrame(response);
                            }
                        }
                    }
                    catch (Exception e)
                    {
                        Logger.Instance.Log(e);
                    }
                };

                poller.Add(keepAliveTimer);
                poller.Add(responseSocket);
                poller.Add(poisonedSocket);

                Logger.Instance.Log($"Receiving requests on: {_bindServerString}", Application.LogCategory.Info);
                poller.Run();

                responseSocket.Close();
                poisonedSocket.Close();
            }
        }

客户

        private string SendRequest(IBridgeMessage request, out Exception e)
        {
            e = null;
            string response = null;
            using (var socket = new RequestSocket())
            {
                try
                {
                    socket.Connect(_endpoint);
                    byte[] encryptedRequest = CryptoAES.StandardCrypto.Encrypt(Encoding.UTF8.GetBytes(NMTBridgeMessageFactory.Serialize(request)));

                    socket.SendFrame(encryptedRequest);
                    if (socket.TryReceiveFrameBytes(_timeout, out byte[] reply))
                    {
                        response = Encoding.UTF8.GetString(CryptoAES.StandardCrypto.Decrypt(reply));
                    }
                    else
                    {
                        e = new TimeoutException("Timeout occured!");
                        response = null;
                    }
                }
                catch (Exception ex)
                {
                    e = ex;
                    response = null;
                }
            }

            return response;
        }

我希望服务器检测到客户端断开连接。

标签: c#netmq

解决方案


推荐阅读