public void Receive_BrokerDisconnectedWithLogging_ShouldReturnRequest() { const string host_address = "tcp://localhost:5555"; var loggingMessages = new List <string> (); // setup the counter socket for communication using (var ctx = NetMQContext.Create()) using (var broker = ctx.CreateRouterSocket()) using (var poller = new NetMQ.Poller()) using (var session = new MDPWorker(host_address, "test")) { broker.Bind(host_address); // we need to pick up any message in order to avoid errors but don't answer broker.ReceiveReady += (s, e) => e.Socket.ReceiveMessage(); poller.AddSocket(broker); var t = Task.Factory.StartNew(() => poller.Start()); // speed up the test session.HeartbeatDelay = TimeSpan.FromMilliseconds(250); session.ReconnectDelay = TimeSpan.FromMilliseconds(250); // set the event handler to receive the logging messages session.LogInfoReady += (s, e) => loggingMessages.Add(e.Info); // initialize the worker - broker protocol session.Receive(null); poller.Stop(); poller.RemoveSocket(broker); Assert.That(loggingMessages.Count(m => m.Contains("retrying")), Is.EqualTo(3)); // 3 times retrying and 1 time initial connecting Assert.That(loggingMessages.Count(m => m.Contains("localhost")), Is.EqualTo(4)); Assert.That(loggingMessages.Last().Contains("abandoning")); } }
public void ReceiveImplicitConnect_ValidScenario_ShouldReturnRequest() { const string host_address = "tcp://localhost:5557"; var loggingMessages = new List <string> (); // setup the counter socket for communication using (var ctx = NetMQContext.Create()) using (var broker = ctx.CreateRouterSocket()) using (var poller = new NetMQ.Poller()) using (var session = new MDPWorker(host_address, "test", new[] { (byte)'1' })) { broker.Bind(host_address); // we need to pick up any message in order to avoid errors broker.ReceiveReady += (s, e) => { var msg = e.Socket.ReceiveMessage(); // we expect to receive a 5 Frame mesage // [WORKER ADR][EMPTY]["MDPW01"]["READY"]["test"] if (msg.FrameCount != 5) { Assert.Fail("Message with wrong count of frames {0}", msg.FrameCount); } // make sure the frames are as expected Assert.That(msg[1], Is.EqualTo(NetMQFrame.Empty)); Assert.That(msg[2].ConvertToString(), Is.EqualTo("MDPW01")); Assert.That(msg[3].BufferSize, Is.EqualTo(1)); Assert.That(msg[3].Buffer[0], Is.EqualTo((byte)MDPCommand.Ready)); Assert.That(msg[4].ConvertToString(), Is.EqualTo("test")); // tell worker to stop gracefully var reply = new NetMQMessage(); reply.Push(new[] { (byte)MDPCommand.Kill }); // push MDP Version reply.Push(msg[2]); // push separator reply.Push(NetMQFrame.Empty); // push worker address reply.Push(msg[0]); // send reply which is a request for the worker e.Socket.SendMessage(reply); }; poller.AddSocket(broker); var t = Task.Factory.StartNew(() => poller.Start()); // set the event handler to receive the logging messages session.LogInfoReady += (s, e) => loggingMessages.Add(e.Info); // initialize the worker - broker protocol session.Receive(null); poller.Stop(); poller.RemoveSocket(broker); Assert.That(loggingMessages.Count, Is.EqualTo(5)); Assert.That(loggingMessages[0], Is.EqualTo("[WORKER] connected to broker at tcp://localhost:5557")); Assert.That(loggingMessages[1].Contains("[WORKER] sending"), Is.True); Assert.That(loggingMessages[2].Contains("[WORKER] received")); Assert.That(loggingMessages[4].Contains("abandoning")); } }
public void Receive_RequestWithWrongFirstFrame_ShouldThrowApplicationException() { const string host_address = "tcp://localhost:5555"; // setup the counter socket for communication using (var ctx = NetMQContext.Create()) using (var broker = ctx.CreateRouterSocket()) using (var poller = new NetMQ.Poller()) using (var session = new MDPWorker(host_address, "test")) { broker.Bind(host_address); // we need to pick up any message in order to avoid errors broker.ReceiveReady += (s, e) => { var msg = e.Socket.ReceiveMessage(); // we expect to receive a 5 Frame mesage // [WORKER ADR][EMPTY]["MDPW01"]["READY"]["test"] if (msg.FrameCount != 5) { Assert.Fail("Message with wrong count of frames {0}", msg.FrameCount); } // make sure the frames are as expected Assert.That(msg[1], Is.EqualTo(NetMQFrame.Empty)); Assert.That(msg[2].ConvertToString(), Is.EqualTo("MDPW01")); Assert.That(msg[3].BufferSize, Is.EqualTo(1)); Assert.That(msg[3].Buffer[0], Is.EqualTo((byte)MDPCommand.Ready)); Assert.That(msg[4].ConvertToString(), Is.EqualTo("test")); // tell worker to stop gracefully var reply = new NetMQMessage(); reply.Push(new[] { (byte)MDPCommand.Kill }); // push MDP Version reply.Push("MDPW01"); // push separator reply.Push("Should be empty"); // push worker address reply.Push(msg[0]); // send reply which is a request for the worker e.Socket.SendMessage(reply); }; poller.AddSocket(broker); var t = Task.Factory.StartNew(() => poller.Start()); try { var reply = session.Receive(null); } catch (ApplicationException ex) { Assert.That(ex.Message, Is.EqualTo("First frame must be an empty frame!")); } poller.Stop(); poller.RemoveSocket(broker); } }
public void Send_WrongHeaderFromBrokerNoLogging_ShouldThrowApplicationException() { const string host_address = "tcp://localhost:5555"; // setup the counter socket for communication using (var ctx = NetMQContext.Create()) using (var broker = ctx.CreateRouterSocket()) using (var poller = new Poller()) using (var session = new MDPClient(host_address)) { broker.Bind(host_address); // we need to pick up any message in order to avoid errors broker.ReceiveReady += (s, e) => { // return empty reply var msg = e.Socket.ReceiveMessage(); // we expect to receive a 4 Frame mesage // [REQ ADR][EMPTY]["MDPC01"]["echo"]["REQUEST"] if (msg.FrameCount != 5) { Assert.Fail("Message with wrong count of frames {0}", msg.FrameCount); } // REQUEST socket will strip the his address + empty frame // ROUTER has to add the address prelude in order to identify the correct socket(!) // [REQ ADR][EMPTY]["MDPC00"]["echo"]["REQUEST"] var clientAddress = msg.Pop(); msg.Pop(); // forget empty frame var mdpVersion = msg.Pop(); msg.Pop(); // drop service name version msg.Push("NoService"); msg.Push(mdpVersion); msg.Push(NetMQFrame.Empty); msg.Push(clientAddress); // reinsert the client's address e.Socket.SendMessage(msg); }; poller.AddSocket(broker); var t = Task.Factory.StartNew(() => poller.Start()); // well formed message var requestMessage = new NetMQMessage(new[] { new NetMQFrame("REQUEST") }); try { session.Send("echo", requestMessage); } catch (ApplicationException ex) { Assert.That(ex.Message, Is.EqualTo("[CLIENT INFO] answered by wrong service: NoService")); } poller.Stop(); poller.RemoveSocket(broker); } }
private void DisposeSynced() { Thread.MemoryBarrier(); m_poller.RemoveSocket(m_serverSocket); m_serverSocket.ReceiveReady -= m_currentMessageHandler; m_serverSocket.Dispose(); m_clientSocket.Dispose(); }
public void Send_CorrectInputWithLogging_ShouldReturnCorrectReply() { const string host_address = "tcp://localhost:5555"; var loggingMessages = new List <string> (); // setup the counter socket for communication using (var ctx = NetMQContext.Create()) using (var broker = ctx.CreateRouterSocket()) using (var poller = new Poller()) using (var session = new MDPClient(host_address)) { broker.Bind(host_address); // we need to pick up any message in order to avoid errors broker.ReceiveReady += (s, e) => { var msg = e.Socket.ReceiveMessage(); // we expect to receive a 4 Frame mesage // [client adrR][e][mdp header][service][request] if (msg.FrameCount != 5) { Assert.Fail("Message with wrong count of frames {0}", msg.FrameCount); } // REQUEST socket will strip the his address + empty frame // ROUTER has to add the address prelude in order to identify the correct socket(!) // [client adr][e][mdp header][service][reply] var request = msg.Last.ConvertToString(); // get the request string msg.RemoveFrame(msg.Last); // remove the request frame msg.Append(new NetMQFrame(request + " OK")); // append the reply frame e.Socket.SendMessage(msg); }; poller.AddSocket(broker); var t = Task.Factory.StartNew(() => poller.Start()); // set the event handler to receive the logging messages session.LogInfoReady += (s, e) => loggingMessages.Add(e.Info); // well formed message var requestMessage = new NetMQMessage(new[] { new NetMQFrame("REQUEST") }); // correct call var reply = session.Send("echo", requestMessage); poller.Stop(); poller.RemoveSocket(broker); Assert.That(reply.FrameCount, Is.EqualTo(1)); Assert.That(reply.First.ConvertToString(), Is.EqualTo("REQUEST OK")); Assert.That(loggingMessages.Count, Is.EqualTo(3)); Assert.That(loggingMessages[0], Is.EqualTo("[CLIENT] connecting to broker at tcp://localhost:5555")); Assert.That(loggingMessages[1].Contains("[CLIENT INFO] sending"), Is.True); Assert.That(loggingMessages[2].Contains("[CLIENT INFO] received"), Is.True); } }
public void Send_CorrectInputWithLogging_ShouldReturnCorrectReply() { const string hostAddress = "tcp://localhost:5555"; var loggingMessages = new List<string>(); // setup the counter socket for communication using (var context = NetMQContext.Create()) using (var broker = context.CreateRouterSocket()) using (var poller = new Poller()) using (var session = new MDPClient(hostAddress)) { broker.Bind(hostAddress); // we need to pick up any message in order to avoid errors broker.ReceiveReady += (s, e) => { var msg = e.Socket.ReceiveMessage(); // we expect to receive a 4 Frame message // [client adrR][e][mdp header][service][request] if (msg.FrameCount != 5) Assert.Fail("Message with wrong count of frames {0}", msg.FrameCount); // REQUEST socket will strip the his address + empty frame // ROUTER has to add the address prelude in order to identify the correct socket(!) // [client adr][e][mdp header][service][reply] var request = msg.Last.ConvertToString(); // get the request string msg.RemoveFrame(msg.Last); // remove the request frame msg.Append(new NetMQFrame(request + " OK")); // append the reply frame e.Socket.SendMessage(msg); }; poller.AddSocket(broker); Task.Factory.StartNew(poller.PollTillCancelled); // set the event handler to receive the logging messages session.LogInfoReady += (s, e) => loggingMessages.Add(e.Info); // well formed message var requestMessage = new NetMQMessage(new[] { new NetMQFrame("REQUEST") }); // correct call var reply = session.Send("echo", requestMessage); poller.CancelAndJoin(); poller.RemoveSocket(broker); Assert.That(reply.FrameCount, Is.EqualTo(1)); Assert.That(reply.First.ConvertToString(), Is.EqualTo("REQUEST OK")); Assert.That(loggingMessages.Count, Is.EqualTo(3)); Assert.That(loggingMessages[0], Is.EqualTo("[CLIENT] connecting to broker at tcp://localhost:5555")); Assert.That(loggingMessages[1].Contains("[CLIENT INFO] sending"), Is.True); Assert.That(loggingMessages[2].Contains("[CLIENT INFO] received"), Is.True); } }
public void Send_EmptyReplyFromBrokerWithLogging_ShouldThrowApplicationException() { const string host_address = "tcp://localhost:5555"; var loggingMessages = new List <string> (); // setup the counter socket for communication using (var ctx = NetMQContext.Create()) using (var broker = ctx.CreateRouterSocket()) using (var poller = new Poller()) using (var session = new MDPClient(host_address)) { broker.Bind(host_address); // we need to pick up any message in order to avoid errors broker.ReceiveReady += (s, e) => { // return empty reply var msg = e.Socket.ReceiveMessage(); // we expect to receive a 4 Frame mesage // [REQ ADR][EMPTY]["MDPC01"]["echo"]["REQUEST"] if (msg.FrameCount != 5) { Assert.Fail("Message with wrong count of frames {0}", msg.FrameCount); } // REQUEST socket will strip the his address + empty frame // ROUTER has to add the address prelude in order to identify the correct socket(!) // [REQ ADR][EMPTY]["MDPC01"]["echo"]["REQUEST"] e.Socket.SendMessage(msg); }; poller.AddSocket(broker); var t = Task.Factory.StartNew(() => poller.Start()); // set the event handler to receive the logging messages session.LogInfoReady += (s, e) => loggingMessages.Add(e.Info); // well formed message var requestMessage = new NetMQMessage(new[] { new NetMQFrame("REQUEST") }); // correct call session.Send("echo", requestMessage); poller.Stop(); poller.RemoveSocket(broker); Assert.That(loggingMessages.Count, Is.EqualTo(3)); Assert.That(loggingMessages[0], Is.EqualTo("[CLIENT] connecting to broker at tcp://localhost:5555")); Assert.That(loggingMessages[1].Contains("[CLIENT INFO] sending"), Is.True); Assert.That(loggingMessages[2].Contains("[CLIENT INFO] received"), Is.True); } }
/// <summary> /// run the broker - if not bound to endpoint automatically binds to known endpoint /// </summary> /// <param name="token">CancellationToken to cancel the method</param> /// <exception cref="InvalidOperationException">Can't start same broker more than once!</exception> public void RunSynchronous(CancellationToken token) { if (m_isRunning) { throw new InvalidOperationException("Can't start same broker more than once!"); } if (!m_isBound) { Bind(); } m_isRunning = true; using (var poller = new NetMQ.Poller()) { Socket.ReceiveReady += ProcessReceiveMessage; // get timer for scheduling heartbeat var timer = new NetMQTimer(HeartbeatInterval); // send every 'HeartbeatInterval' a heartbeat to all not expired workers timer.Elapsed += (s, e) => SendHeartbeat(); poller.AddSocket(Socket); poller.AddTimer(timer); Log("[BROKER] Starting to listen for incoming messages ..."); // start the poller and wait for the return, which will happen once token is // signalling Cancel(!) Task.Factory.StartNew(poller.Start, token).Wait(); Log("[BROKER] ... Stopped!"); // clean up poller.RemoveTimer(timer); poller.RemoveSocket(Socket); // unregister event handler Socket.ReceiveReady -= ProcessReceiveMessage; } m_isRunning = false; }
public void Send_WrongServiceNameWithLogging_ShouldLogPermanentError() { const string host_address = "tcp://localhost:5555"; var loggingMessages = new List <string> (); // setup the counter socket for communication using (var ctx = NetMQContext.Create()) using (var broker = ctx.CreateRouterSocket()) using (var poller = new Poller()) using (var session = new MDPClient(host_address)) { broker.Bind(host_address); // we need to pick up any message in order to avoid errors broker.ReceiveReady += (s, e) => { // just swallow message -> wrong service name var msg = e.Socket.ReceiveMessage(); }; poller.AddSocket(broker); var t = Task.Factory.StartNew(() => poller.Start()); // set the event handler to receive the logging messages session.LogInfoReady += (s, e) => loggingMessages.Add(e.Info); // well formed message var requestMessage = new NetMQMessage(new[] { new NetMQFrame("REQUEST") }); // wrong service name session.Send("xyz", requestMessage); poller.Stop(); poller.RemoveSocket(broker); Assert.That(loggingMessages.Count, Is.EqualTo(7)); Assert.That(loggingMessages[6], Is.EqualTo("[CLIENT ERROR] permanent error, abandoning!")); } }
public void AddTwoSocketAfterRemovingTest() { using (NetMQContext contex = NetMQContext.Create()) { // we are using three responses to make sure we actually //move the correct socket and other sockets still work using (var router = contex.CreateRouterSocket()) using (var router2 = contex.CreateRouterSocket()) using (var router3 = contex.CreateRouterSocket()) using (var router4 = contex.CreateRouterSocket()) { router.Bind("tcp://127.0.0.1:5002"); router2.Bind("tcp://127.0.0.1:5003"); router3.Bind("tcp://127.0.0.1:5004"); router4.Bind("tcp://127.0.0.1:5005"); using (var dealer = contex.CreateDealerSocket()) using (var dealer2 = contex.CreateDealerSocket()) using (var dealer3 = contex.CreateDealerSocket()) using (var dealer4 = contex.CreateDealerSocket()) using (Poller poller = new Poller()) { dealer.Connect("tcp://127.0.0.1:5002"); dealer2.Connect("tcp://127.0.0.1:5003"); dealer3.Connect("tcp://127.0.0.1:5004"); dealer4.Connect("tcp://127.0.0.1:5005"); int router1arrived = 0; int router2arrived = 0; bool router3arrived = false; bool router4arrived = false; bool more; //The ReceiveReady event is raised by the Poller router.ReceiveReady += (s, a) => { router1arrived++; router.Receive(out more); router.Receive(out more); poller.RemoveSocket(router); }; poller.AddSocket(router); //The ReceiveReady event is raised by the Poller router3.ReceiveReady += (s, a) => { router3.Receive(out more); router3.Receive(out more); router3arrived = true; }; //The ReceiveReady event is raised by the Poller router4.ReceiveReady += (s, a) => { router4.Receive(out more); router4.Receive(out more); router4arrived = true; }; //The ReceiveReady event is raised by the Poller router2.ReceiveReady += (s, a) => { router2arrived++; router2.Receive(out more); router2.Receive(out more); if (router2arrived == 1) { poller.AddSocket(router3); poller.AddSocket(router4); } }; poller.AddSocket(router2); Task task = Task.Factory.StartNew(poller.Start); dealer.Send("1"); Thread.Sleep(300); dealer2.Send("2"); Thread.Sleep(300); dealer3.Send("3"); dealer4.Send("4"); dealer2.Send("2"); dealer.Send("1"); Thread.Sleep(300); poller.Stop(true); task.Wait(); router.Receive(true, out more); Assert.IsTrue(more); router.Receive(true, out more); Assert.IsFalse(more); Assert.AreEqual(1, router1arrived); Assert.AreEqual(2, router2arrived); Assert.IsTrue(router3arrived); Assert.IsTrue(router4arrived); } } } }
/// <summary> /// run the broker - if not bound to endpoint automatically binds to known endpoint /// </summary> /// <param name="token">CancellationToken to cancel the method</param> /// <exception cref="InvalidOperationException">Can't start same broker more than once!</exception> public void RunSynchronous (CancellationToken token) { if (m_isRunning) throw new InvalidOperationException ("Can't start same broker more than once!"); if (!m_isBound) Bind (); m_isRunning = true; using (var poller = new Poller ()) { Socket.ReceiveReady += ProcessReceivedMessage; // get timer for scheduling heartbeat var timer = new NetMQTimer (HeartbeatInterval); // send every 'HeartbeatInterval' a heartbeat to all not expired workers timer.Elapsed += (s, e) => SendHeartbeat (); poller.AddSocket (Socket); poller.AddTimer (timer); Log ("Starting to listen for incoming messages ..."); // start the poller and wait for the return, which will happen once token is // signalling Cancel(!) Task.Factory.StartNew (poller.PollTillCancelled, token).Wait (); Log ("... Stopped!"); // clean up poller.RemoveTimer (timer); poller.RemoveSocket (Socket); // unregister event handler Socket.ReceiveReady -= ProcessReceivedMessage; } m_isRunning = false; }
public void Receive_RequestWithWrongMDPComand_ShouldLogCorrectMessage() { const string host_address = "tcp://localhost:5555"; var loggingMessages = new List <string> (); var first = true; // setup the counter socket for communication using (var ctx = NetMQContext.Create()) using (var broker = ctx.CreateRouterSocket()) using (var poller = new NetMQ.Poller()) using (var session = new MDPWorker(host_address, "test", Encoding.ASCII.GetBytes("Worker"), 2)) { broker.Bind(host_address); // we need to pick up any message in order to avoid errors broker.ReceiveReady += (s, e) => { var msg = e.Socket.ReceiveMessage(); // we expect to receive a 5 Frame mesage // [WORKER ADR][EMPTY]["MDPW01"]["READY"]["test"] if (msg.FrameCount != 5) { return; // it is a HEARTBEAT } // make sure the frames are as expected Assert.That(msg[1], Is.EqualTo(NetMQFrame.Empty)); Assert.That(msg[2].ConvertToString(), Is.EqualTo("MDPW01")); Assert.That(msg[3].BufferSize, Is.EqualTo(1)); Assert.That(msg[3].Buffer[0], Is.EqualTo((byte)MDPCommand.Ready)); Assert.That(msg[4].ConvertToString(), Is.EqualTo("test")); // tell worker to stop gracefully var reply = new NetMQMessage(); if (first) { reply.Push(new[] { (byte)0xff }); first = false; } else { reply.Push(new[] { (byte)MDPCommand.Kill }); } // push MDP Version reply.Push("MDPW01"); // push separator reply.Push(NetMQFrame.Empty); // push worker address reply.Push(msg[0]); // send reply which is a request for the worker e.Socket.SendMessage(reply); }; // set the event handler to receive the logging messages session.LogInfoReady += (s, e) => loggingMessages.Add(e.Info); poller.AddSocket(broker); var t = Task.Factory.StartNew(() => poller.Start()); session.HeartbeatDelay = TimeSpan.FromMilliseconds(250); session.ReconnectDelay = TimeSpan.FromMilliseconds(250); // initialize the worker - broker protocol session.Receive(null); Assert.That(loggingMessages.Count(m => m.Contains("[WORKER ERROR] invalid command received")), Is.EqualTo(1)); Assert.That(loggingMessages.Count(m => m.Contains("abandoning")), Is.EqualTo(1)); poller.Stop(); poller.RemoveSocket(broker); } }
public void Receive_REPLYtoREQUEST_ShouldSendCorrectReply() { const string host_address = "tcp://localhost:5557"; var loggingMessages = new List <string> (); // setup the counter socket for communication using (var ctx = NetMQContext.Create()) using (var broker = ctx.CreateRouterSocket()) using (var poller = new NetMQ.Poller()) using (var session = new MDPWorker(host_address, "test", new[] { (byte)'W', (byte)'1' })) { broker.Bind(host_address); // we need to pick up any message in order to avoid errors broker.ReceiveReady += (s, e) => { var msg = e.Socket.ReceiveMessage(); if (msg[3].Buffer[0] == (byte)MDPCommand.Ready) { // this is a READY message and we // send REQUEST message var request = new NetMQMessage(); request.Push("echo test"); // [request] request.Push(NetMQFrame.Empty); // [e][request] request.Push("C1"); // [client adr][e][request] request.Push(new[] { (byte)MDPCommand.Request }); // [command][client adr][e][request] request.Push(msg[2]); // [header][command][client adr][e][request] request.Push(NetMQFrame.Empty); // [e][header][command][client adr][e][request] request.Push(msg[0]); // [worker adr][e][header][command][client adr][e][request] // send reply which is a request for the worker e.Socket.SendMessage(request); } if (msg[3].Buffer[0] == (byte)MDPCommand.Reply) { // we expect to receive // [WORKER ADR][e]["MDPW01"][REPLY][CLIENT ADR][e][request == "echo test"] // make sure the frames are as expected Assert.That(msg[0].ConvertToString(), Is.EqualTo("W1")); Assert.That(msg[1], Is.EqualTo(NetMQFrame.Empty)); Assert.That(msg[2].ConvertToString(), Is.EqualTo("MDPW01")); Assert.That(msg[3].BufferSize, Is.EqualTo(1)); Assert.That(msg[3].Buffer[0], Is.EqualTo((byte)MDPCommand.Reply)); Assert.That(msg[4].ConvertToString(), Is.EqualTo("C1")); Assert.That(msg[5], Is.EqualTo(NetMQFrame.Empty)); Assert.That(msg[6].ConvertToString(), Is.EqualTo("echo test")); // tell worker to stop gracefully var reply = new NetMQMessage(); reply.Push(new[] { (byte)MDPCommand.Kill }); // push MDP Version reply.Push(msg[2]); // push separator reply.Push(NetMQFrame.Empty); // push worker address reply.Push(msg[0]); // send reply which is a request for the worker e.Socket.SendMessage(reply); } }; poller.AddSocket(broker); var t = Task.Factory.StartNew(() => poller.Start()); // set the event handler to receive the logging messages session.LogInfoReady += (s, e) => loggingMessages.Add(e.Info); // initialize the worker - broker protocol // and get initial request var workerRequest = session.Receive(null); // just echo the request session.Receive(workerRequest); poller.Stop(); poller.RemoveSocket(broker); Assert.That(loggingMessages.Count, Is.EqualTo(8)); Assert.That(loggingMessages[0], Is.EqualTo("[WORKER] connected to broker at tcp://localhost:5557")); Assert.That(loggingMessages[1].Contains("Ready")); Assert.That(loggingMessages[2].Contains("[WORKER] received")); Assert.That(loggingMessages[3].Contains("Request")); Assert.That(loggingMessages[4].Contains("Reply")); Assert.That(loggingMessages[6].Contains("Kill")); Assert.That(loggingMessages[7].Contains("abandoning")); } }
public void Receive_BrokerDisconnectedWithLogging_ShouldReturnRequest() { const string hostAddress = "tcp://localhost:5555"; var loggingMessages = new List<string> (); // setup the counter socket for communication using (var context = NetMQContext.Create ()) using (var broker = context.CreateRouterSocket ()) using (var poller = new Poller ()) using (var session = new MDPWorker (hostAddress, "test")) { broker.Bind (hostAddress); // we need to pick up any message in order to avoid errors but don't answer broker.ReceiveReady += (s, e) => e.Socket.ReceiveMultipartMessage (); poller.AddSocket (broker); Task.Factory.StartNew (poller.PollTillCancelled); // speed up the test session.HeartbeatDelay = TimeSpan.FromMilliseconds (250); session.ReconnectDelay = TimeSpan.FromMilliseconds (250); // set the event handler to receive the logging messages session.LogInfoReady += (s, e) => loggingMessages.Add (e.Info); // initialise the worker - broker protocol session.Receive (null); poller.CancelAndJoin (); poller.RemoveSocket (broker); Assert.That (loggingMessages.Count (m => m.Contains ("retrying")), Is.EqualTo (3)); // 3 times retrying and 1 time initial connecting Assert.That (loggingMessages.Count (m => m.Contains ("localhost")), Is.EqualTo (4)); Assert.That (loggingMessages.Last ().Contains ("abandoning")); } }
public void Receive_REPLYtoREQUEST_ShouldSendCorrectReply() { const string hostAddress = "tcp://localhost:5557"; var loggingMessages = new List<string> (); // setup the counter socket for communication using (var context = NetMQContext.Create ()) using (var broker = context.CreateRouterSocket ()) using (var poller = new Poller ()) using (var session = new MDPWorker (hostAddress, "test", new[] { (byte) 'W', (byte) '1' })) { broker.Bind (hostAddress); // we need to pick up any message in order to avoid errors broker.ReceiveReady += (s, e) => { var msg = e.Socket.ReceiveMultipartMessage (); if (msg[3].Buffer[0] == (byte) MDPCommand.Ready) { // this is a READY message and we // send REQUEST message var request = new NetMQMessage (); request.Push ("echo test"); // [request] request.Push (NetMQFrame.Empty); // [e][request] request.Push ("C1"); // [client adr][e][request] request.Push (new[] { (byte) MDPCommand.Request }); // [command][client adr][e][request] request.Push (msg[2]); // [header][command][client adr][e][request] request.Push (NetMQFrame.Empty); // [e][header][command][client adr][e][request] request.Push (msg[0]); // [worker adr][e][header][command][client adr][e][request] // send reply which is a request for the worker e.Socket.SendMessage (request); } if (msg[3].Buffer[0] == (byte) MDPCommand.Reply) { // we expect to receive // [WORKER ADR][e]["MDPW01"][REPLY][CLIENT ADR][e][request == "echo test"] // make sure the frames are as expected Assert.That (msg[0].ConvertToString (), Is.EqualTo ("W1")); Assert.That (msg[1], Is.EqualTo (NetMQFrame.Empty)); Assert.That (msg[2].ConvertToString (), Is.EqualTo ("MDPW01")); Assert.That (msg[3].BufferSize, Is.EqualTo (1)); Assert.That (msg[3].Buffer[0], Is.EqualTo ((byte) MDPCommand.Reply)); Assert.That (msg[4].ConvertToString (), Is.EqualTo ("C1")); Assert.That (msg[5], Is.EqualTo (NetMQFrame.Empty)); Assert.That (msg[6].ConvertToString (), Is.EqualTo ("echo test")); // tell worker to stop gracefully var reply = new NetMQMessage (); reply.Push (new[] { (byte) MDPCommand.Kill }); // push MDP Version reply.Push (msg[2]); // push separator reply.Push (NetMQFrame.Empty); // push worker address reply.Push (msg[0]); // send reply which is a request for the worker e.Socket.SendMessage (reply); } }; poller.AddSocket (broker); Task.Factory.StartNew (poller.PollTillCancelled); // set the event handler to receive the logging messages session.LogInfoReady += (s, e) => loggingMessages.Add (e.Info); // initialise the worker - broker protocol // and get initial request var workerRequest = session.Receive (null); // just echo the request session.Receive (workerRequest); poller.CancelAndJoin (); poller.RemoveSocket (broker); Assert.That (loggingMessages.Count, Is.EqualTo (8)); Assert.That (loggingMessages[0], Is.EqualTo ("[WORKER] connected to broker at tcp://localhost:5557")); Assert.That (loggingMessages[1].Contains ("Ready")); Assert.That (loggingMessages[2].Contains ("[WORKER] received")); Assert.That (loggingMessages[3].Contains ("Request")); Assert.That (loggingMessages[4].Contains ("Reply")); Assert.That (loggingMessages[6].Contains ("Kill")); Assert.That (loggingMessages[7].Contains ("abandoning")); } }
public void Receive_RequestWithWrongMDPComand_ShouldLogCorrectMessage() { const string hostAddress = "tcp://localhost:5555"; var loggingMessages = new List<string> (); var first = true; // setup the counter socket for communication using (var context = NetMQContext.Create ()) using (var broker = context.CreateRouterSocket ()) using (var poller = new Poller ()) using (var session = new MDPWorker (hostAddress, "test", Encoding.ASCII.GetBytes ("Worker"), 2)) { broker.Bind (hostAddress); // we need to pick up any message in order to avoid errors broker.ReceiveReady += (s, e) => { var msg = e.Socket.ReceiveMultipartMessage (); // we expect to receive a 5 Frame message // [WORKER ADR][EMPTY]["MDPW01"]["READY"]["test"] if (msg.FrameCount != 5) return; // it is a HEARTBEAT // make sure the frames are as expected Assert.That (msg[1], Is.EqualTo (NetMQFrame.Empty)); Assert.That (msg[2].ConvertToString (), Is.EqualTo ("MDPW01")); Assert.That (msg[3].BufferSize, Is.EqualTo (1)); Assert.That (msg[3].Buffer[0], Is.EqualTo ((byte) MDPCommand.Ready)); Assert.That (msg[4].ConvertToString (), Is.EqualTo ("test")); // tell worker to stop gracefully var reply = new NetMQMessage (); if (first) { reply.Push (new[] { (byte) 0xff }); first = false; } else reply.Push (new[] { (byte) MDPCommand.Kill }); // push MDP Version reply.Push ("MDPW01"); // push separator reply.Push (NetMQFrame.Empty); // push worker address reply.Push (msg[0]); // send reply which is a request for the worker e.Socket.SendMessage (reply); }; // set the event handler to receive the logging messages session.LogInfoReady += (s, e) => loggingMessages.Add (e.Info); poller.AddSocket (broker); Task.Factory.StartNew (poller.PollTillCancelled); session.HeartbeatDelay = TimeSpan.FromMilliseconds (250); session.ReconnectDelay = TimeSpan.FromMilliseconds (250); // initialise the worker - broker protocol session.Receive (null); Assert.That (loggingMessages.Count (m => m.Contains ("[WORKER ERROR] invalid command received")), Is.EqualTo (1)); Assert.That (loggingMessages.Count (m => m.Contains ("abandoning")), Is.EqualTo (1)); poller.CancelAndJoin (); poller.RemoveSocket (broker); } }
public void Send_WrongMDPVersionFromBrokerNoLogging_ShouldThrowApplicationException() { const string hostAddress = "tcp://localhost:5555"; // setup the counter socket for communication using (var context = NetMQContext.Create()) using (var broker = context.CreateRouterSocket()) using (var poller = new Poller()) using (var session = new MDPClient(hostAddress)) { broker.Bind(hostAddress); // we need to pick up any message in order to avoid errors broker.ReceiveReady += (s, e) => { // return empty reply var msg = e.Socket.ReceiveMessage(); // we expect to receive a 4 Frame message // [REQ ADR][EMPTY]["MDPC01"]["echo"]["REQUEST"] if (msg.FrameCount != 5) Assert.Fail("Message with wrong count of frames {0}", msg.FrameCount); // REQUEST socket will strip the his address + empty frame // ROUTER has to add the address prelude in order to identify the correct socket(!) // [REQ ADR][EMPTY]["MDPC00"]["echo"]["REQUEST"] var clientAddress = msg.Pop(); msg.Pop(); // forget empty frame msg.Pop(); // drop the MDP Version Frame msg.Push("MDPC00"); // insert wrong MDP version msg.Push(NetMQFrame.Empty); msg.Push(clientAddress); // reinsert the client's address e.Socket.SendMessage(msg); }; poller.AddSocket(broker); Task.Factory.StartNew(poller.PollTillCancelled); // well formed message var requestMessage = new NetMQMessage(new[] { new NetMQFrame("REQUEST") }); try { session.Send("echo", requestMessage); } catch (ApplicationException ex) { Assert.That(ex.Message, Is.StringContaining("MDP Version mismatch")); } poller.CancelAndJoin(); poller.RemoveSocket(broker); } }
public void Send_WrongServiceNameWithLogging_ShouldLogPermanentError() { const string hostAddress = "tcp://localhost:5555"; var loggingMessages = new List<string>(); // setup the counter socket for communication using (var context = NetMQContext.Create()) using (var broker = context.CreateRouterSocket()) using (var poller = new Poller()) using (var session = new MDPClient(hostAddress)) { broker.Bind(hostAddress); // we need to pick up any message in order to avoid errors broker.ReceiveReady += (s, e) => { // just swallow message -> wrong service name e.Socket.ReceiveMessage(); }; poller.AddSocket(broker); Task.Factory.StartNew(poller.PollTillCancelled); // set the event handler to receive the logging messages session.LogInfoReady += (s, e) => loggingMessages.Add(e.Info); // well formed message var requestMessage = new NetMQMessage(new[] { new NetMQFrame("REQUEST") }); // wrong service name session.Send("xyz", requestMessage); poller.CancelAndJoin(); poller.RemoveSocket(broker); Assert.That(loggingMessages.Count, Is.EqualTo(7)); Assert.That(loggingMessages[6], Is.EqualTo("[CLIENT ERROR] permanent error, abandoning!")); } }
/// <summary> /// ParanoidPirate.Queue [-v] /// /// Does load-balancing with heartbeating on worker tasks to detect /// crashed, blocked or slow running worker tasks . /// </summary> private static void Main(string[] args) { Console.Title = "NetMQ ParanoidPirate Queue"; // serves as flag for exiting the program var exit = false; // catch CTRL+C as exit command Console.CancelKeyPress += (s, e) => { e.Cancel = true; exit = true; }; var verbose = args.Length > 0 && args[0] == "-v"; using (var context = NetMQContext.Create()) using (var frontend = context.CreateRouterSocket()) using (var backend = context.CreateRouterSocket()) using (var poller = new Poller()) { frontend.Bind(Commons.QueueFrontend); backend.Bind(Commons.QueueBackend); var workers = new Workers(); // client sends to this socket frontend.ReceiveReady += (s, e) => { // only process incoming client requests // if we have workers available handle client requests as long as we have workers // storage capability of the socket otherwise and pick up later if (workers.Available) { // get all message frames! var request = frontend.ReceiveMultipartMessage(); if (verbose) Console.WriteLine("[QUEUE] received {0}", request); // get next available worker var worker = workers.Next(); // wrap message with worker's address var msg = Wrap(worker, request); if (verbose) Console.WriteLine("[QUEUE -> WORKER] sending {0}", msg); backend.SendMessage(msg); } }; // worker sends to this socket backend.ReceiveReady += (s, e) => { var msg = e.Socket.ReceiveMultipartMessage(); if (verbose) Console.WriteLine("[QUEUE <- WORKER] received {0}", msg); // use workers identity for load-balancing var workerIdentity = Unwrap(msg); var worker = new Worker(workerIdentity); workers.Ready(worker); // just convenience var readableWorkerId = workerIdentity.ConvertToString(); if (msg.FrameCount == 1) { var data = msg[0].ConvertToString(); // the message is either READY or HEARTBEAT or corrupted switch (data) { case Commons.PPPHeartbeat: Console.WriteLine("[QUEUE <- WORKER] Received a Heartbeat from {0}", readableWorkerId); break; case Commons.PPPReady: Console.WriteLine("[QUEUE <- WORKER] Received a READY form {0}", readableWorkerId); break; default: Console.WriteLine("[QUEUE <- WORKER] ERROR received an invalid message!"); break; } } else { if (verbose) Console.WriteLine("[QUEUE -> CLIENT] sending {0}", msg); frontend.SendMessage(msg); } }; var timer = new NetMQTimer(Commons.HeartbeatInterval); // every specified ms QUEUE shall send a heartbeat to all connected workers timer.Elapsed += (s, e) => { // send heartbeat to every worker foreach (var worker in workers) { var heartbeat = new NetMQMessage(); heartbeat.Push(new NetMQFrame(Commons.PPPHeartbeat)); heartbeat.Push(worker.Identity); Console.WriteLine("[QUEUE -> WORKER] sending heartbeat!"); backend.SendMessage(heartbeat); } // restart timer e.Timer.Enable = true; // remove all dead or expired workers workers.Purge(); }; if (verbose) Console.WriteLine("[QUEUE] Start listening!"); poller.AddSocket(frontend); poller.AddSocket(backend); poller.PollTillCancelledNonBlocking(); // hit CRTL+C to stop the while loop while (!exit) {} // Cleanup poller.RemoveTimer(timer); // stop the poler task poller.CancelAndJoin(); // remove the sockets - Dispose is called automatically poller.RemoveSocket(frontend); poller.RemoveSocket(backend); } }
public void AddSocketAfterRemovingTest() { using (NetMQContext contex = NetMQContext.Create()) { // we are using three responses to make sure we actually //move the correct socket and other sockets still work using (var router = contex.CreateRouterSocket()) using (var router2 = contex.CreateRouterSocket()) using (var router3 = contex.CreateRouterSocket()) { router.Bind("tcp://127.0.0.1:5002"); router2.Bind("tcp://127.0.0.1:5003"); router3.Bind("tcp://127.0.0.1:5004"); using (var dealer = contex.CreateDealerSocket()) using (var dealer2 = contex.CreateDealerSocket()) using (var dealer3 = contex.CreateDealerSocket()) using (Poller poller = new Poller()) { dealer.Connect("tcp://127.0.0.1:5002"); dealer2.Connect("tcp://127.0.0.1:5003"); dealer3.Connect("tcp://127.0.0.1:5004"); bool router1arrived = false; bool router2arrived = false; bool router3arrived = false; bool more; //The ReceiveReady event is raised by the Poller router.ReceiveReady += (s, a) => { router1arrived = true; router.Receive(out more); router.Receive(out more); poller.RemoveSocket(router); }; poller.AddSocket(router); //The ReceiveReady event is raised by the Poller router3.ReceiveReady += (s, a) => { router3.Receive(out more); router3.Receive(out more); router3arrived = true; }; //The ReceiveReady event is raised by the Poller router2.ReceiveReady += (s, a) => { router2arrived = true; router2.Receive(out more); router2.Receive(out more); poller.AddSocket(router3); }; poller.AddSocket(router2); Task task = Task.Factory.StartNew(poller.Start); dealer.Send("1"); Thread.Sleep(300); dealer2.Send("2"); Thread.Sleep(300); dealer3.Send("3"); Thread.Sleep(300); poller.Stop(true); task.Wait(); Assert.IsTrue(router1arrived); Assert.IsTrue(router2arrived); Assert.IsTrue(router3arrived); } } } }
public void ReceiveImplicitConnect_ValidScenario_ShouldReturnRequest() { const string hostAddress = "tcp://localhost:5557"; var loggingMessages = new List<string> (); // setup the counter socket for communication using (var context = NetMQContext.Create ()) using (var broker = context.CreateRouterSocket ()) using (var poller = new Poller ()) using (var session = new MDPWorker (hostAddress, "test", new[] { (byte) '1' })) { broker.Bind (hostAddress); // we need to pick up any message in order to avoid errors broker.ReceiveReady += (s, e) => { var msg = e.Socket.ReceiveMultipartMessage (); // we expect to receive a 5 Frame message // [WORKER ADR][EMPTY]["MDPW01"]["READY"]["test"] if (msg.FrameCount != 5) Assert.Fail ("Message with wrong count of frames {0}", msg.FrameCount); // make sure the frames are as expected Assert.That (msg[1], Is.EqualTo (NetMQFrame.Empty)); Assert.That (msg[2].ConvertToString (), Is.EqualTo ("MDPW01")); Assert.That (msg[3].BufferSize, Is.EqualTo (1)); Assert.That (msg[3].Buffer[0], Is.EqualTo ((byte) MDPCommand.Ready)); Assert.That (msg[4].ConvertToString (), Is.EqualTo ("test")); // tell worker to stop gracefully var reply = new NetMQMessage (); reply.Push (new[] { (byte) MDPCommand.Kill }); // push MDP Version reply.Push (msg[2]); // push separator reply.Push (NetMQFrame.Empty); // push worker address reply.Push (msg[0]); // send reply which is a request for the worker e.Socket.SendMessage (reply); }; poller.AddSocket (broker); Task.Factory.StartNew (poller.PollTillCancelled); // set the event handler to receive the logging messages session.LogInfoReady += (s, e) => loggingMessages.Add (e.Info); // initialise the worker - broker protocol session.Receive (null); poller.CancelAndJoin (); poller.RemoveSocket (broker); Assert.That (loggingMessages.Count, Is.EqualTo (5)); Assert.That (loggingMessages[0], Is.EqualTo ("[WORKER] connected to broker at tcp://localhost:5557")); Assert.That (loggingMessages[1].Contains ("[WORKER] sending"), Is.True); Assert.That (loggingMessages[2].Contains ("[WORKER] received")); Assert.That (loggingMessages[4].Contains ("abandoning")); } }
public void CancelSocketTest() { using (NetMQContext contex = NetMQContext.Create()) { // we are using three responses to make sure we actually //move the correct socket and other sockets still work using (var router = contex.CreateRouterSocket()) using (var router2 = contex.CreateRouterSocket()) using (var router3 = contex.CreateRouterSocket()) { router.Bind("tcp://127.0.0.1:5002"); router2.Bind("tcp://127.0.0.1:5003"); router3.Bind("tcp://127.0.0.1:5004"); using (var dealer = contex.CreateDealerSocket()) using (var dealer2 = contex.CreateDealerSocket()) using (var dealer3 = contex.CreateDealerSocket()) using (Poller poller = new Poller()) { dealer.Connect("tcp://127.0.0.1:5002"); dealer2.Connect("tcp://127.0.0.1:5003"); dealer3.Connect("tcp://127.0.0.1:5004"); bool first = true; //The ReceiveReady event is raised by the Poller router2.ReceiveReady += (s, a) => { bool more; // identity byte[] identity = a.Socket.Receive(out more); // message a.Socket.Receive(out more); a.Socket.SendMore(identity); a.Socket.Send("2"); }; poller.AddSocket(router2); //The ReceiveReady event is raised by the Poller router.ReceiveReady += (s, a) => { if (!first) { Assert.Fail("This should happen because we cancelled the socket"); } first = false; bool more; // identity a.Socket.Receive(out more); string m = a.Socket.ReceiveString(out more); Assert.False(more); Assert.AreEqual("Hello", m); // cancelling the socket poller.RemoveSocket(a.Socket); }; poller.AddSocket(router); //The ReceiveReady event is raised by the Poller router3.ReceiveReady += (s, a) => { bool more; // identity byte[] identity = a.Socket.Receive(out more); // message a.Socket.Receive(out more); a.Socket.SendMore(identity).Send("3"); }; poller.AddSocket(router3); Task pollerTask = Task.Factory.StartNew(poller.Start); dealer.Send("Hello"); // sending this should not arrive on the poller, //therefore response for this will never arrive dealer.Send("Hello2"); Thread.Sleep(100); // sending this should not arrive on the poller, //therefore response for this will never arrive dealer.Send("Hello3"); Thread.Sleep(500); bool more2; // making sure the socket defined before the one cancelled still works dealer2.Send("1"); string msg = dealer2.ReceiveString(out more2); Assert.AreEqual("2", msg); // making sure the socket defined after the one cancelled still works dealer3.Send("1"); msg = dealer3.ReceiveString(out more2); Assert.AreEqual("3", msg); // we have to give this some time if we want to make sure //it's really not happening and it not only because of time Thread.Sleep(300); poller.Stop(); Thread.Sleep(100); Assert.IsTrue(pollerTask.IsCompleted); } } } }
public void Send_EmptyReplyFromBrokerWithLogging_ShouldThrowApplicationException() { const string hostAddress = "tcp://localhost:5555"; var loggingMessages = new List<string>(); // setup the counter socket for communication using (var context = NetMQContext.Create()) using (var broker = context.CreateRouterSocket()) using (var poller = new Poller()) using (var session = new MDPClient(hostAddress)) { broker.Bind(hostAddress); // we need to pick up any message in order to avoid errors broker.ReceiveReady += (s, e) => { // return empty reply var msg = e.Socket.ReceiveMessage(); // we expect to receive a 4 Frame message // [REQ ADR][EMPTY]["MDPC01"]["echo"]["REQUEST"] if (msg.FrameCount != 5) Assert.Fail("Message with wrong count of frames {0}", msg.FrameCount); // REQUEST socket will strip the his address + empty frame // ROUTER has to add the address prelude in order to identify the correct socket(!) // [REQ ADR][EMPTY]["MDPC01"]["echo"]["REQUEST"] e.Socket.SendMessage(msg); }; poller.AddSocket(broker); Task.Factory.StartNew(poller.PollTillCancelled); // set the event handler to receive the logging messages session.LogInfoReady += (s, e) => loggingMessages.Add(e.Info); // well formed message var requestMessage = new NetMQMessage(new[] { new NetMQFrame("REQUEST") }); // correct call session.Send("echo", requestMessage); poller.CancelAndJoin(); poller.RemoveSocket(broker); Assert.That(loggingMessages.Count, Is.EqualTo(3)); Assert.That(loggingMessages[0], Is.EqualTo("[CLIENT] connecting to broker at tcp://localhost:5555")); Assert.That(loggingMessages[1].Contains("[CLIENT INFO] sending"), Is.True); Assert.That(loggingMessages[2].Contains("[CLIENT INFO] received"), Is.True); } }
public void Receive_RequestWithWrongFirstFrame_ShouldThrowApplicationException() { const string hostAddress = "tcp://localhost:5555"; // setup the counter socket for communication using (var context = NetMQContext.Create ()) using (var broker = context.CreateRouterSocket ()) using (var poller = new Poller ()) using (var session = new MDPWorker (hostAddress, "test")) { broker.Bind (hostAddress); // we need to pick up any message in order to avoid errors broker.ReceiveReady += (s, e) => { var msg = e.Socket.ReceiveMultipartMessage (); // we expect to receive a 5 Frame message // [WORKER ADR][EMPTY]["MDPW01"]["READY"]["test"] if (msg.FrameCount != 5) Assert.Fail ("Message with wrong count of frames {0}", msg.FrameCount); // make sure the frames are as expected Assert.That (msg[1], Is.EqualTo (NetMQFrame.Empty)); Assert.That (msg[2].ConvertToString (), Is.EqualTo ("MDPW01")); Assert.That (msg[3].BufferSize, Is.EqualTo (1)); Assert.That (msg[3].Buffer[0], Is.EqualTo ((byte) MDPCommand.Ready)); Assert.That (msg[4].ConvertToString (), Is.EqualTo ("test")); // tell worker to stop gracefully var reply = new NetMQMessage (); reply.Push (new[] { (byte) MDPCommand.Kill }); // push MDP Version reply.Push ("MDPW01"); // push separator reply.Push ("Should be empty"); // push worker address reply.Push (msg[0]); // send reply which is a request for the worker e.Socket.SendMessage (reply); }; poller.AddSocket (broker); Task.Factory.StartNew (poller.PollTillCancelled); try { session.Receive (null); } catch (ApplicationException ex) { Assert.That (ex.Message, Is.EqualTo ("First frame must be an empty frame!")); } poller.CancelAndJoin (); poller.RemoveSocket (broker); } }