message-io
是一個快速且易於使用的事件驅動網路庫。該庫在內部處理作業系統套接字,並向使用者提供簡單的事件訊息 API。它還允許您遵循一些規則為您自己的傳輸協定建立適配器,將繁瑣的非同步和線程管理委託給庫。
如果您在使用該庫時發現問題或您有改進它的想法,請隨時提出問題。歡迎任何貢獻!請記住:咖啡因越多,工作效率越高!
管理套接字很困難,因為您需要應對線程、並發、全雙工、編碼、來自作業系統的 IO 錯誤(在某些情況下確實很難理解)等。增加了新的複雜度:同步來自作業系統的非同步事件。
message-io
提供了一種簡單的方法來處理所有上述問題,使它們對您(想要創建具有自己的問題的應用程式)的程式設計師來說是透明的。為此,該程式庫為您提供了一個簡單的 API,其中包含兩個需要理解的概念:訊息(您發送和接收的資料)和端點(該資料的接收者)。這種抽象化也提供了獨立於所使用的傳輸協定而使用相同 API 的可能性。您可以在一行中變更應用程式的傳輸。
wasm
但已計劃)。NodeHandler
來管理所有連接(連接、監聽、刪除、發送)和訊號(計時器、優先權)。NodeListener
用於處理來自網路的所有訊號和事件。std::io::Error
。message-io
沒有您需要的傳輸?輕鬆添加適配器。 新增到您的Cargo.toml
(預設包含所有運輸):
[ dependencies ]
message-io = " 0.18 "
如果您只想使用可用傳輸電池的子集,則可以透過其關聯功能tcp
、 udp
和websocket
來選擇它們。例如,為了僅包含TCP和UDP ,請新增至您的Cargo.toml
:
[ dependencies ]
message-io = { version = " 0.18 " , default-features = false , features = [ " tcp " , " udp " ] }
以下範例是最簡單的伺服器,它從客戶端讀取訊息並使用相同的訊息回應它們。它能夠同時為3種不同的協定提供「服務」。
use message_io :: node :: { self } ;
use message_io :: network :: { NetEvent , Transport } ;
fn main ( ) {
// Create a node, the main message-io entity. It is divided in 2 parts:
// The 'handler', used to make actions (connect, send messages, signals, stop the node...)
// The 'listener', used to read events from the network or signals.
let ( handler , listener ) = node :: split :: < ( ) > ( ) ;
// Listen for TCP, UDP and WebSocket messages at the same time.
handler . network ( ) . listen ( Transport :: FramedTcp , "0.0.0.0:3042" ) . unwrap ( ) ;
handler . network ( ) . listen ( Transport :: Udp , "0.0.0.0:3043" ) . unwrap ( ) ;
handler . network ( ) . listen ( Transport :: Ws , "0.0.0.0:3044" ) . unwrap ( ) ;
// Read incoming network events.
listener . for_each ( move |event| match event . network ( ) {
NetEvent :: Connected ( _ , _ ) => unreachable ! ( ) , // Used for explicit connections.
NetEvent :: Accepted ( _endpoint , _listener ) => println ! ( "Client connected" ) , // Tcp or Ws
NetEvent :: Message ( endpoint , data ) => {
println ! ( "Received: {}" , String :: from_utf8_lossy ( data ) ) ;
handler . network ( ) . send ( endpoint , data ) ;
} ,
NetEvent :: Disconnected ( _endpoint ) => println ! ( "Client disconnected" ) , //Tcp or Ws
} ) ;
}
以下範例顯示了可以連接到先前伺服器的用戶端。它每秒向伺服器發送一條訊息並監聽其回顯回應。將Transport::FramedTcp
變更為Udp
或Ws
將變更使用的底層傳輸。
use message_io :: node :: { self , NodeEvent } ;
use message_io :: network :: { NetEvent , Transport } ;
use std :: time :: Duration ;
enum Signal {
Greet ,
// Any other app event here.
}
fn main ( ) {
let ( handler , listener ) = node :: split ( ) ;
// You can change the transport to Udp or Ws (WebSocket).
let ( server , _ ) = handler . network ( ) . connect ( Transport :: FramedTcp , "127.0.0.1:3042" ) . unwrap ( ) ;
listener . for_each ( move |event| match event {
NodeEvent :: Network ( net_event ) => match net_event {
NetEvent :: Connected ( _endpoint , _ok ) => handler . signals ( ) . send ( Signal :: Greet ) ,
NetEvent :: Accepted ( _ , _ ) => unreachable ! ( ) , // Only generated by listening
NetEvent :: Message ( _endpoint , data ) => {
println ! ( "Received: {}" , String :: from_utf8_lossy ( data ) ) ;
} ,
NetEvent :: Disconnected ( _endpoint ) => ( ) ,
}
NodeEvent :: Signal ( signal ) => match signal {
Signal :: Greet => { // computed every second
handler . network ( ) . send ( server , "Hello server!" . as_bytes ( ) ) ;
handler . signals ( ) . send_with_timer ( Signal :: Greet , Duration :: from_secs ( 1 ) ) ;
}
}
} ) ;
}
克隆儲存庫並測試Ping Pong範例(類似README範例,但更豐富)。
運行伺服器:
cargo run --example ping-pong server tcp 3456
運行客戶端:
cargo run --example ping-pong client tcp 127.0.0.1:3456
您可以透過更改傳輸、運行多個客戶端、斷開它們的連接等來使用它。
message-io
沒有的傳輸協定?添加適配器! message-io
提供兩種API。作為庫用戶與message-io
本身進行對話的用戶 API ,以及那些想要將其協定適配器新增至庫中的內部適配器 API 。
如果可以在mio
之上建立傳輸協定(大多數現有協定庫都可以),那麼您可以非常輕鬆地將其添加到message-io
:
在src/adapters/<my-transport-protocol>.rs
中新增適配器文件,以實現您在此處找到的特徵。它只包含 8 個需要實現的強制函數(請參閱模板),並且需要大約 150 行程式碼來實作一個適配器。
在 src/network/transport.rs 中的Transport
枚舉中新增一個欄位來註冊您的新適配器。
就這樣。您可以像其他傳輸一樣將新傳輸與message-io
API 一起使用。
哎呀!另一步:發出Pull 請求,以便每個人都可以使用它:)
message-io
開源項目您出色的專案使用message-io
嗎?發出拉取請求並將其添加到清單中!
message-io
主要目標是讓事情變得簡單。這很好,但有時這種觀點可能會使本來就複雜的事情變得更加複雜。
例如, message-io
允許在不使用async/await
模式的情況下處理非同步網路事件。它降低了處理來自網路的收入訊息的複雜性,這很棒。然而,讀取非同步訊息的應用程式也傾向於對這些事件執行非同步任務。這種非同步繼承可以輕鬆傳播到整個應用程序,如果沒有非同步/等待模式,則很難維護或擴展。在這種情況下,也許tokio
可能是更好的選擇。您需要處理更多低階網路內容,但您會在組織和執行緒/資源管理方面有所收穫。
關於message-io
的節點使用,可能會發生類似的問題。由於節點可以獨立用作客戶端/伺服器或兩者,因此您可以輕鬆地開始製作對等應用程式。其實這也是message-io
的意圖之一。然而,如果您的目標規模較大,就會出現與此模式相關的問題需要處理,而libp2p
等函式庫附帶了大量工具來幫助實現該目標。
當然,這並不是對庫使用的免責聲明(我使用它!),更多的是誠實地了解其功能,並根據您的需求引導您使用正確的工具。
總結一下:
message-io
讓問題變得更簡單!tokio
、 libp2p
或其他,以更好地控制它。