/// <summary> /// Start monitor the socket, the method doesn't start a new thread and will block until the monitor poll is stopped /// </summary> /// <exception cref="InvalidOperationException">The Monitor must not have already started nor attached to a poller.</exception> public void Start() { // in case the sockets is created in another thread Thread.MemoryBarrier(); if (IsRunning) { throw new InvalidOperationException("Monitor already started"); } if (m_attachedPoller != null) { throw new InvalidOperationException("Monitor attached to a poller"); } try { InternalStart(); while (m_cancel == 0) { m_monitoringSocket.Poll(Timeout); } } finally { InternalClose(); } }
/// <summary> /// send a request to a broker for a specific service and receive the reply /// /// if the reply is not available within a specified time /// the client deems the connection as lost and reconnects /// for a specified number of times. if no reply is available /// throughout this procedure the client abandons /// the reply is checked for validity and returns the reply /// according to the verbose flag it reports about its activities /// </summary> /// <param name="serviceName">the name of the service requested</param> /// <param name="request">the request message to process by service</param> /// <returns>the reply from service</returns> /// <exception cref="ApplicationException">malformed message received</exception> /// <exception cref="ApplicationException">malformed header received</exception> /// <exception cref="ApplicationException">reply received from wrong service</exception> public NetMQMessage Send(string serviceName, NetMQMessage request) { if (string.IsNullOrWhiteSpace(serviceName)) { throw new ApplicationException("serviceName must not be empty or null."); } if (ReferenceEquals(request, null)) { throw new ApplicationException("the request must not be null"); } // memorize it for the event handler m_serviceName = serviceName; // if for any reason the socket is NOT connected -> connect it! if (!m_connected) { Connect(); } var message = new NetMQMessage(request); // prefix the request according to MDP specs // Frame 1: "MDPCxy" (six bytes MDP/Client x.y) // Frame 2: service name as printable string // Frame 3: request message.Push(serviceName); message.Push(m_mdpClient); Log(string.Format("[CLIENT INFO] sending {0} to service {1}", message, serviceName)); var retiesLeft = Retries; while (retiesLeft > 0) { // beware of an exception if broker has not picked up the message at all // because one can not send multiple times! it is strict REQ -> REP -> REQ ... m_client.SendMultipartMessage(message); // Poll -> see ReceiveReady for event handling if (m_client.Poll(Timeout)) { // set by event handler return(m_reply); } // if it failed assume communication dead and re-connect if (--retiesLeft > 0) { Log("[CLIENT WARNING] no reply, reconnecting ..."); Connect(); } } Log("[CLIENT ERROR] permanent error, abandoning!"); m_client.Dispose(); return(null); }
// on message pushed to me. private void OnPull() { while (!this.token_pp.IsCancellationRequested) { puller.Poll(TimeSpan.FromMilliseconds(100)); //try //{ // while (hasMore) // { // sb.Append(Encoding.UTF8.GetString(this.puller.Receive(SendReceiveOptions.DontWait, out hasMore))); // } // string msg = sb.ToString(); // sb.Clear(); // if (msg.Length > 0) // { // pullMsgHandler(msg); // } //} //catch (Exception ce) //{ // Console.WriteLine("OnPull Error: {0}", ce.Message); // log.Error("Pulling Message error: ", ce); //} } log.Debug("Puller Closed"); puller.Close(); }
/// <summary> /// /// </summary> public void Start() { m_server = new RouterSocket(); m_server.Bind("tcp://*:" + ListnenPort); m_server.ReceiveReady += Server_ReceiveReady; m_server.SendReady += Server_SendReady; m_started = true; new Thread(() => { long nextSend = 0, nextHeartBeat = 0; while (m_started) { var tmp = TimeSpan.FromMilliseconds(1); m_server.Poll(tmp); if (nextSend <= 0) { SendQueue(); nextSend = SendInterval; } if (nextHeartBeat <= 0) { Heartbeat(); nextHeartBeat = PingInterval; } nextSend -= 10; nextHeartBeat -= 10; Thread.Sleep(10); } }) { IsBackground = true }.Start(); }
/// <summary> /// Start monitor the socket, the method doesn't start a new thread and will block until the monitor poll is stopped /// </summary> /// <exception cref="InvalidOperationException">The Monitor must not have already started nor attached to a poller.</exception> public void Start() { if (IsRunning) { throw new InvalidOperationException("Monitor already started"); } if (m_attachedPoller != null) { throw new InvalidOperationException("Monitor attached to a poller"); } try { InternalStart(); while (m_cancel == 0) { m_monitoringSocket.Poll(Timeout); } } finally { InternalClose(); } }
/// <summary> /// Listens the specified on message received. /// </summary> /// <param name="onMessageReceived">The on message received.</param> /// <param name="token">The tokenSource.</param> internal void Listen(Action <Message> onMessageReceived, CancellationTokenSource token) { socket.ReceiveReady += (sender, args) => { var inbound = socket.ReceiveString(); var message = Message.FromJson(inbound); onMessageReceived(message); }; while (!token.IsCancellationRequested) { socket.Poll(); } }
public string Request(string service, string msg, int timeoutmsec) { string resp = string.Empty; LinkAddress address = config.ReqRep.FindLinkAddress(service); if (address == null) { return(resp); } bool pollResult = false; string requestId = Guid.NewGuid().ToString(); using (NetMQContext context = NetMQContext.Create()) { NetMQSocket client = context.CreateRequestSocket(); client.Options.Linger = TimeSpan.Zero; client.Options.Identity = Encoding.UTF8.GetBytes(requestId); client.Connect(address.Address); try { byte[] data = Encoding.UTF8.GetBytes(msg); client.Send(data); } catch (Exception) { client.Disconnect(address.Address); client.Dispose(); return(resp); } client.ReceiveReady += ClientOnReceiveReady; pollResult = client.Poll(TimeSpan.FromMilliseconds(timeoutmsec)); client.ReceiveReady -= ClientOnReceiveReady; client.Disconnect(address.Address); client.Dispose(); } if (pollResult) { if (responseMsgs.ContainsKey(requestId)) { responseMsgs.TryRemove(requestId, out resp); } } return(resp); }
private static bool TryRequest(NetMQContext context, string endpoint, string requestString) { Console.WriteLine("Trying echo service at {0}", endpoint); NetMQSocket client = context.CreateRequestSocket(); client.Options.Linger = TimeSpan.Zero; client.Connect(endpoint); client.Send(requestString); client.ReceiveReady += ClientOnReceiveReady; bool pollResult = client.Poll(TimeSpan.FromMilliseconds(REQUEST_TIMEOUT)); client.ReceiveReady -= ClientOnReceiveReady; client.Disconnect(endpoint); client.Dispose(); return(pollResult); }
static void Main(string[] args) { using (var context = NetMQContext.Create()) { worker = context.CreateRequestSocket(); var randomizer = new Random(DateTime.Now.Millisecond); Guid guid = Guid.NewGuid(); worker.Options.Identity = Encoding.Unicode.GetBytes(guid.ToString()); worker.ReceiveReady += WorkerOnReceiveReady; worker.Connect(SERVER_ENDPOINT); Console.WriteLine("W: {0} worker ready", guid); worker.Send(Encoding.Unicode.GetBytes(LRU_READY)); var cycles = 0; while (true) { cycles += 1; if (cycles > 3 && randomizer.Next(0, 5) == 0) { Console.WriteLine("W: {0} simulating a crash", guid); System.Threading.Thread.Sleep(5000); //break; } else if (cycles > 3 && randomizer.Next(0, 5) == 0) { Console.WriteLine("W: {0} simulating CPU overload", guid); System.Threading.Thread.Sleep(3000); } Console.WriteLine("W: {0} normal reply", guid); worker.Poll(TimeSpan.FromMilliseconds(1000)); } } }
/// <summary> /// initially sends a READY message to the broker upon connection /// and waits for a request to come /// </summary> /// <param name="reply">the reply to send</param> /// <returns>the request to process</returns> /// <remarks> /// if it is the initial call to Receive - reply must be <c>null</c> in order to /// send READY and subsequently wait for a request. /// reply == <c>null</c> will bypass the sending of a message! /// </remarks> public NetMQMessage Receive(NetMQMessage reply) { // set the number of left retries to connect m_retriesLeft = m_connectionRetries; if (!m_connected) { Connect(); } // since Connect send the READY we are waiting after a Connect for a // REQ and must skip the REPLY step // if however the Connect has not been called than we have received // and processed a REQ and must send a REP and at one must be pending if (!ReferenceEquals(reply, null) && m_expectReply != 0) { if (ReferenceEquals(m_returnIdentity, null) || m_returnIdentity.BufferSize == 0) { throw new ApplicationException("A malformed reply has been provided"); } var message = Wrap(reply, m_returnIdentity); // [client id][e][reply] Send(MDPCommand.Reply, null, message); } m_expectReply = 1; // now wait for the next request while (!m_exit) { // see ReceiveReady event handler -> ProcessReceiveReady if (m_worker.Poll(HeartbeatDelay)) { // a request has been received, so connection is established - reset the connection retries m_retriesLeft = m_connectionRetries; // ProcessReceiveReady will set m_request only if a request arrived if (!ReferenceEquals(m_request, null)) { return(m_request); } } else { // if m_liveliness times no message has been received -> try to reconnect if (--m_liveliness == 0) { // if we tried it _HEARTBEAT_LIVELINESS * m_connectionRetries times without // success therefor we deem the broker dead or the communication broken // and abandon the worker if (--m_retriesLeft < 0) { Log("[WORKER] abandoning worker due to errors!"); break; } Log("[WORKER INFO] disconnected from broker - retrying ..."); // wait before reconnecting Thread.Sleep(HeartbeatDelay); // reconnect Connect(); } Send(MDPCommand.Heartbeat, null, null); // set new point in time for sending the next heartbeat } } if (m_exit) { Log("[WORKER] abandoning worker due to request!"); } m_worker.Dispose(); return(null); }
private void ReceiveEvents(String subscriptionUri, String topic, CancellationToken cancellationToken) { using (NetMQContext context = NetMQContext.Create()) { using (NetMQSocket subscriberSocket = context.CreateSubscriberSocket()) { subscriberSocket.IgnoreErrors = true; subscriberSocket.Connect(subscriptionUri); subscriberSocket.Subscribe(topic); Logger.Info("ZeroMQCache: Connected to subscriptionUri \"{0}\".", subscriptionUri); // Eventhandler delegate to handle receiving messages subscriberSocket.ReceiveReady += (sender, args) => { try { if (args.ReceiveReady) { // Recieve and relay NetMQMessage netMQmessage = args.Socket.ReceiveMessage(); // Recieve the message ZeroMQMessage message = new ZeroMQMessage() { Topic = netMQmessage.Pop().ConvertToString(), Client = netMQmessage.Pop().ConvertToString(), Content = netMQmessage.Pop().ConvertToString() }; Logger.Debug("ZeroMQCache: Received -> {0}", message.ToString()); XmlCacheEvent cacheEvent = XmlCacheEvent.FromXml(message.Content); if (cacheEvent != null) { OnCacheEvent(cacheEvent.CacheRegion, cacheEvent.Key, cacheEvent.EventType); } } } catch (OperationCanceledException) { // We have been asked to cancel operation return; } catch (Exception ex) { Logger.Error("ZeroMQCache: Error receiving message.", ex); } }; while (!cancellationToken.IsCancellationRequested) { try { subscriberSocket.Poll(TimeSpan.FromSeconds(1)); } catch (OperationCanceledException) { // We have been asked to cancel operation break; } catch (Exception ex) { Logger.Error("ZeroMQCache: Error polling for messages.", ex); } } // Close socket subscriberSocket.Close(); } context.Terminate(); } }
private void ReceiveEvents(String submissionUri, String topic, CancellationToken cancellationToken) { using (NetMQContext context = NetMQContext.Create()) { using (NetMQSocket pullSocket = context.CreatePullSocket()) { pullSocket.IgnoreErrors = true; pullSocket.Bind(submissionUri); Logger.Info("ZeroMQBroker: Bound to submissionUri \"{0}\".", submissionUri); // Eventhandler delegate to handle receiving messages pullSocket.ReceiveReady += (sender, args) => { try { if (args.ReceiveReady) { // Recieve and relay NetMQMessage netMQmessage = args.Socket.ReceiveMessage(); // Recieve the message ZeroMQMessage message = new ZeroMQMessage() { Topic = netMQmessage.Pop().ConvertToString(), Client = netMQmessage.Pop().ConvertToString(), Content = netMQmessage.Pop().ConvertToString() }; Logger.Debug("ZeroMQBroker: Received -> {0}", message.ToString()); mQueue.Add(message); // ZeroMQBroker relays multiple topics, verify if the message was meant for the current client if (String.Equals(topic, message.Topic, StringComparison.OrdinalIgnoreCase)) { XmlCacheEvent cacheEvent = XmlCacheEvent.FromXml(message.Content); if (cacheEvent != null) { OnCacheEvent(cacheEvent.CacheRegion, cacheEvent.Key, cacheEvent.EventType); } } } } catch (OperationCanceledException) { // We have been asked to cancel operation return; } catch (Exception ex) { Logger.Error("ZeroMQBroker: Error receiving message.", ex); } }; while (!cancellationToken.IsCancellationRequested) { try { pullSocket.Poll(TimeSpan.FromSeconds(1)); } catch (OperationCanceledException) { // We have been asked to cancel operation break; } catch (Exception ex) { Logger.Error("ZeroMQBroker: Error polling for messages.", ex); } } // Close socket pullSocket.Close(); } context.Terminate(); } }