Example #1
0
            //  .split broker client_msg method
            //  Process a request coming from a client. We implement MMI requests
            //  directly here (at present, we implement only the mmi.service request):
            public void ClientMsg(ZFrame sender, ZMessage msg)
            {
                // service & body
                if (msg.Count < 2)
                {
                    throw new InvalidOperationException();
                }

                using (ZFrame serviceFrame = msg.Pop())
                {
                    Service service = RequireService(serviceFrame);

                    // Set reply return identity to client sender
                    msg.Wrap(sender.Duplicate());

                    //if we got a MMI Service request, process that internally
                    if (serviceFrame.Length >= 4 &&
                        serviceFrame.ToString().StartsWith("mmi."))
                    {
                        string returnCode;
                        if (serviceFrame.ToString().Equals("mmi.service"))
                        {
                            string name = msg.Last().ToString();
                            returnCode = Services.ContainsKey(name) &&
                                         Services[name].Workers > 0
                                            ? "200"
                                            : "404";
                        }
                        else
                        {
                            returnCode = "501";
                        }

                        var client = msg.Unwrap();

                        msg.Clear();
                        msg.Add(new ZFrame(returnCode));
                        msg.Prepend(serviceFrame);
                        msg.Prepend(new ZFrame(MdpCommon.MDPC_CLIENT));

                        msg.Wrap(client);
                        Socket.Send(msg);
                    }
                    else
                    {
                        // Else dispatch the message to the requested Service
                        service.Dispatch(msg);
                    }
                }
            }
Example #2
0
            //  .split service methods
            //  Here is the implementation of the methods that work on a service:

            //  Lazy constructor that locates a service by name or creates a new
            //  service if there is no service already with that name.
            public Service RequireService(ZFrame serviceFrame)
            {
                if (serviceFrame == null)
                {
                    throw new InvalidOperationException();
                }

                string name = serviceFrame.ToString();

                Service service;

                if (Services.ContainsKey(name))
                {
                    service = Services[name];
                }
                else
                {
                    service        = new Service(this, name);
                    Services[name] = service;

                    //zhash_freefn(self->workers, id_string, s_worker_destroy);
                    if (Verbose)
                    {
                        "I: added service: '{0}'".DumpString(name);
                    }
                }

                return(service);
            }
Example #3
0
            //  .skip
            //  The recv method waits for a reply message and returns that to the
            //  caller.
            //  ---------------------------------------------------------------------
            //  Returns the reply message or NULL if there was no reply. Does not
            //  attempt to recover from a broker failure, this is not possible
            //  without storing all unanswered requests and resending them all...
            public ZMessage Recv(CancellationTokenSource cancellor)
            {
                //  Poll socket for a reply, with timeout
                var      p = ZPollItem.CreateReceiver();
                ZMessage msg;
                ZError   error;

                //  .split body of send
                //  On any blocking call, {{libzmq}} will return -1 if there was
                //  an error; we could in theory check for different error codes,
                //  but in practice it's OK to assume it was {{EINTR}} (Ctrl-C):

                // Poll the client Message
                if (Client.PollIn(p, out msg, out error, Timeout))
                {
                    //  If we got a reply, process it
                    if (Verbose)
                    {
                        msg.DumpZmsg("I: received reply");
                    }

                    //  Don't try to handle errors, just assert noisily
                    if (msg.Count < 4)
                    {
                        throw new InvalidOperationException();
                    }

                    using (ZFrame empty = msg.Pop())
                        if (!empty.ToString().Equals(string.Empty))
                        {
                            throw new InvalidOperationException();
                        }

                    using (ZFrame header = msg.Pop())
                        if (!header.ToString().Equals(MdpCommon.MDPC_CLIENT))
                        {
                            throw new InvalidOperationException();
                        }

                    using (ZFrame replyService = msg.Pop())
                    {}

                    return(msg);
                }
                else if (Equals(error, ZError.ETERM))
                {
                    "W: interrupt received, killing client...\n".DumpString();
                    cancellor.Cancel();
                }
                else
                {
                    if (Verbose)
                    {
                        "W: permanent error, abandoning Error: {0}".DumpString(error);
                    }
                }

                return(null);
            }
Example #4
0
        static void Main(string[] args)
        {
            using (ZSocket request = new ZSocket(ZSocketType.REQ))
            {
                request.Connect("tcp://localhost:50000");
                Console.WriteLine($"Connect to server: tcp://localhost:50000");
                for (int i = 0; i < 10; i++)
                {
                    string postStr = $"Lynn {i}";
                    request.Send(new ZFrame(postStr));
                    Console.WriteLine($"Post {postStr} to server....");

                    using (ZFrame reply = request.ReceiveFrame())
                    {
                        Console.WriteLine($"Receive reply: {reply.ToString()}");
                    }
                }
            }
            Console.Read();
        }
Example #5
0
        static void Main(string[] args)
        {
            string url = "tcp://*:50000";

            using (ZSocket receiver = new ZSocket(ZSocketType.REP))
            {
                receiver.Bind(url);
                Console.WriteLine($"Server is binding to {url}");

                while (true)
                {
                    using (ZFrame message = receiver.ReceiveFrame())
                    {
                        Console.WriteLine($"Receive message {message.ToString()}");
                        var reply = new ZFrame("Lynn");
                        Console.WriteLine($"Send reply: {reply.ToString()}");
                        receiver.Send(reply);
                    };
                }
            };
        }
Example #6
0
            //  .split service methods
            //  Here is the implementation of the methods that work on a service:
            //  Lazy constructor that locates a service by name or creates a new
            //  service if there is no service already with that name.
            public Service RequireService(ZFrame serviceFrame)
            {
                if(serviceFrame == null)
                    throw new InvalidOperationException();

                string name = serviceFrame.ToString();

                Service service;
                if (Services.ContainsKey(name))
                {
                    service = Services[name];
                }
                else
                {
                    service = new Service(this, name);
                    Services[name] = service;

                    //zhash_freefn(self->workers, id_string, s_worker_destroy);
                    if (Verbose)
                        "I: added service: '{0}'".DumpString(name);
                }

                return service;
            }
Example #7
0
            //  .split send request and wait for reply
            //  Here is the {{send}} method. It sends a request to the broker and gets
            //  a reply even if it has to retry several times. It takes ownership of
            //  the request message, and destroys it when sent. It returns the reply
            //  message, or NULL if there was no reply after multiple attempts:
            public ZMessage Send(string service, ZMessage request, CancellationTokenSource cancellor)
            {
                if (request == null)
                {
                    throw new InvalidOperationException();
                }

                //  Prefix request with protocol frames
                //  Frame 1: "MDPCxy" (six bytes, MDP/Client x.y)
                //  Frame 2: Service name (printable string)
                request.Prepend(new ZFrame(service));
                request.Prepend(new ZFrame(MdpCommon.MDPC_CLIENT));
                if (Verbose)
                {
                    request.DumpZmsg("I: send request to '{0}' service:", service);
                }

                int retriesLeft = Retries;

                while (retriesLeft > 0 && !cancellor.IsCancellationRequested)
                {
                    if (cancellor.IsCancellationRequested ||
                        (Console.KeyAvailable && Console.ReadKey(true).Key == ConsoleKey.Escape))
                    {
                        _context.Shutdown();
                    }

                    // Copy the Request and send on Client
                    ZMessage msgreq = request.Duplicate();

                    ZError error;
                    if (!Client.Send(msgreq, out error))
                    {
                        if (Equals(error, ZError.ETERM))
                        {
                            cancellor.Cancel();
                            break; // Interrupted
                        }
                    }

                    var      p = ZPollItem.CreateReceiver();
                    ZMessage msg;
                    //  .split body of send
                    //  On any blocking call, {{libzmq}} will return -1 if there was
                    //  an error; we could in theory check for different error codes,
                    //  but in practice it's OK to assume it was {{EINTR}} (Ctrl-C):

                    // Poll the client Message
                    if (Client.PollIn(p, out msg, out error, Timeout))
                    {
                        //  If we got a reply, process it
                        if (Verbose)
                        {
                            msg.DumpZmsg("I: received reply");
                        }

                        if (msg.Count < 3)
                        {
                            throw new InvalidOperationException();
                        }

                        using (ZFrame header = msg.Pop())
                            if (!header.ToString().Equals(MdpCommon.MDPC_CLIENT))
                            {
                                throw new InvalidOperationException();
                            }

                        using (ZFrame replyService = msg.Pop())
                            if (!replyService.ToString().Equals(service))
                            {
                                throw new InvalidOperationException();
                            }

                        request.Dispose();
                        return(msg);
                    }
                    else if (Equals(error, ZError.ETERM))
                    {
                        cancellor.Cancel();
                        break; // Interrupted
                    }
                    else if (Equals(error, ZError.EAGAIN))
                    {
                        if (--retriesLeft > 0)
                        {
                            if (Verbose)
                            {
                                "W: no reply, reconnecting...".DumpString();
                            }

                            ConnectToBroker();
                        }
                        else
                        {
                            if (Verbose)
                            {
                                "W: permanent error, abandoning".DumpString();
                            }
                            break; // Give up
                        }
                    }
                }
                if (cancellor.IsCancellationRequested)
                {
                    "W: interrupt received, killing client...\n".DumpString();
                }
                request.Dispose();
                return(null);
            }
Example #8
0
        //  .split recv method
        //  This is the {{recv}} method; it's a little misnamed because it first sends
        //  any reply and then waits for a new request. If you have a better name
        //  for this, let me know.

        //  Send reply, if any, to broker and wait for next request.
        public ZMessage Recv(ZMessage reply, CancellationTokenSource cancellor)
        {
            if (reply == null &&
                _expectReply)
            {
                throw new InvalidOperationException();
            }

            if (reply != null)
            {
                if (_replyTo == null)
                {
                    throw new InvalidOperationException();
                }
                reply.Wrap(_replyTo);
                SendToBroker(MdpCommon.MdpwCmd.REPLY.ToHexString(), string.Empty, reply);
            }
            _expectReply = true;

            while (true)
            {
                if (cancellor.IsCancellationRequested ||
                    (Console.KeyAvailable && Console.ReadKey(true).Key == ConsoleKey.Escape))
                {
                    _context.Shutdown();
                }

                var      p = ZPollItem.CreateReceiver();
                ZMessage msg;
                ZError   error;
                if (Worker.PollIn(p, out msg, out error, Heartbeat))
                {
                    using (msg)
                    {
                        // If we got a reply
                        if (Verbose)
                        {
                            msg.DumpZmsg("I: received message from broker:");
                        }

                        Liveness = MdpCommon.HEARTBEAT_LIVENESS;

                        // Don't try to handle errors, just assert noisily
                        if (msg.Count < 3)
                        {
                            throw new InvalidOperationException();
                        }

                        using (ZFrame empty = msg.Pop())
                        {
                            if (!empty.ToString().Equals(""))
                            {
                                throw new InvalidOperationException();
                            }
                        }

                        using (ZFrame header = msg.Pop())
                        {
                            if (!header.ToString().Equals(MdpCommon.MDPW_WORKER))
                            {
                                throw new InvalidOperationException();
                            }
                        }
                        //header.ReadString().Equals(MDPW_WORKER);
                        using (ZFrame command = msg.Pop())
                        {
                            if (command.StrHexEq(MdpCommon.MdpwCmd.REQUEST))
                            {
                                //  We should pop and save as many addresses as there are
                                //  up to a null part, but for now, just save one...
                                _replyTo = msg.Unwrap();

                                //  .split process message
                                //  Here is where we actually have a message to process; we
                                //  return it to the caller application:
                                return(msg.Duplicate());
                            }
                            else if (command.StrHexEq(MdpCommon.MdpwCmd.HEARTBEAT))
                            {
                                // Do nothing for heartbeats
                            }
                            else if (command.StrHexEq(MdpCommon.MdpwCmd.DISCONNECT))
                            {
                                ConnectToBroker();
                            }
                            else
                            {
                                "E: invalid input message: '{0}'".DumpString(command.ToString());
                            }
                        }
                    }
                }
                else if (Equals(error, ZError.ETERM))
                {
                    cancellor.Cancel();
                    break; // Interrupted
                }
                else if (Equals(error, ZError.EAGAIN) &&
                         --Liveness == 0)
                {
                    if (Verbose)
                    {
                        "W: disconnected from broker - retrying...".DumpString();
                    }
                    Thread.Sleep(Reconnect);
                    ConnectToBroker();
                }

                // Send HEARTBEAT if it's time
                if (DateTime.UtcNow > HeartbeatAt)
                {
                    SendToBroker(MdpCommon.MdpwCmd.HEARTBEAT.ToHexString(), null, null);
                    HeartbeatAt = DateTime.UtcNow + Heartbeat;
                }
            }
            if (cancellor.IsCancellationRequested)
            {
                "W: interrupt received, killing worker...\n".DumpString();
            }

            return(null);
        }
Example #9
0
 public static bool StrHexEq(this ZFrame zfrm, MdpCommon.MdpwCmd cmd)
 {
     return(zfrm.ToString().ToMdCmd().Equals(cmd));
 }
Example #10
0
        //  .split main task
        //  Finally, here is the main task. We create a new broker instance and
        //  then process messages on the broker Socket:
        public static void MDBroker(string[] args)
        {
            CancellationTokenSource cancellor = new CancellationTokenSource();

            Console.CancelKeyPress += (s, ea) =>
            {
                ea.Cancel = true;
                cancellor.Cancel();
            };

            using (Broker broker = new Broker(Verbose))
            {
                broker.Bind("tcp://*:5555");
                // Get and process messages forever or until interrupted
                while (true)
                {
                    if (cancellor.IsCancellationRequested ||
                        (Console.KeyAvailable && Console.ReadKey(true).Key == ConsoleKey.Escape))
                    {
                        broker.ShutdownContext();
                    }

                    var      p = ZPollItem.CreateReceiver();
                    ZMessage msg;
                    ZError   error;
                    if (broker.Socket.PollIn(p, out msg, out error, MdpCommon.HEARTBEAT_INTERVAL))
                    {
                        if (Verbose)
                        {
                            msg.DumpZmsg("I: received message:");
                        }

                        using (ZFrame sender = msg.Pop())
                            using (ZFrame empty = msg.Pop())
                                using (ZFrame header = msg.Pop())
                                {
                                    if (header.ToString().Equals(MdpCommon.MDPC_CLIENT))
                                    {
                                        broker.ClientMsg(sender, msg);
                                    }
                                    else if (header.ToString().Equals(MdpCommon.MDPW_WORKER))
                                    {
                                        broker.WorkerMsg(sender, msg);
                                    }
                                    else
                                    {
                                        msg.DumpZmsg("E: invalid message:");
                                        msg.Dispose();
                                    }
                                }
                    }
                    else
                    {
                        if (Equals(error, ZError.ETERM))
                        {
                            "W: interrupt received, shutting down...".DumpString();
                            break; // Interrupted
                        }
                        if (!Equals(error, ZError.EAGAIN))
                        {
                            throw new ZException(error);
                        }
                    }
                    // Disconnect and delete any expired workers
                    // Send heartbeats to idle workes if needed
                    if (DateTime.UtcNow > broker.HeartbeatAt)
                    {
                        broker.Purge();

                        foreach (var waitingworker in broker.Waiting)
                        {
                            waitingworker.Send(MdpCommon.MdpwCmd.HEARTBEAT.ToHexString(), null, null);
                        }
                        broker.HeartbeatAt = DateTime.UtcNow + MdpCommon.HEARTBEAT_INTERVAL;
                    }
                }
            }
        }
Example #11
0
            //  .split broker worker_msg method
            //  This method processes one READY, REPLY, HEARTBEAT, or
            //  DISCONNECT message sent to the broker by a worker:
            public void WorkerMsg(ZFrame sender, ZMessage msg)
            {
                if (msg.Count < 1) // At least, command
                {
                    throw new InvalidOperationException();
                }

                ZFrame command = msg.Pop();
                //string id_string = sender.ReadString();
                bool isWorkerReady;

                //string id_string;
                using (var sfrm = sender.Duplicate())
                {
                    var idString = sfrm.Read().ToHexString();
                    isWorkerReady = Workers.ContainsKey(idString);
                }
                Worker worker = RequireWorker(sender);

                using (msg)
                    using (command)
                    {
                        if (command.StrHexEq(MdpCommon.MdpwCmd.READY))
                        {
                            if (isWorkerReady)
                            {
                                // Not first command in session
                                worker.Delete(true);
                            }
                            else if (command.Length >= 4 &&
                                     command.ToString().StartsWith("mmi."))
                            {
                                // Reserd servicee name
                                worker.Delete(true);
                            }
                            else
                            {
                                // Attach worker to service and mark as idle
                                using (ZFrame serviceFrame = msg.Pop())
                                {
                                    worker.Service = RequireService(serviceFrame);
                                    worker.Service.Workers++;
                                    worker.Waiting();
                                }
                            }
                        }
                        else if (command.StrHexEq(MdpCommon.MdpwCmd.REPLY))
                        {
                            if (isWorkerReady)
                            {
                                //  Remove and save client return envelope and insert the
                                //  protocol header and service name, then rewrap envelope.
                                ZFrame client = msg.Unwrap();
                                msg.Prepend(new ZFrame(worker.Service.Name));
                                msg.Prepend(new ZFrame(MdpCommon.MDPC_CLIENT));
                                msg.Wrap(client);
                                Socket.Send(msg);
                                worker.Waiting();
                            }
                            else
                            {
                                worker.Delete(true);
                            }
                        }
                        else if (command.StrHexEq(MdpCommon.MdpwCmd.HEARTBEAT))
                        {
                            if (isWorkerReady)
                            {
                                worker.Expiry = DateTime.UtcNow + MdpCommon.HEARTBEAT_EXPIRY;
                            }
                            else
                            {
                                worker.Delete(true);
                            }
                        }
                        else if (command.StrHexEq(MdpCommon.MdpwCmd.DISCONNECT))
                        {
                            worker.Delete(false);
                        }
                        else
                        {
                            msg.DumpZmsg("E: invalid input message");
                        }
                    }
            }
        private void UpdateLoop(object sender, DoWorkEventArgs e)
        {
            loopActive = true;
            int loopInterval = 50;

            // Loop to get and assign elements, then update UI
            while (loopActive)
            {
                AsyncFormUpdate(new Action(() =>
                {
                    lblStatus.Text = "Update Loop Running";
                }));

                // Check to see if thread cancellation is pending
                // If true, stop the loop
                if (bwUpdateLoop.CancellationPending)
                {
                    requester.Close();
                    context.Shutdown();
                    context.Dispose();
                    requester.Dispose();
                    loopActive = false;

                    AsyncFormUpdate(new Action(() =>
                    {
                        lblStatus.Text = "Update Loop Stopped";
                    }));
                    break;
                }

                /// Socket Code
                // Send
                requester.Send(new ZFrame(_autoMode));

                try
                {
                    // Receive
                    using (ZFrame reply = requester.ReceiveFrame())
                    {
                        returnedData = JObject.Parse(reply.ToString());
                    }
                }
                catch (ZException ex)
                {
                    requester.Close();
                    context.Shutdown();
                    context.Dispose();
                    requester.Dispose();
                    loopActive = false;

                    AsyncFormUpdate(new Action(() =>
                    {
                        lblMode.Text   = "Loop Stopped";
                        lblStatus.Text = "Update Loop Stopped";
                    }));
                    break;
                }

                // ======================================================

                // Take all elements from the Dictionary and update the UI with them
                AsyncFormUpdate(new Action(() => ShowUI(returnedData)));

                // Stall the thread for a given interval to save on bandwidth
                Thread.Sleep(loopInterval);
            }

            /// update the UI with this status
            AsyncFormUpdate(new Action(() => {
                lblMode.Text = "Not Connected";
            }));
        }