{"id":37034679,"url":"https://github.com/paultechguy/netmqpubsub","last_synced_at":"2026-01-14T04:03:45.519Z","repository":{"id":64351472,"uuid":"573576176","full_name":"paultechguy/NetMQPubSub","owner":"paultechguy","description":"A set of lightweight publisher-subscriber components using NET Core and NetMQ.","archived":false,"fork":false,"pushed_at":"2022-12-27T11:46:43.000Z","size":1007,"stargazers_count":6,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"dev","last_synced_at":"2025-09-21T18:45:22.720Z","etag":null,"topics":["cancellationtoken","csharp","example","ipc","netcore","netmq","pubsub","zeromq"],"latest_commit_sha":null,"homepage":"","language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/paultechguy.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2022-12-02T19:58:37.000Z","updated_at":"2024-05-29T06:10:44.000Z","dependencies_parsed_at":"2023-01-31T03:15:16.374Z","dependency_job_id":null,"html_url":"https://github.com/paultechguy/NetMQPubSub","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/paultechguy/NetMQPubSub","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/paultechguy%2FNetMQPubSub","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/paultechguy%2FNetMQPubSub/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/paultechguy%2FNetMQPubSub/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/paultechguy%2FNetMQPubSub/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/paultechguy","download_url":"https://codeload.github.com/paultechguy/NetMQPubSub/tar.gz/refs/heads/dev","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/paultechguy%2FNetMQPubSub/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28408997,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-14T01:52:23.358Z","status":"online","status_checked_at":"2026-01-14T02:00:06.678Z","response_time":107,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cancellationtoken","csharp","example","ipc","netcore","netmq","pubsub","zeromq"],"created_at":"2026-01-14T04:03:44.738Z","updated_at":"2026-01-14T04:03:45.507Z","avatar_url":"https://github.com/paultechguy.png","language":"C#","readme":"# NetMQPubSub\nNetMQPubSub is a lightweight IPC publish-subscribe library written in NET Core. The underlying IPC transport layer is provided by\n[NetMQ](https://github.com/zeromq/netmq).  The number of NetMQ features implemented in NetMQPubSub is limited to\nonly those required to support messaging between a publisher and its subscribers. Currently, this is a small number\nof features, but we will expand the feature set as needed in the future.\n\n## Overview\n\nNetMQPubSub provides support for features such as:\n* NET Standard Library - Supports C#, Android, Linux, macOS, Windows, Library\n* Multiple subscribers, subscribing to different topics.\n* Cancellation of publishers and subscribers using a .NET Core CancellationToken.\n* Can be used by both .NET Core web applications and console applications.\n* Messages can sent/received as strings or entity objects.\n\n## License\nNetMQPubSub uses the \u003ca href=\"https://mit-license.org/\" target=\"_blank\"\u003eMIT License\u003c/a\u003e model.\n\n## Nuget Packages\n\nFor most applications you write with NetMQPubSub, you will need to include\nseveral nuget packages (along with [NetMQ](https://github.com/zeromq/netmq)):\n\n* [NetMQPubSub.Common](https://www.nuget.org/packages/NetMQPubSub.Common) - Features that are common across both publisher and subscriber.\n* [NetMQPubSub.Core](https://www.nuget.org/packages/NetMQPubSub.Core) - Interfaces for publisher and subscriber related components. This has no dependency on NetMQ libraries.\n* [NetMQPubSub.Publisher](https://www.nuget.org/packages/NetMQPubSub.Publisher) - Features for publisher.\n* [NetMQPubSub.Subscriber](https://www.nuget.org/packages/NetMQPubSub.Subscriber) - Features for subscriber.\n\n**Note:** Except as noted, the [NetMQ](https://github.com/zeromq/netmq) IPC transport layer libraries must be\nincluded in code projects.\n\n## Example Applications\n\nIn addition, the repository also includes source code for the following example applications:\n\n* NetMQPubSub.ConsoleApp - This is a console-based application that demonstrates sending continuous messages from a single publisher to a large number of subscribers.  This also demonstrates how to cancel all messaging agents based on a NET Core cancellation token.\nThe source code for this application is included below.\n* NetMQPubSub.WebApp - A web application that demonstrates how to publish a message to a subscriber (within the web application as a service worker) when a web button is pressed. The code provides details on how to configure dependency injection for NET Core.\n\n## Community Enhancements\nWe welcome pull requests from the community to enhance and grow NetMQPubSub.\n\n## NetMQPubSub.ConsoleApp\nThis sample console application creates a single publisher and 10 subscribers.  The publisher will publish a message,\nusing one of 10 random topics, every 50ms.  Each subscriber is subscribed to a single topic.\nThe application will execute until the Enter key is pressed. This example provides a suitable demonstration of how\nto leverage a NET Core CancellationToken to stop and dispose of the publisher and all subscribers once\nthe Enter key is pressed. Lastly, it shows the proper way for an application to perform\nthe required NetMQ cleanup when an application shuts down (see the code reference\nto *NetMQPubSubHelper.Cleanup*).\n\n``` csharp\nnamespace NetMQPubSub.ConsoleApp;\n\nusing NetMQPubSub.Publisher;\nusing NetMQPubSub.Common.Helpers;\nusing NetMQPubSub.Subscriber;\nusing System;\nusing System.Linq;\nusing System.Text.Json;\nusing NetMQPubSub.Core.Interfaces;\n\ninternal class Program\n{\n\tprivate const int MaximumSubscribers = 10;\n\tprivate readonly List\u003cstring\u003e topics = Enumerable\n\t\t.Range(0, MaximumSubscribers)\n\t\t.Select(t =\u003e $\"Topic{t}\")\n\t\t.ToList();\n\n\tstatic void Main()\n\t{\n\t\tnew Program().Run();\n\t\tNetMQPubSubHelper.Cleanup();\n\t}\n\n\tprivate void Run()\n\t{\n\t\tConsole.Write(\"Press Enter to begin.  Once running, press Enter again to stop.\");\n\t\tConsole.ReadLine();\n\n\t\tvar cancellationTokenSource = new CancellationTokenSource();\n\t\tvar server = Task.Run(() =\u003e SubscribersAsync(cancellationTokenSource.Token));\n\t\tvar client = Task.Run(() =\u003e PublisherAsync(cancellationTokenSource.Token));\n\n\t\tConsole.ReadLine();\n\n\t\tcancellationTokenSource.Cancel();\n\t\tTask.WaitAll(server, client);\n\t}\n\n\tprivate void SubscribersAsync(CancellationToken cancelToken)\n\t{\n\t\t// or use \"inproc://{name}\" for in-process (e.g. inproc://job-service)\n\t\tvar addr = \"tcp://localhost:12345\";\n\n\t\tvar subscriberTasks = new List\u003cTask\u003e();\n\t\tfor (var i = 0; i \u003c topics.Count; i++)\n\t\t{\n\t\t\tvar topicIndex = i;\n\t\t\tsubscriberTasks.Add(Task.Run(() =\u003e RunTopicSubscriberAsync(topics[topicIndex], addr, topicIndex, cancelToken), cancelToken));\n\t\t}\n\n\t\tTask.WaitAll(subscriberTasks.ToArray());\n\t}\n\n\tprivate void PublisherAsync(CancellationToken cancelToken)\n\t{\n\t\t// or use \"inproc://{name}\" for in-process (e.g. inproc://job-service)\n\t\tvar addr = \"tcp://localhost:12345\";\n\n\t\tusing IMessagePublisher publisher = new MessagePublisher();\n\t\tpublisher.Options.SendHighWatermark = 1000;\n\n\t\tConsole.WriteLine(\"Publisher socket binding...\");\n\t\tpublisher.Bind(addr);\n\n\t\t// now that we've bound a socket, give subscriber a bit of time to initialize\n\t\t// before we begin sending messages\n\t\tThread.Sleep(1000);\n\n\t\tvar counter = 0;\n\t\tvar rand = new Random();\n\t\tdo\n\t\t{\n\t\t\tvar randomizedTopic = rand.Next(this.topics.Count);\n\t\t\tvar topic = this.topics[randomizedTopic];\n\t\t\t++counter;\n\n\t\t\tConsole.WriteLine($\"==\u003e Sending message for topic \\\"{topic}\\\". Message: #{counter}\");\n\t\t\tpublisher.SendTopicMessage(topic, new TestMessage() { Counter = counter });\n\n\t\t\t// simulate a bit of processing\n\t\t\tThread.Sleep(50);\n\n\t\t} while (!cancelToken.IsCancellationRequested);\n\n\t\tpublisher.Close(); // also consider Unbind(addr)\n\t\tConsole.WriteLine($\"==\u003e Publisher done!\");\n\t}\n\n\tprivate static void RunTopicSubscriberAsync(string topic, string addr, int id, CancellationToken cancelToken)\n\t{\n\t\tConsole.WriteLine($\"Subscriber #{id} socket connecting...\");\n\n\t\tusing IMessageSubscriber subscriber = new MessageSubscriber();\n\t\tsubscriber.Options.ReceiveHighWatermark = 1000;\n\t\tsubscriber.Connect(addr);\n\t\tsubscriber.TopicSubscribe(topic);\n\n\t\tconst int maxSecondsDelayBeforeCancelCheck = 2;\n\t\tvar timeout = TimeSpan.FromSeconds(maxSecondsDelayBeforeCancelCheck);\n\t\tdo\n\t\t{\n\t\t\tif (subscriber.TryReceiveMessage\u003cTestMessage\u003e(timeout, out var messageTopicReceived, out var entityReceived))\n\t\t\t{\n\t\t\t\tConsole.WriteLine($\"\u003c== Subscriber #{id} message for topic \\\"{messageTopicReceived}\\\". Message: {JsonSerializer.Serialize(entityReceived)}\");\n\t\t\t}\n\n\t\t} while (!cancelToken.IsCancellationRequested);\n\n\t\tsubscriber.Close(); // also consider Disconnect(addr)\n\t\tConsole.WriteLine($\"\u003c== Subscriber #{id} done!\");\n\t}\n\n\tinternal class TestMessage\n\t{\n\t\tpublic int Counter { get; set; }\n\n\t\tpublic string Name { get; set; }\n\n\t\tpublic DateTime Now { get; set; }\n\n\t\tpublic TestMessage()\n\t\t{\n\t\t\tvar names = new string[] { \"Joe\", \"Sally\", \"Mary\", \"Steve\", \"Iris\", \"Bob\" };\n\t\t\tvar random = new Random();\n\t\t\tthis.Counter = 0;\n\t\t\tthis.Name = names[random.Next(names.Length)];\n\t\t\tthis.Now = DateTime.Now;\n\t\t}\n\t}\n}\n```","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpaultechguy%2Fnetmqpubsub","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpaultechguy%2Fnetmqpubsub","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpaultechguy%2Fnetmqpubsub/lists"}