Skip to content

Commit 20f56fc

Browse files
committed
Added README
1 parent 626470a commit 20f56fc

File tree

4 files changed

+184
-6
lines changed

4 files changed

+184
-6
lines changed

Cargo.toml

+8-1
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,17 @@ name = "message-io"
33
version = "0.1.0"
44
authors = ["lemunozm <[email protected]>"]
55
edition = "2018"
6+
readme = "README.md"
7+
license = "Apache-2.0"
8+
description = "Easy asynchronous network message library"
9+
homepage = "https://github.com/lemunozm/message-io/"
10+
repository = "https://github.com/lemunozm/message-io/"
11+
keywords = ["network", "message", "asynchronous", "events"]
12+
categories = ["asynchronous", "game-development", "network-programming"]
13+
maintenance = "actively-developed"
614

715
[dependencies]
816
mio = { version = "0.7", features = ["os-poll", "tcp", "udp"] }
917
serde = { version = "1.0", features = ["derive"] }
1018
bincode = "1.3.1"
1119
crossbeam-channel = "0.4.2"
12-

README.md

+127
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
[![message-io](https://img.shields.io/crates/v/message-io)](https://crates.io/crates/message-io)
2+
[![license](https://img.shields.io/crates/l/message-io)](https://www.apache.org/licenses/LICENSE-2.0.txt)
3+
[![downloads](https://img.shields.io/crates/d/message-io)](https://crates.io/crates/message-io)
4+
5+
# `message-io`
6+
`message-io` is an asynchronous network message library for building clients and servers.
7+
This library offers an event-based API over an abstraction network transport layer.
8+
9+
This library can be used but it is still growing, so if you see any bug or strange behaviour, please put an issue!
10+
Of course, any contribution is welcome!
11+
12+
## For who is this project?
13+
- People who want to make an application that needs to communicate over tcp/udp protocols.
14+
- People who want to make a multiplayer game (server and/or client).
15+
- People who don't want to deal with concurrence or socket connection problems.
16+
- People who want to push the effort in the messages among the apps, not in how to transport them.
17+
18+
## Features
19+
- Asynchronous: internal poll event with non-blocking sockets.
20+
- Really easy API:
21+
- Abstraction from transport layer: Do not thinks about sockets, only thing about data messages.
22+
- Only two main entities: an extensible event-queue to manage all events.
23+
and a network manager to manage the connections, and send/receive data.
24+
- Forget concurrence problem: "One thread to rule them all",
25+
- Significant performance: one thread for manage all internal conenctions over a OS poll, binary serialization, small overhead over OS sockets).
26+
27+
## Getting started
28+
Add to your `Cargo.toml`
29+
```
30+
message-io = "0.1"
31+
```
32+
33+
### Documentation
34+
- [Basic concepts](#basic-concepts)
35+
- [API documentation](https://docs.rs/message-io/)
36+
37+
### Example
38+
The following example is simplest server that reads `HelloServer` message
39+
and responses with a `HelloClient` message.
40+
It is capable to manage several client connections and listen from 2 differents ports and interfaces.
41+
42+
```rust
43+
use message_io::event_queue::{EventQueue};
44+
use message_io::network_manager::{NetworkManager, NetEvent, TransportProtocol};
45+
use serde::{Serialize, Deserialize};
46+
47+
#[derive(Serialize, Deserialize)]
48+
enum Message {
49+
HelloServer,
50+
HelloClient,
51+
// Other messages here
52+
}
53+
54+
enum Event {
55+
Network(NetEvent<Message>),
56+
// Other user events here
57+
}
58+
59+
fn main() {
60+
let mut event_queue = EventQueue::new();
61+
62+
// Create NetworkManager, the callback will push the network event into the event queue
63+
let network_sender = event_queue.sender().clone();
64+
let mut network = NetworkManager::new(move |net_event| network_sender.send(Event::Network(net_event)));
65+
66+
// Listen TCP messages at ports 3001 and 3002.
67+
network.listen("127.0.0.1:3001".parse().unwrap(), TransportProtocol::Tcp).unwrap();
68+
network.listen("0.0.0.0.0:3002".parse().unwrap(), TransportProtocol::Tcp).unwrap();
69+
70+
loop {
71+
match event_queue.receive() { // Read the next event or wait until have it.
72+
Event::Network(net_event) => match net_event {
73+
NetEvent::Message(message, endpoint) => match message {
74+
Message::HelloServer => network.send(endpoint, Message::HelloClient).unwrap(),
75+
_ => (), // Other messages here
76+
},
77+
NetEvent::AddedEndpoint(_endpoint) => println!("Client connected"),
78+
NetEvent::RemovedEndpoint(_endpoint) => println!("Client disconnected"),
79+
},
80+
// Other events here
81+
}
82+
}
83+
}
84+
```
85+
86+
## Basic concepts
87+
The library has two main pieces:
88+
89+
- **`EventQueue`**:
90+
Is a generic and synchronized queue where all the system events are sent.
91+
The user must be read these events in its main thread in order to dispatch actions.
92+
93+
<p align="center">
94+
<img src="https://docs.google.com/drawings/d/e/2PACX-1vQr06OL40IWagXWHoyytUIlR1SHoahYE0Pkj6r0HmokaUMW4ojC5MV2OViFO9m-2jDqrDokPJ62oSzg/pub?w=837&h=313"/>
95+
</p>
96+
97+
- **`NetworkManager`**:
98+
It is an abstraction layer of the transport protocols that works over non-blocking sockets.
99+
It allows to create/remove connections, send and receive messages (defined by the user).
100+
101+
To manage the connections the `NetworkManager` offers an *`Endpoint`* that is an unique identifier of the connection
102+
that can be used to remove, send or identify input messages.
103+
104+
<p align="center">
105+
<img src="https://docs.google.com/drawings/d/e/2PACX-1vS3y1BKwPHjoFqtHm2pqfmvxr0JRQIzeRJim9s2UOrOIS74cGwlyqxnH4_DHVXTverziCjPzl6FtQMe/pub?w=586&h=273"/>
106+
</p>
107+
108+
The power comes when both pieces joins together, allowing to process all actions from one thread.
109+
To reach this, the user have to connect the `NetworkManager` to the `EventQueue` sending `NetEvent` produced by the first one.
110+
111+
<p align="center">
112+
<img src="https://docs.google.com/drawings/d/e/2PACX-1vT6IuBVr4mLbdNfs2yZayqqUJ04PsuqG27Ce3Vdr0ZG8ItX3slISoKVxyndybaYPIS5oFZ6N4TljrKQ/pub?w=701&h=383"/>
113+
</p>
114+
115+
## Test yourself!
116+
Clone the repository and test the `basic`example that you can found in [`examples/basic`](examples/basic):
117+
118+
Run the server:
119+
```
120+
cargo run --example basic server [tcp/udp]
121+
```
122+
In other terminals, run one or more clients:
123+
```
124+
cargo run --example basic client [tcp/udp]
125+
```
126+
(By default, if no protocol is specified, `tcp` is used)
127+

examples/hello_world_server.rs

+41
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
use message_io::event_queue::{EventQueue};
2+
use message_io::network_manager::{NetworkManager, NetEvent, TransportProtocol};
3+
use serde::{Serialize, Deserialize};
4+
5+
#[derive(Serialize, Deserialize)]
6+
enum Message {
7+
HelloServer,
8+
HelloClient,
9+
// Other messages here
10+
}
11+
12+
enum Event {
13+
Network(NetEvent<Message>),
14+
// Other user events here
15+
}
16+
17+
fn main() {
18+
let mut event_queue = EventQueue::new();
19+
20+
// Create NetworkManager, the callback will push the network event into the event queue
21+
let network_sender = event_queue.sender().clone();
22+
let mut network = NetworkManager::new(move |net_event| network_sender.send(Event::Network(net_event)));
23+
24+
// Listen TCP messages at ports 3001 and 3002.
25+
network.listen("127.0.0.1:3001".parse().unwrap(), TransportProtocol::Tcp).unwrap();
26+
network.listen("0.0.0.0.0:3002".parse().unwrap(), TransportProtocol::Tcp).unwrap();
27+
28+
loop {
29+
match event_queue.receive() { // Read the next event or wait until have it.
30+
Event::Network(net_event) => match net_event {
31+
NetEvent::Message(message, endpoint) => match message {
32+
Message::HelloServer => network.send(endpoint, Message::HelloClient).unwrap(),
33+
_ => (), // Other messages here
34+
},
35+
NetEvent::AddedEndpoint(_endpoint) => println!("Client connected"),
36+
NetEvent::RemovedEndpoint(_endpoint) => println!("Client disconnected"),
37+
},
38+
// Other events here
39+
}
40+
}
41+
}

src/network_manager.rs

+8-5
Original file line numberDiff line numberDiff line change
@@ -23,14 +23,17 @@ pub enum TransportProtocol {
2323
/// Input network events.
2424
pub enum NetEvent<InMessage>
2525
where InMessage: for<'b> Deserialize<'b> + Send + 'static {
26-
// Input message received by the network.
26+
/// Input message received by the network.
2727
Message(InMessage, Endpoint),
2828

29-
// New endpoint added to a listener.
29+
/// New endpoint added to a listener.
30+
/// In TCP it will be sent when a new connection was accepted by the listener.
31+
/// IN UDP will be sent when the socket send data by first time, before the Message event.
3032
AddedEndpoint(Endpoint),
3133

32-
// A connection lost event.
33-
// This event is only dispatched when a connection is lost, [remove_endpoint()] not generate any event.
34+
/// A connection lost event.
35+
/// This event is only dispatched when a connection is lost, `remove_endpoint()` not generate the event.
36+
/// This event will be sent only in TCP. Because UDP is not connection oriented, this event can no be detected
3437
RemovedEndpoint(Endpoint),
3538
}
3639

@@ -136,7 +139,7 @@ impl<'a> NetworkManager {
136139
}
137140

138141
/// Serialize and send the message thought the connections represented by the given endpoints.
139-
/// When there are severals endpoints to send the data. It is better to call this function instead of several calls to send,
142+
/// When there are severals endpoints to send the data. It is better to call this function instead of several calls to `send()`,
140143
/// because the serialization only is performed one time for all the endpoints.
141144
/// An Err with the unrecognized ids is returned.
142145
pub fn send_all<'b, OutMessage>(&mut self, endpoints: impl IntoIterator<Item=&'b Endpoint>, message: OutMessage) -> Result<(), Vec<Endpoint>>

0 commit comments

Comments
 (0)