{"id":34547053,"url":"https://github.com/ulala-x/net-zmq","last_synced_at":"2026-01-13T23:41:05.272Z","repository":{"id":329194115,"uuid":"1116634341","full_name":"ulala-x/net-zmq","owner":"ulala-x","description":"High-performance ZeroMQ bindings for .NET with cppzmq-style API","archived":false,"fork":false,"pushed_at":"2025-12-30T10:29:52.000Z","size":3417,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-01-13T19:51:03.242Z","etag":null,"topics":["csharp","dotnet","libzmq","messaging","networking","nuget","zeromq","zmq"],"latest_commit_sha":null,"homepage":"https://www.nuget.org/packages/Net.Zmq","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/ulala-x.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-12-15T06:52:30.000Z","updated_at":"2025-12-30T10:29:55.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/ulala-x/net-zmq","commit_stats":null,"previous_names":["ulala-x/net-zmq"],"tags_count":6,"template":false,"template_full_name":null,"purl":"pkg:github/ulala-x/net-zmq","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ulala-x%2Fnet-zmq","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ulala-x%2Fnet-zmq/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ulala-x%2Fnet-zmq/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ulala-x%2Fnet-zmq/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ulala-x","download_url":"https://codeload.github.com/ulala-x/net-zmq/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ulala-x%2Fnet-zmq/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28405308,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-13T21:51:37.118Z","status":"ssl_error","status_checked_at":"2026-01-13T21:45:14.585Z","response_time":56,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"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":["csharp","dotnet","libzmq","messaging","networking","nuget","zeromq","zmq"],"created_at":"2025-12-24T07:19:03.289Z","updated_at":"2026-01-13T23:41:05.267Z","avatar_url":"https://github.com/ulala-x.png","language":"C#","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Net.Zmq\n\n[![English](https://img.shields.io/badge/lang:en-red.svg)](README.md) [![한국어](https://img.shields.io/badge/lang:한국어-blue.svg)](README.ko.md)\n\n[![Build and Test](https://github.com/ulala-x/net-zmq/actions/workflows/build.yml/badge.svg)](https://github.com/ulala-x/net-zmq/actions/workflows/build.yml)\n[![NuGet](https://img.shields.io/nuget/v/Net.Zmq.svg)](https://www.nuget.org/packages/Net.Zmq)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)\n[![Documentation](https://img.shields.io/badge/docs-online-blue.svg)](https://ulala-x.github.io/net-zmq/)\n[![Changelog](https://img.shields.io/badge/changelog-v0.2.0-green.svg)](CHANGELOG.md)\n\nA modern .NET 8+ binding for ZeroMQ (libzmq) with cppzmq-style API.\n\n## Features\n\n- **Modern .NET**: Built for .NET 8.0+ with `[LibraryImport]` source generators (no runtime marshalling overhead)\n- **cppzmq Style**: Familiar API for developers coming from C++\n- **Type Safe**: Strongly-typed socket options, message properties, and enums\n- **Cross-Platform**: Supports Windows, Linux, and macOS (x64, ARM64)\n- **Safe by Default**: SafeHandle-based resource management\n\n## Installation\n\n```bash\ndotnet add package Net.Zmq\n```\n\n## Quick Start\n\n### REQ-REP Pattern\n\n```csharp\nusing Net.Zmq;\n\n// Server\nusing var ctx = new Context();\nusing var server = new Socket(ctx, SocketType.Rep);\nserver.Bind(\"tcp://*:5555\");\n\nvar request = server.RecvString();\nserver.Send(\"World\");\n\n// Client\nusing var client = new Socket(ctx, SocketType.Req);\nclient.Connect(\"tcp://localhost:5555\");\nclient.Send(\"Hello\");\nvar reply = client.RecvString();\n```\n\n### PUB-SUB Pattern\n\n```csharp\nusing Net.Zmq;\n\n// Publisher\nusing var ctx = new Context();\nusing var pub = new Socket(ctx, SocketType.Pub);\npub.Bind(\"tcp://*:5556\");\npub.Send(\"topic1 Hello subscribers!\");\n\n// Subscriber\nusing var sub = new Socket(ctx, SocketType.Sub);\nsub.Connect(\"tcp://localhost:5556\");\nsub.Subscribe(\"topic1\");\nvar message = sub.RecvString();\n```\n\n### Router-to-Router Pattern\n\n```csharp\nusing System.Text;\nusing Net.Zmq;\n\nusing var ctx = new Context();\nusing var peerA = new Socket(ctx, SocketType.Router);\nusing var peerB = new Socket(ctx, SocketType.Router);\n\n// Set explicit identities for Router-to-Router\npeerA.SetOption(SocketOption.Routing_Id, \"PEER_A\"u8.ToArray());\npeerB.SetOption(SocketOption.Routing_Id, \"PEER_B\"u8.ToArray());\n\npeerA.Bind(\"tcp://127.0.0.1:5555\");\npeerB.Connect(\"tcp://127.0.0.1:5555\");\n\n// Peer B sends to Peer A (first frame = target identity)\npeerB.Send(\"PEER_A\"u8, SendFlags.SendMore);\npeerB.Send(\"Hello from Peer B!\");\n\n// Peer A receives (first frame = sender identity)\nSpan\u003cbyte\u003e idBuffer = stackalloc byte[64];\nint idLen = peerA.Recv(idBuffer);\nvar senderId = idBuffer[..idLen];\nvar message = peerA.RecvString();\n\n// Peer A replies using sender's identity\npeerA.Send(senderId, SendFlags.SendMore);\npeerA.Send(\"Hello back from Peer A!\");\n```\n\n### Polling\n\n```csharp\nusing Net.Zmq;\n\n// Create Poller instance\nusing var poller = new Poller(capacity: 2);\n\n// Add sockets and store their indices\nint idx1 = poller.Add(socket1, PollEvents.In);\nint idx2 = poller.Add(socket2, PollEvents.In);\n\n// Poll for events\nif (poller.Poll(timeout: 1000) \u003e 0)\n{\n    if (poller.IsReadable(idx1)) { /* handle socket1 */ }\n    if (poller.IsReadable(idx2)) { /* handle socket2 */ }\n}\n```\n\n### Message API\n\n```csharp\nusing Net.Zmq;\n\n// Create and send message\nusing var msg = new Message(\"Hello World\");\nsocket.Send(msg);\n\n// Receive message\nusing var reply = new Message();\nsocket.Recv(reply);\nConsole.WriteLine(reply.ToString());\n```\n\n## Socket Types\n\n| Type | Description |\n|------|-------------|\n| `SocketType.Req` | Request socket (client) |\n| `SocketType.Rep` | Reply socket (server) |\n| `SocketType.Pub` | Publish socket |\n| `SocketType.Sub` | Subscribe socket |\n| `SocketType.Push` | Push socket (pipeline) |\n| `SocketType.Pull` | Pull socket (pipeline) |\n| `SocketType.Dealer` | Async request |\n| `SocketType.Router` | Async reply |\n| `SocketType.Pair` | Exclusive pair |\n\n## API Reference\n\n### Context\n\n```csharp\nvar ctx = new Context();                           // Default\nvar ctx = new Context(ioThreads: 2, maxSockets: 1024);  // Custom\n\nctx.SetOption(ContextOption.IoThreads, 4);\nvar threads = ctx.GetOption(ContextOption.IoThreads);\n\nvar (major, minor, patch) = Context.Version;       // Get ZMQ version\nbool hasCurve = Context.Has(\"curve\");              // Check capability\n```\n\n### Socket\n\n```csharp\nvar socket = new Socket(ctx, SocketType.Req);\n\n// Connection\nsocket.Bind(\"tcp://*:5555\");\nsocket.Connect(\"tcp://localhost:5555\");\nsocket.Unbind(\"tcp://*:5555\");\nsocket.Disconnect(\"tcp://localhost:5555\");\n\n// Send\nsocket.Send(\"Hello\");\nsocket.Send(byteArray);\nsocket.Send(message, SendFlags.SendMore);\nbool sent = socket.Send(data, SendFlags.DontWait); // false if would block\n\n// Receive\nstring str = socket.RecvString();\nint bytesRead = socket.Recv(buffer);\nsocket.Recv(message);\nbool received = socket.TryRecvString(out string result);\nbool gotData = socket.TryRecv(buffer, out int size);\n\n// Options\nsocket.SetOption(SocketOption.Linger, 0);\nint linger = socket.GetOption\u003cint\u003e(SocketOption.Linger);\n```\n\n## Performance\n\n### Recommended Message Strategies\n\nNet.Zmq provides multiple message buffer strategies to accommodate different performance requirements:\n\n**Available Strategies:**\n- **Basic Message**: Simple `Message` object for general use\n- **ArrayPool**: Uses `ArrayPool\u003cbyte\u003e.Shared` for buffer reuse (manual return required)\n- **MessageZeroCopy**: Zero-copy messages using `Marshal.AllocHGlobal` for large data\n\n**Recommendations by Message Size:**\n- **Small messages (≤1KB)**: **`ArrayPool\u003cbyte\u003e.Shared`** - Best performance with minimal GC pressure\n- **Large messages (≥64KB)**: **`MessageZeroCopy`** - Zero-copy semantics with minimal GC overhead\n\n**Receive Mode:**\n- Single socket → Blocking\n- Multiple sockets → `Poller`\n\n```csharp\n// Small messages: ArrayPool (recommended)\nvar buffer = ArrayPool\u003cbyte\u003e.Shared.Rent(size);\ntry\n{\n    // Fill buffer with data\n    socket.Send(buffer.AsSpan(0, size));\n}\nfinally\n{\n    ArrayPool\u003cbyte\u003e.Shared.Return(buffer);\n}\n\n// Large messages: MessageZeroCopy\nnint nativePtr = Marshal.AllocHGlobal(dataSize);\nunsafe\n{\n    var nativeSpan = new Span\u003cbyte\u003e((void*)nativePtr, dataSize);\n    sourceData.CopyTo(nativeSpan);\n}\nusing var message = new Message(nativePtr, dataSize, ptr =\u003e\n{\n    Marshal.FreeHGlobal(ptr); // Called when libzmq is done\n});\nsocket.Send(message);\n\n// Receive: Blocking with Message\nusing var msg = new Message();\nsocket.Recv(msg);\n// Process msg.Data\n```\n\nFor fine-tuning options and detailed benchmarks, see [docs/benchmarks.md](docs/benchmarks.md).\n\n## Supported Platforms\n\n| OS | Architecture |\n|----|--------------|\n| Windows | x64, ARM64 |\n| Linux | x64, ARM64 |\n| macOS | x64, ARM64 |\n\n## Documentation\n\nComplete API documentation is available at: [https://ulala-x.github.io/net-zmq/](https://ulala-x.github.io/net-zmq/)\n\nThe documentation includes:\n- API Reference for all classes and methods\n- Usage examples and patterns\n- Performance benchmarks\n- Platform-specific guides\n\n## Requirements\n\n- .NET 8.0 or later\n- Native libzmq library (automatically provided via Net.Zmq.Native package)\n\n## License\n\nMIT License - see [LICENSE](LICENSE) for details.\n\n## Related Projects\n\n- [libzmq](https://github.com/zeromq/libzmq) - ZeroMQ core library\n- [cppzmq](https://github.com/zeromq/cppzmq) - C++ binding (API inspiration)\n- [libzmq-native](https://github.com/ulala-x/libzmq-native) - Native binaries\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fulala-x%2Fnet-zmq","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fulala-x%2Fnet-zmq","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fulala-x%2Fnet-zmq/lists"}