我正在使用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;
}
我希望服务器检测到客户端断开连接。