我想做的事:
...编写一个(1)个服务器/(N)个客户端(网络游戏)架构,它使用 UDP 套接字作为通信的底层基础。
消息发送为,通过(crate)
Vec<u8>
编码bincode
我还希望能够偶尔发送可能超过
MTU
~ 的典型最大值的数据报,1500 bytes
并在接收端正确组装,包括发送ack
-messages 等。(我假设我必须自己实现,对吧?)
对于UdpSocket
我想过使用tokio
的实现,也许framed
。我不确定这是否是一个不错的选择,因为这似乎会引入一个不必要的映射步骤Vec<u8>
(由 序列化bincode
)到Vec<u8>
(由 需要UdpCodec
)tokio
(?)
考虑这个最小的代码示例:
Cargo.toml (服务器)
bincode = "1.0"
futures = "0.1"
tokio-core = "^0.1"
(Serde
并且serde-derive
用于shared
定义协议的 crate 中!)
(我想尽快tokio-core
更换tokio
)
fn main() -> () {
let addr = format!("127.0.0.1:{port}", port = 8080);
let addr = addr.parse::<SocketAddr>().expect(&format!("Couldn't create valid SocketAddress out of {}", addr));
let mut core = Core::new().unwrap();
let handle = core.handle();
let socket = UdpSocket::bind(&addr, &handle).expect(&format!("Couldn't bind socket to address {}", addr));
let udp_future = socket.framed(MyCodec {}).for_each(|(addr, data)| {
socket.send_to(&data, &addr); // Just echo back the data
Ok(())
});
core.run(udp_future).unwrap();
}
struct MyCodec;
impl UdpCodec for MyCodec {
type In = (SocketAddr, Vec<u8>);
type Out = (SocketAddr, Vec<u8>);
fn decode(&mut self, src: &SocketAddr, buf: &[u8]) -> io::Result<Self::In> {
Ok((*src, buf.to_vec()))
}
fn encode(&mut self, msg: Self::Out, buf: &mut Vec<u8>) -> SocketAddr {
let (addr, mut data) = msg;
buf.append(&mut data);
addr
}
}
这里的问题是:
let udp_future = socket.framed(MyCodec {}).for_each(|(addr, data)| { | ------ 移到这里的值 ^^^^^^^^^^^^^ 之后捕获到这里的值move | = 注意: move 发生是因为
socket
有 typetokio_core::net::UdpSocket
,它没有实现Copy
trait
该错误完全有道理,但我不确定如何创建如此简单的回显服务。实际上,消息的处理涉及到更多的逻辑,但为了一个最小的例子,这应该足以给出一个粗略的想法。
我的解决方法是一个丑陋的黑客:创建第二个套接字。