mnet
English | 简体中文
可靠的 UDP 传输层,连接在切换网络 / 出口 IP 变化时不断开(类似 mosh)。
提供纯 Ruby ARQ 引擎,以及基于 kcp gem 的 C 引擎。
想了解内部实现原理(包结构、数据传输、切网不断连)见 DESIGN.md。
特性
- 切网不断连:会话用 128-bit token 标识(而非 TCP 的源地址四元组),源地址变化时对端自动更新指向
- 端口跳变:mosh 式
hop,旧 socket 保留 60s 收延迟包 - 可选加密:每包 AES-256-GCM(
key,需预共享) - 两种引擎:
proto: :mnet(纯 Ruby,无 C 依赖)/proto: :kcp(C 引擎,快) - 流式会话:
Mnet::Session实现 IO 兼容接口(read / write / readpartial / wait_readable),可直接被OpenSSL::SSL::SSLSocket包装 - 跨平台:纯 Ruby 部分天然跨平台,KCP 由
kcpgem 提供原生扩展
安装
# Gemfile
gem 'mnet'
快速开始
require 'mnet'
# ---- 服务端(回显)----
server = Mnet::Server.new('0.0.0.0', 9000)
loop do
io = server.accept_session
Thread.new { while (d = io.readpartial(65_536)); io.write(d); end }
end
# ---- 客户端 ----
endpoint = Mnet::Endpoint.new
sess = endpoint.dial('127.0.0.1', 9000, proto: :kcp) # :mnet 或 :kcp
sess.write('hello')
puts sess.readpartial(1024)
引擎选择
proto |
说明 |
|---|---|
:mnet |
纯 Ruby ARQ,无 C 依赖,简单、易调试 |
:kcp |
C 引擎(依赖 kcp gem),快约 8 倍,需编译原生扩展 |
proto: :kcp时,mnet 会自动把 KCP 引擎的 MTU 设为IP_MTU(1280) - Mnet 头(41) - 加密开销(28,仅启用 key 时), 使「Mnet 头 + KCP 包(+ 加密)」整包不超过链路 MTU,避免 IP 分片。 如需自定义可用kcp_mtu:选项覆盖。
加密(预共享密钥)
每包 AES-256-GCM,两端需预共享同一个 32 字节密钥:
require 'securerandom'
key = SecureRandom.random_bytes(32)
# 服务端注册密钥(可注册多个)
server = Mnet::Server.new('0.0.0.0', 9000, keys: [key])
# 客户端带密钥拨号
sess = endpoint.dial('127.0.0.1', 9000, proto: :kcp, key: key)
会话 ID 由密钥派生(SHA256(key)[0,16]);密钥不对时服务端解密失败、直接丢弃包,客户端连不上。
TLS(嵌套)
Mnet::Session 实现了 IO 兼容接口,可被 SSLSocket 直接包装(SSLServer 写法兼容):
require 'openssl'
server = Mnet::Server.new('0.0.0.0', 9001)
ssl_server = OpenSSL::SSL::SSLServer.new(server, ssl_context)
ssl_server.start_immediately = false # 把握手放到工作线程,不阻塞 accept
loop do
ssl_sock = ssl_server.accept
Thread.new do
ssl_sock.accept
# ...读写 ssl_sock...
end
end
切网迁移
endpoint.hop # 模拟切网(真实场景下客户端绑 0.0.0.0,内核自动换源地址,无需手动 hop)
基准测试
环境:loopback(127.0.0.1),pipelined echo(写端与读端并发,按总字节计)。
| 方案 | 1KB 消息吞吐 |
|---|---|
| TCP(裸) | ~49 MB/s |
| TCP + SSL | ~22 MB/s |
mnet 纯 Ruby(proto: :mnet) |
~1.8 MB/s |
| mnet 纯 Ruby + key(AES-GCM) | ~1.6 MB/s |
mnet + KCP(proto: :kcp) |
~5.0 MB/s |
| mnet + KCP + key(AES-GCM) | ~4.1 MB/s |
结论:
- KCP 引擎比纯 Ruby 快约 2.7 倍(5.0 vs 1.8 MB/s)
- 加密开销很小:
key(每包 AES-GCM)只慢 ~15~18% - 明文 KCP 约为 TCP 的 1/10;瓶颈在 Ruby 层的每包 glue(pack/unpack + 线程切换),不在 ARQ 算法
- 以上是 loopback 合成基准;真实网络延迟主导时,交互式(小消息)体感无差别
复现:ruby -I lib -I ../kcp/lib test/bench_compare.rb [消息数] [消息字节]
许可
MIT。