3 个版本 (重大更新)
0.3.0 | 2024年7月8日 |
---|---|
0.2.0 | 2024年6月26日 |
0.1.0 | 2024年6月25日 |
#1087 在 网络编程
每月下载量 39
用于 warqueen_derive
44KB
550 行
Warqueen - 业余规模的网络 crate
基于消息,非异步,非阻塞。使用优秀的 Quinn 网络crate。
作为客户端,只需连接,发送消息,并在任何时候轮询接收到的消息,以非阻塞的方式,无需异步。作为服务器,同样的操作,并在任何时候轮询新的客户端连接。可以在几个循环中完成这些操作,API非常简单,易于理解和使用。
消息类型仅限于发送时可能的一个类型和接收时可能的一个类型,服务器和客户端交换这些类型角色。自然地,两者都使用枚举。
希望你喜欢 :3
用法
让我们从客户端开始。
首先定义两种消息类型,用于与服务器通信。客户端可以发送(到服务器)的类型和客户端可以接收(从服务器)的类型。
use serde::{Deserialize, Serialize};
use warqueen::{NetReceive, NetSend};
#[derive(Serialize, NetSend)]
enum MessageClientToServer {
String(String),
}
#[derive(Deserialize, NetReceive)]
enum MessageServerToClient {
String(String),
}
NetSend
和 NetReceive
derive 宏实现了同名的特质,允许标记的类型分别发送和接收。
然后创建 ClientNetworking
以连接到服务器,并在循环中使用它。
// Full type is `ClientNetworking<MessageClientToServer, MessageServerToClient>`.
let mut client = ClientNetworking::new(server_address);
loop {
// Handling received messages from the server, as well as connection events.
while let Some(event) = client.poll_event_from_server() {
match event {
ClientEvent::Message(message) => match message {
MessageServerToClient::String(content) => println!("The server says \"{content}\""),
},
ClientEvent::Connected => println!("Connected"),
ClientEvent::Disconnected => println!("Disconnected"),
}
}
// Sending a message to the server.
let message = MessageClientToServer::String("hiii :3".to_string());
client.send_message_to_server(message);*
sleep(Duration::from_millis(10));
}
请注意,连接不会立即建立,可能需要一些时间,当最终建立时,会有一个 ClientEvent::Connected
事件轮询以通知客户端。如果连接始终未建立,则不会轮询此类事件;在这种情况下,超时错误可能是相关的。
当是时候离开时,可以按如下方式正确关闭连接。
client.disconnect().wait_for_proper_disconnection();
请注意,如果 ClientNetworking::disconnect
调用不在主线程中,则返回的 DisconnectionHandle
应传递到主线程(例如通过通道),然后才应调用 DisconnectionHandle::wait_for_proper_disconnection
。有关更多信息,请参阅文档。
服务器非常相似,它应该使用与客户端相同的信息类型,除了使用特性 NetSend
和 NetReceive
实现相反(因为服务器发送时客户端接收,反之亦然)(只需交换 derive,包括 serde)。如果服务器和客户端使用相同类型定义,那就更好了:两种类型都可以实现这两种特性(#[derive(Serialize, Deserialize, NetSend, NetReceived)]
)。
然后创建 ServerListenerNetworking
,用于监听想要连接的新客户端,并在循环中使用它。
// Full type is `ServerListenerNetworking<MessageServerToClient, MessageClientToServer>`.
let server_listener = ServerListenerNetworking::new(desired_port);
let mut clients = vec![];
loop {
// Handling new clients connections.
while let Some(client) = server_listener.poll_client() {
// Client type is `ClientOnServerNetworking<MessageServerToClient, MessageClientToServer>`.
println!("Connected to a client at {}", client.client_address());
clients.push(client);
}
// Handling clients...
sleep(Duration::from_millis(10));
}
从 ServerListenerNetworking::poll_client
查询的客户端类型为 ClientOnServerNetworking
,基本上是 ClientNetworking
的服务器端等效物。在客户端程序中,对于每个连接的 ClientNetworking
,服务器程序中都有一个相应的 ClientOnServerNetworking
。
// Handling received messages as well as connection events from all clients.
for (index, client) in clients.iter().enumerate() {
while let Some(event) = client.poll_event_from_client() {
match event {
ClientOnServerEvent::Message(message) => match message {
MessageClientToServer::String(content) => {
println!("Client {index} says \"{content}\"");
},
},
ClientOnServerEvent::Disconnected => {
println!("Client {index} disconnected");
},
}
}
}
// Sending a message to a client.
let message = MessageServerToClient::String("nyaa~".to_string());
clients[some_index_whatever].send_message_to_client(message);
注意,服务器端 ClientEvent::Connected
事件的等效是 ServerListenerNetworking::poll_client
返回一个连接到客户端,不需要 ClientOnServerEvent::Connected
,因为 ClientOnServerNetworking
在创建时已经连接到客户端。
断开连接与客户端相同,它还带有 DisconnectionHandle
(对于每次断开连接),以便在不在主线程上断开连接时特别小心地将它带到主线程。
clients[some_index_whatever].disconnect().wait_for_proper_disconnection();
缩放
业余级别!只是一个围绕 Quinn(最佳 Rust 网络库?)的小包装,以获得我喜欢的 API。它可能适合游戏网络,希望如此!至少我在我的游戏中使用它。
请参阅 待办事项列表 以获取潜在的未来功能。也欢迎贡献力量!
请注意,任何有意提交以供您在 Apache-2.0 许可证定义的工作中包含的贡献,都应按以下方式双授权,没有任何附加条款或条件。
许可证
版权 2024 Jeanne DEMOUSSEL。
本项目受以下任一许可证的许可:
任选其一。
依赖项
~14–24MB
~437K SLoC