{"id":13504016,"url":"https://github.com/lemunozm/message-io","last_synced_at":"2025-05-13T22:07:09.358Z","repository":{"id":40234468,"uuid":"276974837","full_name":"lemunozm/message-io","owner":"lemunozm","description":"Fast and easy-to-use event-driven network library.","archived":false,"fork":false,"pushed_at":"2025-03-18T07:21:17.000Z","size":712,"stargazers_count":1165,"open_issues_count":20,"forks_count":79,"subscribers_count":16,"default_branch":"master","last_synced_at":"2025-05-12T16:06:00.815Z","etag":null,"topics":["actor-model","actor-system","asynchronous","event-driven","event-driven-architecture","event-manager","events","message-driven","message-queue","multicast","network","network-programming","non-blocking","sockets","tcp","tcp-server","transport","udp","udp-server","websocket"],"latest_commit_sha":null,"homepage":"","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/lemunozm.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"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}},"created_at":"2020-07-03T19:37:30.000Z","updated_at":"2025-05-09T17:33:39.000Z","dependencies_parsed_at":"2024-02-02T10:30:50.078Z","dependency_job_id":"d73c318e-b61a-421c-b776-32ec9ef63d83","html_url":"https://github.com/lemunozm/message-io","commit_stats":{"total_commits":240,"total_committers":11,"mean_commits":"21.818181818181817","dds":0.07499999999999996,"last_synced_commit":"2f8efe1d48148e7f9c32c6c9963728ef5f871ad2"},"previous_names":[],"tags_count":54,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lemunozm%2Fmessage-io","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lemunozm%2Fmessage-io/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lemunozm%2Fmessage-io/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lemunozm%2Fmessage-io/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/lemunozm","download_url":"https://codeload.github.com/lemunozm/message-io/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":253778173,"owners_count":21962822,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","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":["actor-model","actor-system","asynchronous","event-driven","event-driven-architecture","event-manager","events","message-driven","message-queue","multicast","network","network-programming","non-blocking","sockets","tcp","tcp-server","transport","udp","udp-server","websocket"],"created_at":"2024-07-31T23:00:52.516Z","updated_at":"2025-05-13T22:07:04.349Z","avatar_url":"https://github.com/lemunozm.png","language":"Rust","readme":"[![](https://img.shields.io/crates/v/message-io)](https://crates.io/crates/message-io)\n[![](https://img.shields.io/docsrs/message-io)](https://docs.rs/message-io)\n[![](https://img.shields.io/crates/l/message-io)](https://www.apache.org/licenses/LICENSE-2.0.txt)\n[![](https://img.shields.io/crates/d/message-io)](https://crates.io/crates/message-io)\n[![](https://img.shields.io/github/actions/workflow/status/lemunozm/message-io/.github/workflows/rust.yml?branch=master)](https://github.com/lemunozm/message-io/actions?query=workflow%3A%22message-io+ci%22)\n[![](https://img.shields.io/badge/buymeacoffee-donate-yellow)](https://www.buymeacoffee.com/lemunozm)\n\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"docs/images/message-io-title.png\" title=\"message-io\"\u003e\n\u003c/p\u003e\n\n`message-io` is a fast and easy-to-use event-driven network library.\nThe library handles the OS socket internally and offers a simple event message API to the user.\nIt also allows you to make an adapter for your own transport protocol following some\n[rules](#custom-adapter), delegating the tedious asynchrony and thread management to the library.\n\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"https://docs.google.com/drawings/d/e/2PACX-1vSPmycMsWoQq60MPEODcakFQVPkDwVy98AnduTswFNPGBB5dpbIsSCHHBhS2iEuSUtbVaYQb7zgfgjO/pub?w=653\u0026h=305\" width=\"653\"/\u003e\n\u003c/p\u003e\n\nIf you find a problem using the library or you have an idea to improve it,\ndo not hesitate to open an issue. **Any contribution is welcome!**\nAnd remember: more [caffeine](https://www.buymeacoffee.com/lemunozm), more productive!\n\n## Motivation\nManaging sockets is hard because you need to fight with threads, concurrency, full duplex, encoding,\nIO errors that come from the OS (which are really difficult to understand in some situations), etc.\nIf you make use of *non-blocking* sockets, it adds a new layer of complexity:\nsynchronize the events that come asynchronously from the Operating System.\n\n`message-io` offers an easy way to deal with all these aforementioned problems,\nmaking them transparent for you,\nthe programmer that wants to make an application with its own problems.\nFor that, the library gives you a simple API with two concepts to understand:\n**messages** (the data you send and receive), and **endpoints** (the recipients of that data).\nThis abstraction also offers the possibility to use the same API independently\nof the transport protocol used.\nYou could change the transport of your application in literally one line.\n\n## Features\n- Highly scalable: **non-blocking sockets** that allow for the management of thousands of active connections.\n- Multiplatform: see [mio platform support](https://github.com/tokio-rs/mio#platforms).\n- Multiple transport protocols\n([docs](https://docs.rs/message-io/latest/message_io/network/enum.Transport.html)):\n  - **TCP**: stream and framed mode (to deal with messages instead of stream)\n  - **UDP**, with multicast option\n  - **WebSocket**: plain and ~~secure~~[#102](https://github.com/lemunozm/message-io/issues/102)\n  option using [tungstenite-rs](https://github.com/snapview/tungstenite-rs)\n  (`wasm` is not supported but [planned](https://github.com/lemunozm/message-io/issues/100)).\n- Custom FIFO events with timers and priority.\n- Easy, intuitive and consistent API:\n  - Follows [KISS principle](https://en.wikipedia.org/wiki/KISS_principle).\n  - Abstraction from transport layer: don't think about sockets, think about messages and endpoints.\n  - Only two main entities to use:\n    - a [`NodeHandler`](https://docs.rs/message-io/latest/message_io/node/struct.NodeHandler.html)\n    to manage all connections (connect, listen, remove, send) and signals (timers, priority).\n    - a [`NodeListener`](https://docs.rs/message-io/latest/message_io/node/struct.NodeListener.html)\n    to process all signals and events from the network.\n  - Forget concurrency problems: handle all connection and listeners from one thread:\n    \"One thread to rule them all\".\n  - Easy error handling:\n    do not deal with dark internal `std::io::Error` when sending/receiving from the network.\n- High performance (see the [benchmarks](docs/performance_benchmarks.md)):\n    - Write/read messages with zero-copy.\n    You write and read directly from the internal OS socket buffer without any copy in the middle by the library.\n    - Full duplex: simultaneous reading/writing operations over the same internal OS socket.\n- Customizable: `message-io` doesn't have the transport you need?\n  Easily add an [adapter](#custom-adapter).\n\n## Documentation\n- [API documentation](https://docs.rs/message-io/)\n- [Basic concepts](docs/basic_concepts.md)\n- [Benchmarks](docs/performance_benchmarks.md)\n- [Examples](examples):\n  - [Ping Pong](examples/ping-pong) (a simple client/server example)\n  - [Multicast](examples/multicast)\n  - [Distributed network with discovery server](examples/distributed)\n  - [File transfer](examples/file-transfer)\n- [Open Source applications](#app-list)\n\n## Getting started\nAdd to your `Cargo.toml` (all transports included by default):\n```toml\n[dependencies]\nmessage-io = \"0.19\"\n```\nIf you **only** want to use a subset of the available transport battery,\nyou can select them by their associated features `tcp`, `udp`, and `websocket`.\nFor example, in order to include only *TCP* and *UDP*, add to your `Cargo.toml`:\n```toml\n[dependencies]\nmessage-io = { version = \"0.19\", default-features = false, features = [\"tcp\", \"udp\"] }\n```\n\n### All in one: TCP, UDP and WebSocket echo server\nThe following example is the simplest server that reads messages from the clients and responds\nto them with the same message.\nIt is able to offer the \"service\" for 3 differents protocols at the same time.\n\n```rust,no_run\nuse message_io::node::{self};\nuse message_io::network::{NetEvent, Transport};\n\nfn main() {\n    // Create a node, the main message-io entity. It is divided in 2 parts:\n    // The 'handler', used to make actions (connect, send messages, signals, stop the node...)\n    // The 'listener', used to read events from the network or signals.\n    let (handler, listener) = node::split::\u003c()\u003e();\n\n    // Listen for TCP, UDP and WebSocket messages at the same time.\n    handler.network().listen(Transport::FramedTcp, \"0.0.0.0:3042\").unwrap();\n    handler.network().listen(Transport::Udp, \"0.0.0.0:3043\").unwrap();\n    handler.network().listen(Transport::Ws, \"0.0.0.0:3044\").unwrap();\n\n    // Read incoming network events.\n    listener.for_each(move |event| match event.network() {\n        NetEvent::Connected(_, _) =\u003e unreachable!(), // Used for explicit connections.\n        NetEvent::Accepted(_endpoint, _listener) =\u003e println!(\"Client connected\"), // Tcp or Ws\n        NetEvent::Message(endpoint, data) =\u003e {\n            println!(\"Received: {}\", String::from_utf8_lossy(data));\n            handler.network().send(endpoint, data);\n        },\n        NetEvent::Disconnected(_endpoint) =\u003e println!(\"Client disconnected\"), //Tcp or Ws\n    });\n}\n```\n\n### Echo client\nThe following example shows a client that can connect to the previous server.\nIt sends a message each second to the server and listen its echo response.\nChanging the `Transport::FramedTcp` to `Udp` or `Ws` will change the underlying transport used.\n\n```rust,no_run\nuse message_io::node::{self, NodeEvent};\nuse message_io::network::{NetEvent, Transport};\nuse std::time::Duration;\n\nenum Signal {\n    Greet,\n    // Any other app event here.\n}\n\nfn main() {\n    let (handler, listener) = node::split();\n\n    // You can change the transport to Udp or Ws (WebSocket).\n    let (server, _) = handler.network().connect(Transport::FramedTcp, \"127.0.0.1:3042\").unwrap();\n\n    listener.for_each(move |event| match event {\n        NodeEvent::Network(net_event) =\u003e match net_event {\n            NetEvent::Connected(_endpoint, _ok) =\u003e handler.signals().send(Signal::Greet),\n            NetEvent::Accepted(_, _) =\u003e unreachable!(), // Only generated by listening\n            NetEvent::Message(_endpoint, data) =\u003e {\n                println!(\"Received: {}\", String::from_utf8_lossy(data));\n            },\n            NetEvent::Disconnected(_endpoint) =\u003e (),\n        }\n        NodeEvent::Signal(signal) =\u003e match signal {\n            Signal::Greet =\u003e { // computed every second\n                handler.network().send(server, \"Hello server!\".as_bytes());\n                handler.signals().send_with_timer(Signal::Greet, Duration::from_secs(1));\n            }\n        }\n    });\n}\n```\n\n### Test it yourself!\nClone the repository and test the *Ping Pong* example\n(similar to the *README* example but more vitaminized).\n\nRun the server:\n```sh\ncargo run --example ping-pong server tcp 3456\n```\nRun the client:\n```sh\ncargo run --example ping-pong client tcp 127.0.0.1:3456\n```\n\nYou can play with it by changing the transport, running several clients, disconnecting them, etc.\nSee more [here](examples/ping-pong).\n\n## Do you need a transport protocol that `message-io` doesn't have? Add an adapter! \u003cspan id=\"custom-adapter\"/\u003e\n\n`message-io` offers two *kinds* of API.\nThe **user API** that talks to `message-io` itself as a user of the library,\nand the internal **adapter API** for those who want to add their protocol adapters into the library.\n\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"https://docs.google.com/drawings/d/e/2PACX-1vRMwZsL8Tki3Sq9Zc2hpZ8L3bJPuj38zgiMKzBCXsX3wrPnfyG2hp-ijmDFUPqicEQZFeyUFxhcdJMB/pub?w=546\u0026h=276\"/\u003e\n\u003c/p\u003e\n\nIf a transport protocol can be built in top of [`mio`](https://github.com/tokio-rs/mio)\n(most of the existing protocol libraries can), then you can add it to `message-io` **really easily**:\n\n1. Add your *adapter* file in `src/adapters/\u003cmy-transport-protocol\u003e.rs` that implements the\n  traits that you find [here](https://docs.rs/message-io/latest/message_io/network/adapter/index.html).\n  It contains only 8 mandatory functions to implement (see the [template](src/adapters/template.rs)),\n  and it takes arround 150 lines to implement an adapter.\n\n1. Add a new field in the `Transport` enum found in\n[src/network/transport.rs](src/network/transport.rs) to register your new adapter.\n\nThat's all.\nYou can use your new transport with the `message-io` API like any other.\n\nOops! one more step: make a *Pull Request* so everyone can use it :)\n\n## Open source projects using `message-io` \u003cspan id=\"app-list\"/\u003e\n- [Termchat](https://github.com/lemunozm/termchat) Terminal chat through the LAN with video streaming and file transfer.\n- [Egregoria](https://github.com/Uriopass/Egregoria) Contemplative society simulation.\n- [Project-Midas](https://github.com/ray33ee/Project-Midas) Distributed network based parallel computing system.\n- [AsciiArena](https://github.com/lemunozm/asciiarena) Terminal multiplayer death match game (alpha).\n- [LanChat](https://github.com/sigmaSd/LanChat) LanChat flutter + rust demo.\n\n*Does your awesome project use `message-io`? Make a Pull Request and add it to the list!*\n\n## Is message-io for me?\n`message-io` has the main goal to keep things simple.\nThis is great, but sometimes this point of view could make more complex the already complex things.\n\nFor instance, `message-io` allows handling asynchronous network events without using an `async/await` pattern.\nIt reduces the complexity to handle income messages from the network, which is great.\nNevertheless, the applications that read asynchronous messages tend to perform\nasynchronous tasks over these events too.\nThis asynchronous inheritance can easily be propagated to your entire application\nbeing difficult to maintain or scale without an async/await pattern.\nIn those cases, maybe [`tokio`](https://tokio.rs) could be a better option.\nYou need to deal with more low-level network stuff but you gain in organization and thread/resource management.\n\nA similar issue can happen regarding the node usage of `message-io`.\nBecause a node can be used independently as a client/server or both,\nyou can easily start to make peer to peer applications.\nIn fact, this is one of the intentions of `message-io`.\nNevertheless, if your goal scales, will appear problems related to this patter to deal with,\nand libraries such as [`libp2p`](https://libp2p.io) come with a huge battery of tools to help to archive that goal.\n\nOf course, this is not a disclaiming about the library usage (I use it!),\nit is more about being honest about its capabilities,\nand to guide you to the right tool depending on what are you looking for.\n\nTo summarize:\n\n- If you have a medium complex network problem: make it simpler with `message-io`!\n- If you have a really complex network problem: use\n  [`tokio`](https://tokio.rs), [`libp2p`](https://libp2p.io) or others, to have more control over it.\n","funding_links":["https://www.buymeacoffee.com/lemunozm"],"categories":["Libraries","Rust","库 Libraries"],"sub_categories":["Network programming","网络编程 Network programming"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flemunozm%2Fmessage-io","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Flemunozm%2Fmessage-io","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flemunozm%2Fmessage-io/lists"}