lemunozm / message-io

Fast and easy-to-use event-driven network library.
Apache License 2.0
1.12k stars 75 forks source link

non-blocking connections #79

Closed lemunozm closed 3 years ago

lemunozm commented 3 years ago

Currently, the connect() method performs a connection in a blocking way. For many basic use cases, this is even preferred to an async connection, since it allows you to configure the returned Endpoint easily before listening to any event.

Currently, the blocking way:

let (node, listener) = node::split();
// This function waits until the connection is finished
let (endpoint, local_addr) = node.connect(Transport::FramedTcp, "123.4.5.6:1234")?; 
// The user could decide some logic in base of the connection result before call listener.for_each
listener.for_each(|event| match event.network() {
    NetEvent::Connected(endpoint, listener_id) => { /* */ }
    NetEvent::Message(endpoint, data) => { /* */ }
    NetEvent::Disconnected(endpoint) => { /* */ }
});

Nevertheless, the user could not want to wait for that connection and do other stuff in the meantime. In this case, we need an asynchronous connection. This also implies a new NetEvent to notify that the connection has been established or not. The propossed method:

let (node, listener) = node::split();
// This function NOT wait until the connection is finished
let local_addr = node.connect(Transport::FramedTcp, "123.4.5.6:1234")?; //Now works asynchonously
listener.for_each(|event| match event.network() {
    NetEvent::Connected(endpoint, established) => { /* connection succesful or not*/ }
    NetEvent::Accepted(endpoint, listener_id) => { /* used for listenings */ }
    NetEvent::Message(endpoint, data) => { /* */ }
    NetEvent::Disconnected(endpoint) => { /* */ }
});

The proposed way will split the NetEvent::Connected into Connected and Accepted. This is due to two reasons:

  1. The Accepted event (that is the previous Connected) contains the listener_id of the listen that accepted that connection, which does not exist when the user explicitly creates the connection. Both events offer different things.
  2. Adds clarity to the reader and the API is more symmetric: Connected for connect, Accepted for listen