Пример #1
0
        private PublisherSocket GetNewPublisherSocket(string addressZeroMq)
        {
            PublisherSocket publisherSocket;

            {
                _loggerDelegate?.Invoke(string.Format("Publisher socket binding to: {0}\n", addressZeroMq));

                publisherSocket = new PublisherSocket();

                // Corner case: wait until publisher socket is ready (see code below that waits for
                // "_publisherReadySignal").
                NetMQMonitor monitor;
                {
                    // Must ensure that we have a unique monitor name for every instance of this class.
                    string endPoint = string.Format("inproc://#SubjectNetMQ#Publisher#{0}#{1}", addressZeroMq, Guid.NewGuid().ToString());
                    monitor = new NetMQMonitor(publisherSocket,
                                               endPoint,
                                               SocketEvents.Accepted | SocketEvents.Listening
                                               );
                    monitor.Accepted  += Publisher_Event_Accepted;
                    monitor.Listening += Publisher_Event_Listening;
                    monitor.StartAsync();
                }

                publisherSocket.Options.SendHighWatermark = this.HighwaterMark;
                try
                {
                    publisherSocket.Bind(addressZeroMq);
                }
                catch (NetMQException ex)
                {
                    // This is usually because the address is in use.
                    throw new Exception(string.Format("Error E56874. Cannot bind publisher to '{0}'. 95% probability that this is caused by trying to bind a publisher to a port already in use by another process. To fix, choose a unique publisher port for this process. For more on this error, see 'Readme.md' (or the GitHub homepage for NetMQ.ReactiveExtensions).", addressZeroMq), ex);
                }

                // Corner case: wait until publisher socket is ready (see code below that sets "_publisherReadySignal").
                {
                    Stopwatch sw = Stopwatch.StartNew();
                    _publisherReadySignal.WaitOne(TimeSpan.FromMilliseconds(3000));
                    _loggerDelegate?.Invoke(string.Format("Publisher: Waited {0} ms for binding.\n", sw.ElapsedMilliseconds));
                }
                {
                    monitor.Accepted  -= Publisher_Event_Accepted;
                    monitor.Listening -= Publisher_Event_Listening;
                    // Current issue with NegMQ: Cannot stop or dispose monitor, or else it stops the parent socket.
                    //monitor.Stop();
                    //monitor.Dispose();
                }
            }

            // Otherwise, the first item we publish may get missed by the subscriber. 500 milliseconds consistently works
            // locally, but occasionally fails on the AppVeyor build server. 650 milliseconds is optimal.
            using (EventWaitHandle wait = new ManualResetEvent(false))
            {
                // Cannot use Thread.Sleep() here, as this is incompatible with .NET Core 1.0, Windows 8.0, 8.1, and 10.
                wait.WaitOne(TimeSpan.FromMilliseconds(650));
            }

            return(publisherSocket);
        }
Пример #2
0
 public void StartAsync()
 {
     using (var rep = new ResponseSocket())
         using (var monitor = new NetMQMonitor(rep, "inproc://foo", SocketEvents.Closed))
         {
             var task = monitor.StartAsync();
             Thread.Sleep(200);
             Assert.AreEqual(TaskStatus.Running, task.Status);
             monitor.Stop();
             Assert.True(task.Wait(TimeSpan.FromMilliseconds(1000)));
         }
 }
Пример #3
0
 public void StartAsync()
 {          
     using (var rep = new ResponseSocket())
     using (var monitor = new NetMQMonitor(rep, "inproc://foo", SocketEvents.Closed))
     {
         var task = monitor.StartAsync();
         Thread.Sleep(200);
         Assert.AreEqual(TaskStatus.Running, task.Status);
         monitor.Stop();
         Assert.True(task.Wait(TimeSpan.FromMilliseconds(1000)));
     }
 }
Пример #4
0
        private void InitializePublisherOnFirstUse()
        {
            if (m_initializePublisherDone == false)             // Double checked locking.
            {
                lock (m_initializePublisherLock)
                {
                    if (m_initializePublisherDone == false)
                    {
                        Console.WriteLine("Publisher socket binding to: {0}", ZeroMqAddress);
                        m_publisherSocket = new PublisherSocket();

                        // Corner case: wait until publisher socket is ready (see code below that waits for
                        // "_publisherReadySignal").
                        NetMQMonitor monitor;
                        {
                            // Must ensure that we have a unique monitor name for every instance of this class.
                            string endPoint = string.Format("inproc://#SubjectNetMQ#Publisher#{0}#{1}", this.QueueName, this.ZeroMqAddress);
                            monitor = new NetMQMonitor(m_publisherSocket, endPoint,
                                                       SocketEvents.Accepted | SocketEvents.Listening
                                                       );
                            monitor.Accepted  += Publisher_Event_Accepted;
                            monitor.Listening += Publisher_Event_Listening;
                            monitor.StartAsync();
                        }


                        m_publisherSocket.Options.SendHighWatermark = 2000 * 1000;

                        m_publisherSocket.Bind(this.ZeroMqAddress);

                        // Corner case: wait until publisher socket is ready (see code below that sets
                        // "_publisherReadySignal").
                        {
                            Stopwatch sw = Stopwatch.StartNew();
                            m_publisherReadySignal.WaitOne(TimeSpan.FromMilliseconds(3000));
                            Console.Write("Publisher: Waited {0} ms for binding.\n", sw.ElapsedMilliseconds);
                        }
                        {
                            monitor.Accepted  -= Publisher_Event_Accepted;
                            monitor.Listening -= Publisher_Event_Listening;
                            // Current issue with NegMQ: Cannot stop or dispose monitor, or else it stops the parent socket.
                            //monitor.Stop();
                            //monitor.Dispose();
                        }
                        m_initializePublisherDone = true;
                    }
                }                  // lock
                Thread.Sleep(500); // Otherwise, the first item we publish may get missed by the subscriber.
            }
        }
Пример #5
0
        private static async Task CreatePushSocket()
        {
            var poller = new NetMQPoller();

            push = new PushSocket();
            push.BindRandomPort("tcp://127.0.0.1");
            NetMQMonitor monitor = new NetMQMonitor(push, "inproc://req.inproc", SocketEvents.All);

            monitor.Connected     += Monitor_Connected;
            monitor.EventReceived += Monitor_EventReceived;
            //monitor.AttachToPoller(poller);
            queue.ReceiveReady += Queue_ReceiveReady;;
            push.Connect(address);
            poller.Add(push);
            poller.Add(queue);
            poller.RunAsync();
            await monitor.StartAsync();
        }
Пример #6
0
 private static void CreatePullSocket()
 {
     try
     {
         var          poller  = new NetMQPoller();
         NetMQMonitor monitor = new NetMQMonitor(pull, "inproc://req.inproc", SocketEvents.All);
         monitor.Accepted      += Monitor_Accepted;
         monitor.EventReceived += Monitor_EventReceived;
         pull.ReceiveReady     += Pull_ReceiveReady1;
         pull.Bind(address);
         //monitor.AttachToPoller(poller);
         poller.Add(pull);
         poller.RunAsync();
         monitor.StartAsync();
     }
     catch (Exception ex)
     {
     }
 }
Пример #7
0
        public bool TryConnectAndMonitorSocket(NetMQSocket socket, string address, NetMQPoller poller = null, Action <IConnectionMonitor, bool> onConnectionStateChanged = null)
        {
            _onConnectionStateChanged = onConnectionStateChanged;

            _monitor               = new NetMQMonitor(socket, $"inproc://monitor.socket/{Guid.NewGuid()}", SocketEvents.Connected | SocketEvents.Disconnected);
            _monitor.Connected    += MonitorConnected;
            _monitor.Disconnected += MonitorDisconnected;

            if (poller == null)
            {
                _monitorTask = _monitor.StartAsync();
            }
            else
            {
                _monitor.AttachToPoller(poller);
            }

            socket.Connect(address);
            return(WaitForConnection());
        }
Пример #8
0
            protected override void _SocketBuilder()
            {
                reportLog("Starting Router name " + Name, LogType.INFO, section);

                socket = new RouterSocket();

                socket.Options.TcpKeepalive         = true;
                socket.Options.TcpKeepaliveIdle     = TimeSpan.FromMilliseconds(100);
                socket.Options.TcpKeepaliveInterval = TimeSpan.FromMilliseconds(100);

                local_port = socket.BindRandomPort("tcp://*");

                monitor = new NetMQMonitor(socket, "inproc://router" + Net2.GetAddressIndex(), SocketEvents.All);
                monitor.Disconnected += Monitor_Disconnected;
                monitor.Accepted     += Monitor_Connected;
                monitor.Timeout       = TimeSpan.FromMilliseconds(100);
                task = monitor.StartAsync();

                setState(Net2State.STARTED);
                start_time = GetTime().sec;

                reportLog("Router is ready on " + local_port, LogType.INFO, section);
            }
Пример #9
0
        private void InitializeSubscriberOnFirstUse()
        {
            if (m_initializeSubscriberDone == false)             // Double checked locking.
            {
                lock (m_subscribersLock)
                {
                    if (m_initializeSubscriberDone == false)
                    {
                        Console.WriteLine("Subscriber socket connecting to: {0}", ZeroMqAddress);
                        m_subscriberSocket = new SubscriberSocket();

                        // Corner case: wait until subscriber socket is ready (see code below that waits for
                        // "_subscriberReadySignal").
                        NetMQMonitor monitor;
                        {
                            // Must ensure that we have a unique monitor name for every instance of this class.
                            string endpoint = string.Format("inproc://#SubjectNetMQ#Subscriber#{0}#{1}", this.QueueName, this.ZeroMqAddress);

                            monitor = new NetMQMonitor(m_subscriberSocket, endpoint,
                                                       SocketEvents.ConnectRetried | SocketEvents.Connected);
                            monitor.ConnectRetried += Subscriber_Event_ConnectRetried;
                            monitor.Connected      += Subscriber_Event_Connected;
                            monitor.StartAsync();
                        }

                        m_subscriberSocket.Options.ReceiveHighWatermark = 2000 * 1000;
                        m_subscriberSocket.Connect(this.ZeroMqAddress);
                        m_subscriberSocket.Subscribe(this.QueueName);

                        if (m_cancellationTokenSource == null)
                        {
                            m_cancellationTokenSource = new CancellationTokenSource();
                        }

                        ManualResetEvent threadReadySignal = new ManualResetEvent(false);

                        m_thread = new Thread(() =>
                        {
                            try
                            {
                                Console.Write("Thread initialized.\n");
                                threadReadySignal.Set();
                                while (m_cancellationTokenSource.IsCancellationRequested == false)
                                {
                                    string messageTopicReceived = m_subscriberSocket.ReceiveFrameString();
                                    if (messageTopicReceived != QueueName)
                                    {
                                        throw new Exception(string.Format("Error E65724. We should always subscribe on the queue name '{0}', instead we got '{1}'.", QueueName, messageTopicReceived));
                                    }
                                    var type = m_subscriberSocket.ReceiveFrameString();
                                    switch (type)
                                    {
                                    // Originated from "OnNext".
                                    case "N":
                                        T messageReceived = m_subscriberSocket.ReceiveFrameBytes().DeserializeProtoBuf <T>();
                                        lock (m_subscribersLock)
                                        {
                                            m_subscribers.ForEach(o => o.OnNext(messageReceived));
                                        }
                                        break;

                                    // Originated from "OnCompleted".
                                    case "C":
                                        lock (m_subscribersLock)
                                        {
                                            m_subscribers.ForEach(o => o.OnCompleted());

                                            // We are done! We don't want to send any more messages to subscribers, and we
                                            // want to close the listening socket.
                                            m_cancellationTokenSource.Cancel();
                                        }
                                        break;

                                    // Originated from "OnException".
                                    case "E":
                                        Exception exception;
                                        string exceptionAsString = "Uninitialized.";
                                        try
                                        {
                                            // Not used, but useful for cross-platform debugging: we can read the error straight off the wire.
                                            exceptionAsString = m_subscriberSocket.ReceiveFrameBytes().DeserializeProtoBuf <string>();
                                            SerializableException exceptionWrapper = m_subscriberSocket.ReceiveFrameBytes().DeSerializeException();
                                            exception = exceptionWrapper.InnerException;
                                        }
                                        catch (Exception ex)
                                        {
                                            // If we had trouble deserializing the exception (probably due to a
                                            // different version of .NET), then do the next best thing: (1) The
                                            // inner exception is the error we got when deserializing, and (2) the
                                            // main exception is the human-readable "exception.ToString()" that we
                                            // originally captured.
                                            exception = new Exception(exceptionAsString, ex);
                                        }

                                        lock (m_subscribersLock)
                                        {
                                            m_subscribers.ForEach(o => o.OnError(exception));
                                        }
                                        break;

                                    // Originated from a "Ping" request.
                                    case "P":
                                        // Do nothing, this is a ping command used to wait until sockets are initialized properly.
                                        Console.Write("Received ping.\n");
                                        break;

                                    default:
                                        throw new Exception(string.Format("Error E28734. Something is wrong - received '{0}' when we expected \"N\", \"C\" or \"E\" - are we out of sync?", type));
                                    }
                                }
                            }
                            catch (Exception ex)
                            {
                                Console.Write("Error E23844. Exception in threadName \"{0}\". Thread exiting. Exception: \"{1}\".\n", QueueName, ex.Message);
                                lock (m_subscribersLock)
                                {
                                    this.m_subscribers.ForEach((ob) => ob.OnError(ex));
                                }
                            }
                            finally
                            {
                                lock (m_subscribersLock)
                                {
                                    m_subscribers.Clear();
                                }
                                m_cancellationTokenSource.Dispose();

                                // Disconnect from the socket.
                                m_subscriberSocket.Dispose();
                            }
                        })
                        {
                            Name         = this.QueueName,
                            IsBackground = true                             // Have to set it to background, or else it will not exit when the program exits.
                        };
                        m_thread.Start();

                        // Wait for thread to properly spin up.
                        threadReadySignal.WaitOne(TimeSpan.FromMilliseconds(3000));

                        // Corner case: wait until the publisher socket is ready (see code above that sets
                        // "_subscriberReadySignal").
                        {
                            Stopwatch sw = Stopwatch.StartNew();
                            m_subscriberReadySignal.WaitOne(TimeSpan.FromMilliseconds(3000));
                            Console.Write("Subscriber: Waited {0} ms for connection.\n", sw.ElapsedMilliseconds);

                            monitor.ConnectRetried -= Subscriber_Event_ConnectRetried;
                            monitor.Connected      -= Subscriber_Event_Connected;

                            // Issue with NetMQ - cannot .Stop or .Dispose, or else it will dispose of the parent socket.
                            //monitor.Stop();
                            //monitor.Dispose();
                        }

                        Console.Write("Subscriber: finished setup.\n");

                        m_initializeSubscriberDone = true;
                    }
                }                  // lock
                Thread.Sleep(500); // Otherwise, the first item we subscribe  to may get missed by the subscriber.
            }
        }
		private PublisherSocket GetNewPublisherSocket(string addressZeroMq)
		{
			PublisherSocket publisherSocket;
			{
				_loggerDelegate?.Invoke(string.Format("Publisher socket binding to: {0}\n", addressZeroMq));

				publisherSocket = new PublisherSocket();

				// Corner case: wait until publisher socket is ready (see code below that waits for
				// "_publisherReadySignal").
				NetMQMonitor monitor;
				{
					// Must ensure that we have a unique monitor name for every instance of this class.
					string endPoint = string.Format("inproc://#SubjectNetMQ#Publisher#{0}#{1}", addressZeroMq, Guid.NewGuid().ToString());
					monitor = new NetMQMonitor(publisherSocket,
						endPoint,
						SocketEvents.Accepted | SocketEvents.Listening
						);
					monitor.Accepted += Publisher_Event_Accepted;                    
                    monitor.Listening += Publisher_Event_Listening;
					monitor.StartAsync();
				}

				publisherSocket.Options.SendHighWatermark = this.HighwaterMark;
				try
				{
					publisherSocket.Bind(addressZeroMq);
				}
				catch (NetMQException ex)
				{
					// This is usually because the address is in use.
					throw new Exception(string.Format("Error E56874. Cannot bind publisher to '{0}'. 95% probability that this is caused by trying to bind a publisher to a port already in use by another process. To fix, choose a unique publisher port for this process. For more on this error, see 'Readme.md' (or the GitHub homepage for NetMQ.ReactiveExtensions).", addressZeroMq), ex);
				}
				
				// Corner case: wait until publisher socket is ready (see code below that sets "_publisherReadySignal").
				{
					Stopwatch sw = Stopwatch.StartNew();
					_publisherReadySignal.WaitOne(TimeSpan.FromMilliseconds(3000));
					_loggerDelegate?.Invoke(string.Format("Publisher: Waited {0} ms for binding.\n", sw.ElapsedMilliseconds));
				}
				{
					monitor.Accepted -= Publisher_Event_Accepted;
					monitor.Listening -= Publisher_Event_Listening;
					// Current issue with NegMQ: Cannot stop or dispose monitor, or else it stops the parent socket.
					//monitor.Stop();
					//monitor.Dispose();
				}
			}

            // Otherwise, the first item we publish may get missed by the subscriber. 500 milliseconds consistently works 
            // locally, but occasionally fails on the AppVeyor build server. 650 milliseconds is optimal.
            using (EventWaitHandle wait = new ManualResetEvent(false))
            {
                // Cannot use Thread.Sleep() here, as this is incompatible with .NET Core 1.0, Windows 8.0, 8.1, and 10.
                wait.WaitOne(TimeSpan.FromMilliseconds(650));
            }

            return publisherSocket;
		}