public void TopicPubSub() { using (var pub = new XPublisherSocket()) using (var sub = new XSubscriberSocket()) { var port = pub.BindRandomPort("tcp://127.0.0.1"); sub.Connect("tcp://127.0.0.1:" + port); sub.SendFrame(new byte[] { 1, (byte)'A' }); // let the subscriber connect to the publisher before sending a message Thread.Sleep(500); var msg = pub.ReceiveFrameBytes(); Assert.AreEqual(2, msg.Length); Assert.AreEqual(1, msg[0]); Assert.AreEqual('A', msg[1]); pub.SendMoreFrame("A"); pub.SendFrame("Hello"); bool more; Assert.AreEqual("A", sub.ReceiveFrameString(out more)); Assert.IsTrue(more); Assert.AreEqual("Hello", sub.ReceiveFrameString(out more)); Assert.False(more); } }
public void Start() { ManualResetEvent mre = new ManualResetEvent(false); // NetMQ.Bind to Publish and Subscribe addresses Task.Factory.StartNew(() => { using (_toSocket = new XPublisherSocket()) using (_fromSocket = new XSubscriberSocket()) { _toSocket.Bind(_toAddress); _fromSocket.Bind(_fromAddress); _proxy = new Proxy(_fromSocket, _toSocket); mre.Set(); // This method is blocking, so important to set the ManualResetEvent before this. _proxy.Start(); } }); // Wait until the message host is actually started before returning mre.WaitOne(-1); }
public void MultipleSubscribers() { using (var pub = new XPublisherSocket()) using (var sub = new XSubscriberSocket()) using (var sub2 = new XSubscriberSocket()) { var port = pub.BindRandomPort("tcp://127.0.0.1"); sub.Connect("tcp://127.0.0.1:" + port); sub.SendFrame(new byte[] { 1, (byte)'A' }); sub.SendFrame(new byte[] { 1, (byte)'A', (byte)'B' }); sub.SendFrame(new byte[] { 1, (byte)'B' }); sub.SendFrame(new byte[] { 1, (byte)'C' }); sub2.Connect("tcp://127.0.0.1:" + port); sub2.SendFrame(new byte[] { 1, (byte)'A' }); sub2.SendFrame(new byte[] { 1, (byte)'A', (byte)'B' }); sub2.SendFrame(new byte[] { 1, (byte)'C' }); Thread.Sleep(500); pub.SendMoreFrame("AB"); pub.SendFrame("1"); Assert.AreEqual("AB", sub.ReceiveMultipartStrings().First(), "First subscriber is expected to receive the message"); Assert.AreEqual("AB", sub2.ReceiveMultipartStrings().First(), "Second subscriber is expected to receive the message"); } }
protected override async Task ExecuteAsync(CancellationToken stoppingToken) { try { _logger.LogInformation("XPub/XSub starting..."); using var _publisher = new XPublisherSocket($"@tcp://127.0.0.1:4444"); _logger.LogInformation($"XPub at 127.0.0.1:4444."); using var _subscriber = new XSubscriberSocket($"@tcp://127.0.0.1:5555"); _logger.LogInformation($"XSub at 127.0.0.1:5555."); var proxy = new Proxy(_subscriber, _publisher); var t = Task.Factory.StartNew(_ => { try { proxy.Start(); } catch (Exception e) { _logger.LogError(e, "ERROR in Proxy Task"); } }, TaskCreationOptions.LongRunning); await Task.Delay(-1, stoppingToken).ContinueWith(_ => { }); proxy.Stop(); await t; // to avoid proxy accessing disposed objects } catch (Exception e) { _logger.LogError(e, "ERROR in Worker"); } finally { _logger.LogInformation("XPub/XSub terminating"); } }
public void Unsubscribe() { using (var pub = new XPublisherSocket()) using (var sub = new XSubscriberSocket()) { var port = pub.BindRandomPort("tcp://127.0.0.1"); sub.Connect("tcp://127.0.0.1:" + port); sub.SendFrame(new byte[] { 1, (byte)'A' }); // let the subscriber connect to the publisher before sending a message Thread.Sleep(500); pub.SendMoreFrame("A"); pub.SendFrame("Hello"); bool more; Assert.AreEqual("A", sub.ReceiveFrameString(out more)); Assert.IsTrue(more); Assert.AreEqual("Hello", sub.ReceiveFrameString(out more)); Assert.False(more); sub.SendFrame(new byte[] { 0, (byte)'A' }); Thread.Sleep(500); pub.SendMoreFrame("A"); pub.SendFrame("Hello"); string str; Assert.IsFalse(sub.TryReceiveFrameString(out str)); } }
public void MultipleSubscriptions() { using (var pub = new XPublisherSocket()) using (var sub = new XSubscriberSocket()) { var port = pub.BindRandomPort("tcp://127.0.0.1"); sub.Connect("tcp://127.0.0.1:" + port); sub.SendFrame(new byte[] { 1, (byte)'C' }); sub.SendFrame(new byte[] { 1, (byte)'B' }); sub.SendFrame(new byte[] { 1, (byte)'A' }); sub.SendFrame(new byte[] { 1, (byte)'D' }); sub.SendFrame(new byte[] { 1, (byte)'E' }); Thread.Sleep(500); sub.SendFrame(new byte[] { 0, (byte)'C' }); sub.SendFrame(new byte[] { 0, (byte)'B' }); sub.SendFrame(new byte[] { 0, (byte)'A' }); sub.SendFrame(new byte[] { 0, (byte)'D' }); sub.SendFrame(new byte[] { 0, (byte)'E' }); Thread.Sleep(500); } }
private void ProxyThread() { if (_disposeCount != 0) { _traces.Debug("IpcEventProxy: disposed before start."); return; } XSubscriberSocket xsub = null; XPublisherSocket xpub = null; try { xsub = _context.CreateXSubscriberSocket(); xpub = _context.CreateXPublisherSocket(); xsub.Bind(_xSubscriberAddress); xpub.Bind(_xPublisherAddress); var xproxy = new Proxy(xpub, xsub, null); _traces.Debug("IpcEventProxy: started (pub->xsub {0} <=> {1} xpub<-sub)", _xSubscriberAddress, _xPublisherAddress); xproxy.Start(); _traces.Debug("IpcEventProxy: stopped."); } catch (NetMQException ex) { if (_disposeCount == 0 && !(ex is TerminatingException)) { _isFaultedState = true; _traces.Error(ex, "Error while IpcEventProxy starting or during operation."); var handler = FaultedState; if (handler != null) { try { handler(this, EventArgs.Empty); } catch (Exception ex2) { _traces.Error(ex2); } } } } finally { if (xsub != null) { _traces.CaptureMqExceptions(xsub.Dispose); } if (xpub != null) { _traces.CaptureMqExceptions(xpub.Dispose); } } }
private static void Intermediary() { using var xpubSocket = new XPublisherSocket("@tcp://localhost:1234"); using var xsubSocket = new XSubscriberSocket("@tcp://127.0.0.1:5678"); Console.WriteLine("Intermediary started, and waiting for messages"); // proxy messages between frontend / backend var proxy = new Proxy(xsubSocket, xpubSocket); // blocks indefinitely proxy.Start(); }
public IMessageBroker Startup() { if (IsStarted) { return(this); } var cancellationTokenSource = _cancellationTokenSource = new CancellationTokenSource(); _proxyTask = Task.Run(() => { var address = _configuration.GetAddress(); var pubAddress = $"@{_configuration.Schema}://{address}:{_configuration.XPubPort}"; var subAddress = $"@{_configuration.Schema}://{address}:{_configuration.XSubPort}"; #if DEBUG System.Diagnostics.Debug.WriteLine($"[{nameof( MessageBroker )}]XPub listening on: {pubAddress}"); System.Diagnostics.Debug.WriteLine($"[{nameof( MessageBroker )}]XSub listening on: {subAddress}"); #endif using (var xpubSocket = new XPublisherSocket(pubAddress)) using (var xsubSocket = new XSubscriberSocket(subAddress)) using (var controlIn = new DealerSocket("@inproc://control-in")) using (var controlOut = new DealerSocket("@inproc://control-out")) using (var controlInRecv = new DealerSocket(">inproc://control-in")) using (var controlOutRecv = new DealerSocket(">inproc://control-out")) { Task.Run(() => { while (!cancellationTokenSource.IsCancellationRequested) { try { var topic = controlInRecv.ReceiveFrameString(); var timestamp_bytes = controlInRecv.ReceiveFrameBytes(); var timestamp_int64 = BitConverter.ToInt64(timestamp_bytes, 0); var timestamp = new DateTimeOffset(timestamp_int64, TimeSpan.FromMinutes(0)); var message = controlInRecv.ReceiveFrameString(); var wrapper = new MessageWrapper(topic, message, timestamp); Logger?.LogReceive(wrapper); } catch (System.ObjectDisposedException) { return; } } }, cancellationTokenSource.Token); //proxy messages between frontend / backend var proxy = _proxy = new Proxy(xsubSocket, xpubSocket, controlIn, controlOut); //WARNING:blocks indefinitely. proxy.Start(); } }, cancellationTokenSource.Token); return(this); }
public void Run() { using (var xPubSocket = new XPublisherSocket("@" + Addresses.BuildFullAddress(Addresses.TCPLocalHost, Addresses.PublisherPort))) using (var xSubSocket = new XSubscriberSocket("@" + Addresses.BuildFullAddress(Addresses.TCPLocalHost, Addresses.SubscriberPort))) { Console.WriteLine("Intermediary broker started, and waiting for messages"); // proxy messages between frontend / backend var proxy = new Proxy(xPubSocket, xSubSocket); // blocks indefinitely proxy.Start(); } }
public IntermediarySocket(IAddressBinder frontendAddressBinder, IAddressBinder backendAddressBinder, XSubscriberSocket frontendSocket, XPublisherSocket backendSocket) { _frontendAddressBinder = frontendAddressBinder; _backendAddressBinder = backendAddressBinder; _frontendSocket = frontendSocket; _backendSocket = backendSocket; _frontendAddressBinder.ConnectOrBindAddress(_frontendSocket); _backendAddressBinder.ConnectOrBindAddress(_backendSocket); _poller = new Poller(_frontendSocket, _backendSocket); _proxy = new Proxy(frontendSocket, backendSocket, poller: _poller); }
public void ThroughXPubXSubWithReconnectingPublisher() { using (var xpub = new XPublisherSocket()) using (var xsub = new XSubscriberSocket()) using (var poller = new NetMQPoller { xsub, xpub }) { var xPubPort = (ushort)xpub.BindRandomPort("tcp://*"); var xSubPort = (ushort)xsub.BindRandomPort("tcp://*"); var proxy = new Proxy(xsub, xpub, poller: poller); proxy.Start(); poller.RunAsync(); // long running subscriber using (var sub = new SubscriberSocket()) { sub.Connect(string.Format("tcp://localhost:{0}", xPubPort)); sub.Subscribe("A"); // publisher 1 using (var pub = new PublisherSocket()) { pub.Connect(string.Format("tcp://localhost:{0}", xSubPort)); // give the publisher a chance to learn of the subscription Thread.Sleep(100); pub.SendMoreFrame("A").SendFrame("1"); } // publisher 2 using (var pub = new PublisherSocket()) { pub.Connect(string.Format("tcp://localhost:{0}", xSubPort)); // give the publisher a chance to learn of the subscription Thread.Sleep(100); pub.SendMoreFrame("A").SendFrame("2"); } var frames = new List <string>(); Assert.True(sub.TryReceiveMultipartStrings(TimeSpan.FromSeconds(1), ref frames)); CollectionAssert.AreEqual(new[] { "A", "1" }, frames); Assert.True(sub.TryReceiveMultipartStrings(TimeSpan.FromSeconds(1), ref frames)); CollectionAssert.AreEqual(new[] { "A", "2" }, frames); } } }
public static void Main(string[] args) { using (var xsubSocket = new XSubscriberSocket("@tcp://*:1234")) using (var xpubSocket = new XPublisherSocket("@tcp://*:5678")) { Console.WriteLine("Intermediary started, and waiting for messages"); // proxy messages between frontend / backend var proxy = new NetMQ.Proxy(xsubSocket, xpubSocket); // blocks indefinitely proxy.Start(); } }
/// <summary> /// 初始化PubSubServer。启动一个Task运行 /// </summary> /// <param name="addr">服务地址。可以运行在不同的PC上进行消息的收发</param> /// <param name="publiserPort">pub server port。订阅者连接到这个端口</param> /// <param name="subscribePort">sub server port。发布者连接到这个端口</param> public void InitServer(int publiserPort, int subscribePort, string addr = "127.0.0.1") { if (HadInited) { return; } _pubSocket = new XPublisherSocket($"@tcp://{addr}:{publiserPort}"); _subSocket = new XSubscriberSocket($"@tcp://{addr}:{subscribePort}"); _proxy = new Proxy(_subSocket, _pubSocket); Task.Factory.StartNew(_proxy.Start); HadInited = true; }
static void Intermediary() { var a2 = $"{address}:55507"; var a3 = $"{address}:55508"; using (var xpubSocket = new XPublisherSocket(a3)) using (var xsubSocket = new XSubscriberSocket(a2)) { Console.WriteLine("Intermediary started, and waiting for messages"); // proxy messages between frontend / backend var proxy = new Proxy(xsubSocket, xpubSocket); // blocks indefinitely proxy.Start(); } }
private void Work() { using (var subscriberSocket = new XSubscriberSocket()) { subscriberSocket.Bind(_toPublisherEndpoint); using (var publisherSocket = new XPublisherSocket()) { publisherSocket.Bind(_toSubscriberEndpoint); _proxy = new Proxy(subscriberSocket, publisherSocket); _proxy.Start(); } } }
public void Start() { using (var xpubSocket = new XPublisherSocket(_settings.PubAddress)) using (var xsubSocket = new XSubscriberSocket(_settings.SubAddress)) { // proxy messages between frontend / backend var proxy = new Proxy(xsubSocket, xpubSocket); _logger.LogInformation("Starting Pub/Sub Intermediary ..."); _logger.LogInformation("Awaiting Connections ..."); // blocks indefinitely proxy.Start(); } }
public IntermediarySocket(IAddressBinder frontendAddressBinder, IAddressBinder backendAddressBinder, XSubscriberSocket frontendSocket, XPublisherSocket backendSocket) { _frontendAddressBinder = frontendAddressBinder; _backendAddressBinder = backendAddressBinder; _frontendSocket = frontendSocket; _backendSocket = backendSocket; _frontendAddressBinder.ConnectOrBindAddress(_frontendSocket); _backendAddressBinder.ConnectOrBindAddress(_backendSocket); _poller = new NetMQPoller { _frontendSocket, _backendSocket }; _proxy = new Proxy(frontendSocket, backendSocket, poller: _poller); }
public void NotSubscribed() { using (var pub = new XPublisherSocket()) using (var sub = new XSubscriberSocket()) { var port = pub.BindRandomPort("tcp://127.0.0.1"); sub.Connect("tcp://127.0.0.1:" + port); // let the subscriber connect to the publisher before sending a message Thread.Sleep(500); pub.SendFrame("Hello"); Assert.IsFalse(sub.TrySkipFrame()); } }
public virtual void Setup(INetManager netManager) { if (string.IsNullOrEmpty(PushsocketString)) { throw new ArgumentNullException(nameof(PushsocketString)); } if (string.IsNullOrEmpty(PullSocketString)) { throw new ArgumentNullException(nameof(PullSocketString)); } if (netManager == null) { throw new ArgumentNullException(nameof(netManager)); } if (!string.IsNullOrEmpty(XPubSocketString) && !string.IsNullOrEmpty(XSubSocketString)) { var PublisherSocket = new XPublisherSocket(XPubSocketString); var SubscriberSocket = new XSubscriberSocket(XSubSocketString); GlobalServerProxy = new Proxy(SubscriberSocket, PublisherSocket); } sender = new PushSocket(PushsocketString); responseSocket = new PullSocket(PullSocketString); Poller = new NetMQPoller() { sender, responseSocket, PushQueue }; NetSend = netManager; PushQueue.ReceiveReady += (o, args) => { var msg = PushQueue.Dequeue(); sender.SendMultipartMessage(msg); }; responseSocket.ReceiveReady += ProcessResponse; IsSetuped = true; }
/// <summary> /// Starts the external to local message transfering. /// </summary> /// <param name="portForSubscribers">The port for local subscribers.</param> /// <param name="discoveryEndpoints">The endpoints to perform other brokers discovery.</param> private void StartExternalToLocalTransfer(int portForSubscribers, EndpointsRange discoveryEndpoints) { Task.Run(() => { using (var xsubSocket = new XSubscriberSocket()) using (var xpubSocket = new XPublisherSocket()) { xpubSocket.Bind($"tcp://localhost:{portForSubscribers}"); var dynamicSubscriber = new DynamicSubscriber(xsubSocket, discoveryEndpoints); dynamicSubscriber.StartDiscovering(); _externalToLocalProxy = new NetMQ.Proxy(xpubSocket, xsubSocket); _externalToLocalProxy.Start(); } }); }
public void SimplePubSub() { using (var pub = new XPublisherSocket()) using (var sub = new XSubscriberSocket()) { var port = pub.BindRandomPort("tcp://127.0.0.1"); sub.Connect("tcp://127.0.0.1:" + port); sub.SendFrame(new byte[] { 1 }); // let the subscriber connect to the publisher before sending a message Thread.Sleep(500); pub.SendFrame("Hello"); Assert.AreEqual("Hello", sub.ReceiveFrameString(out bool more)); Assert.False(more); } }
public void BroadcastEnabled() { using (var pub = new XPublisherSocket()) using (var sub1 = new XSubscriberSocket()) using (var sub2 = new XSubscriberSocket()) { pub.Bind("inproc://manual"); pub.Options.XPubBroadcast = true; sub1.Connect("inproc://manual"); sub2.Connect("inproc://manual"); sub1.SendFrame(new byte[] { 1, (byte)'A' }); sub2.SendFrame(new byte[] { 1, (byte)'A' }); var payload = new[] { (byte)42 }; var msg = new Msg(); msg.InitEmpty(); // add prefix 2 to the topic, this indicates a broadcast message and it will not be sent to sub1 sub1.SendFrame(new byte[] { 2, (byte)'A' }, true); sub1.SendFrame(new byte[] { (byte)42 }); var subscription = pub.ReceiveFrameBytes(); var topic = pub.ReceiveFrameBytes(); var message = pub.ReceiveFrameBytes(); Assert.AreEqual(2, topic[0]); // we must skip the first byte if we have detected a broadcast message // the sender of this message is already marked for exclusion // but the match logic in Send should work with normal topic. topic = topic.Skip(1).ToArray(); pub.SendFrame(topic, true); pub.SendFrame(message); var broadcast2 = sub2.ReceiveFrameBytes(); Assert.IsTrue(broadcast2[0] == 65); broadcast2 = sub2.ReceiveFrameBytes(); Assert.IsTrue(broadcast2.SequenceEqual(payload)); // this message SHOULD NOT be resent to sub1 var received = sub1.TryReceive(ref msg, System.TimeSpan.FromMilliseconds(500)); Assert.IsFalse(received); } }
public void Launch() { try { using (_xPubSocket = new XPublisherSocket($"@tcp://localhost:{_xPubPort}")) using (_xSubSocket = new XSubscriberSocket($"@tcp://localhost:{_xSubPort}")) { _xPubSocket.ReceiveReady += _xPubSocket_ReceiveReady; _xSubSocket.ReceiveReady += _xSubSocket_ReceiveReady; var proxy = new Proxy(_xSubSocket, _xPubSocket); Console.WriteLine("Broker started .."); proxy.Start(); } } catch (Exception ex) { Console.WriteLine($"Error : {ex.Message}"); throw; } }
public void BroadcastDisabled() { using (var pub = new XPublisherSocket()) using (var sub1 = new XSubscriberSocket()) using (var sub2 = new XSubscriberSocket()) { pub.Bind("inproc://manual"); pub.Options.XPubBroadcast = false; sub1.Connect("inproc://manual"); sub2.Connect("inproc://manual"); Thread.Sleep(50); sub1.SendFrame(new byte[] { 1, (byte)'A' }); sub2.SendFrame(new byte[] { 1, (byte)'A' }); var payload = new[] { (byte)42 }; var msg = new Msg(); msg.InitEmpty(); sub1.SendFrame(new byte[] { (byte)'A' }, true); sub1.SendFrame(new byte[] { (byte)42 }); var subscription = pub.ReceiveFrameBytes(); var topic = pub.ReceiveFrameBytes(); var message = pub.ReceiveFrameBytes(); pub.SendFrame(topic, true); pub.SendFrame(message); var broadcast2 = sub2.ReceiveFrameBytes(); Assert.IsTrue(broadcast2[0] == 65); broadcast2 = sub2.ReceiveFrameBytes(); Assert.IsTrue(broadcast2.SequenceEqual(payload)); // sub1 should receive a message normally var broadcast1 = sub1.ReceiveFrameBytes(); Assert.IsTrue(broadcast1[0] == 65); broadcast1 = sub1.ReceiveFrameBytes(); Assert.IsTrue(broadcast1.SequenceEqual(payload)); } }
protected void Dispose(bool disposing) { if (!_disposedValue) { if (disposing) { _proxy.Stop(); _proxy = null; _poller.Dispose(); _poller = null; _backendSocket.Dispose(); _backendSocket = null; _frontendSocket.Dispose(); _frontendSocket = null; } _disposedValue = true; } }
public void Census() { using (var pub = new XPublisherSocket()) using (var sub = new XSubscriberSocket()) { var port = pub.BindRandomPort("tcp://127.0.0.1"); sub.Connect("tcp://127.0.0.1:" + port); sub.SendFrame("Message from subscriber"); // let the subscriber connect to the publisher before sending a message Thread.Sleep(500); var txt = pub.ReceiveFrameString(); Assert.AreEqual("Message from subscriber", txt); sub.SendFrame(new byte[] { }); var msg = pub.ReceiveFrameBytes(); Assert.True(msg.Length == 0); } }
public void Manual() { using (var pub = new XPublisherSocket()) using (var sub = new XSubscriberSocket()) { pub.Bind("inproc://manual"); pub.Options.ManualPublisher = true; sub.Connect("inproc://manual"); sub.SendFrame(new byte[] { 1, (byte)'A' }); var subscription = pub.ReceiveFrameBytes(); Assert.AreEqual(subscription[1], (byte)'A'); pub.Subscribe("B"); pub.SendFrame("A"); pub.SendFrame("B"); Assert.AreEqual("B", sub.ReceiveFrameString()); } }
protected void Dispose(bool disposing) { if (!_disposedValue) { if (disposing) { _proxy.Stop(); _proxy = null; _poller.CancelAndJoin(); _poller.Dispose(); _poller = null; _backendSocket.Dispose(); _backendSocket = null; _frontendSocket.Dispose(); _frontendSocket = null; } _disposedValue = true; } }
public void ThroughXPubXSub() { using (var xpub = new XPublisherSocket()) using (var xsub = new XSubscriberSocket()) using (var proxyPoller = new NetMQPoller { xsub, xpub }) { var xPubPort = (ushort)xpub.BindRandomPort("tcp://*"); var xSubPort = (ushort)xsub.BindRandomPort("tcp://*"); var proxy = new Proxy(xsub, xpub, poller: proxyPoller); proxy.Start(); proxyPoller.RunAsync(); using (var pub = new PublisherSocket()) using (var sub = new SubscriberSocket()) { // Client 1 sub.Connect(string.Format("tcp://localhost:{0}", xPubPort)); pub.Connect(string.Format("tcp://localhost:{0}", xSubPort)); sub.Subscribe("A"); // Client 2 Thread.Sleep(500); pub.SendMoreFrame("A").SendFrame("Hello"); var frames = new List <string>(); Assert.True(sub.TryReceiveMultipartStrings(TimeSpan.FromSeconds(1), ref frames)); CollectionAssert.AreEqual( new[] { "A", "Hello" }, frames); } } }
public void MultiplePublishers() { using (var pub = new XPublisherSocket()) using (var pub2 = new XPublisherSocket()) using (var sub = new XSubscriberSocket()) using (var sub2 = new XSubscriberSocket()) { var port = pub.BindRandomPort("tcp://127.0.0.1"); var port2 = pub2.BindRandomPort("tcp://127.0.0.1"); // see comments below why verbose option is needed in this test pub.Options.XPubVerbose = true; pub2.Options.XPubVerbose = true; sub.Connect("tcp://127.0.0.1:" + port); sub.Connect("tcp://127.0.0.1:" + port2); sub2.Connect("tcp://127.0.0.1:" + port); sub2.Connect("tcp://127.0.0.1:" + port2); // should subscribe to both sub.SendFrame(new byte[] { 1, (byte)'A' }); sub2.SendFrame(new byte[] { 1, (byte)'A' }); Thread.Sleep(500); var msg = pub.ReceiveFrameString(); Assert.AreEqual(2, msg.Length); Assert.AreEqual(1, msg[0]); Assert.AreEqual('A', msg[1]); var msg2 = pub2.ReceiveFrameBytes(); Assert.AreEqual(2, msg2.Length); Assert.AreEqual(1, msg2[0]); Assert.AreEqual('A', msg2[1]); // Next two blocks (pub(2).Receive) will hang without XPub verbose option: // sub and sub2 both have sent `.Send(new byte[] { 1, (byte)'A' });` messages // which are the same, so XPub will discard the second message for .Receive() // because it is normally used to pass topics upstream. // (un)subs are done in XPub.cs at line 150-175, quote: // >> If the subscription is not a duplicate, store it so that it can be // >> passed to used on next recv call. // For verbose: // >> If true, send all subscription messages upstream, not just unique ones // These options must be set before sub2.Send(new byte[] { 1, (byte)'A' }); // pub.Options.XPubVerbose = true; // pub2.Options.XPubVerbose = true; // Note that resending sub2.Send(..) here wont help because XSub won't resent existing subs to XPub - quite sane behavior // Comment out the verbose options and the next 8 lines and the test will // still pass, even with non-unique messages from subscribers (see the bottom of the test) msg = pub.ReceiveFrameString(); Assert.AreEqual(2, msg.Length); Assert.AreEqual(1, msg[0]); Assert.AreEqual('A', msg[1]); msg2 = pub2.ReceiveFrameBytes(); Assert.AreEqual(2, msg2.Length); Assert.AreEqual(1, msg2[0]); Assert.AreEqual('A', msg2[1]); pub.SendMoreFrame("A"); pub.SendFrame("Hello from the first publisher"); bool more; Assert.AreEqual("A", sub.ReceiveFrameString(out more)); Assert.IsTrue(more); Assert.AreEqual("Hello from the first publisher", sub.ReceiveFrameString(out more)); Assert.False(more); // this returns the result of the latest // connect - address2, not the source of the message // This is documented here: http://api.zeromq.org/3-2:zmq-getsockopt //var ep = sub2.Options.LastEndpoint; //Assert.AreEqual(address, ep); // same for sub2 Assert.AreEqual("A", sub2.ReceiveFrameString(out more)); Assert.IsTrue(more); Assert.AreEqual("Hello from the first publisher", sub2.ReceiveFrameString(out more)); Assert.False(more); pub2.SendMoreFrame("A"); pub2.SendFrame("Hello from the second publisher"); Assert.AreEqual("A", sub.ReceiveFrameString(out more)); Assert.IsTrue(more); Assert.AreEqual("Hello from the second publisher", sub.ReceiveFrameString(out more)); Assert.False(more); Assert.AreEqual("tcp://127.0.0.1:" + port2, sub2.Options.LastEndpoint); // same for sub2 Assert.AreEqual("A", sub2.ReceiveFrameString(out more)); Assert.IsTrue(more); Assert.AreEqual("Hello from the second publisher", sub2.ReceiveFrameString(out more)); Assert.False(more); // send both to address and address2 sub.SendFrame("Message from subscriber"); sub2.SendFrame("Message from subscriber 2"); Assert.AreEqual("Message from subscriber", pub.ReceiveFrameString()); Assert.AreEqual("Message from subscriber", pub2.ReceiveFrameString()); // Does not hang even though is the same as above, but the first byte is not 1 or 0. // Won't hang even when messages are equal Assert.AreEqual("Message from subscriber 2", pub.ReceiveFrameString()); Assert.AreEqual("Message from subscriber 2", pub2.ReceiveFrameString()); } }
public void CouldTrackSubscriberIdentityInXPubSocket() { using (var pub = new XPublisherSocket()) using (var sub1 = new XSubscriberSocket()) using (var sub2 = new XSubscriberSocket()) { pub.Bind("inproc://manual"); pub.Options.ManualPublisher = true; sub1.Connect("inproc://manual"); sub2.Connect("inproc://manual"); Thread.Sleep(50); sub1.SendFrame(new byte[] { 1, (byte)'A' }); var identity1 = new byte[] { 1 }; var identity2 = new byte[] { 2 }; sub1.SendFrame(new byte[] { (byte)'A' }, true); sub1.SendFrame(new byte[] { (byte)42 }); var subscription = pub.ReceiveFrameBytes(); // NB Identity must be set before pub.Subscribe/Unsubscribe/Send, because these operations clear a private field with last subscriber // set identity to sub1 pub.Options.Identity = identity1; Assert.IsTrue(identity1.SequenceEqual(pub.Options.Identity), "Cannot read identity that was just set"); pub.Subscribe(subscription); Assert.IsTrue(identity1.SequenceEqual(pub.Options.Identity), "Identity must be kept after Subscribe/Unsubscribe/Send operations (which clear m_lastPipe)"); var topic = pub.ReceiveFrameBytes(); var message = pub.ReceiveFrameBytes(); sub2.SendFrame(new byte[] { 1, (byte)'A' }); sub2.SendFrame(new byte[] { (byte)'A' }, true); sub2.SendFrame(new byte[] { (byte)43 }); subscription = pub.ReceiveFrameBytes(); // Id of sub2 is not set yet Assert.IsNull(pub.Options.Identity); pub.Options.Identity = identity2; Assert.IsTrue(identity2.SequenceEqual(pub.Options.Identity), "Cannot read identity that was just set"); pub.Subscribe(subscription); Assert.IsTrue(identity2.SequenceEqual(pub.Options.Identity), "Identity must be kept after Subscribe/Unsubscribe/Send operations (which clear m_lastPipe)"); topic = pub.ReceiveFrameBytes(); message = pub.ReceiveFrameBytes(); sub1.SendFrame(new byte[] { (byte)'A' }, true); sub1.SendFrame(new byte[] { (byte)44 }); topic = pub.ReceiveFrameBytes(); message = pub.ReceiveFrameBytes(); Assert.IsTrue(identity1.SequenceEqual(pub.Options.Identity), "Identity option must be set to the identity of sub1 here"); sub2.SendFrame(new byte[] { (byte)'A' }, true); sub2.SendFrame(new byte[] { (byte)45 }); topic = pub.ReceiveFrameBytes(); message = pub.ReceiveFrameBytes(); Assert.IsTrue(identity2.SequenceEqual(pub.Options.Identity), "Identity option must be set to the identity of sub2 here"); } }