我的服务使用套接字通信收集和显示一些统计信息。一些客户端通过使用WebSocket协议的Web浏览器连接到它,而其他客户端使用使用常规套接字的Windows服务。
我已经以这种方式创建了一个侦听端口:
let on = "0.0.0.0:8081";
let server = std::net::TcpListener::bind(on)?;
while let Ok((stream, _)) = server.accept() {
let peer_adr = stream.peer_addr().unwrap();
if peer_adr.to_string().starts_with("127.0.0") {
// socket
} else {
// web socket
let ws = tungstenite::accept(stream)?;
}
}
字符串
我已经尝试了IP检查来检测客户端的类型,这对于生产是不可接受的。
我的问题是:
1.是否有更好的实施方案?
1.是否有任何标准方法来检测每个传入流的类型?(类似于stream.protocol.start_with("ws")
)
环境
Rust version: `1.74 - stable`
Extra crate: `tungstenite = { version = "0.20" }`
型
2条答案
按热度按时间hsvhsicv1#
没有所谓的“传入”协议。它是一个应用程序协议,有无数这样的协议。虽然许多开始与客户端发送数据(如HTTP、SIP等)其他应用程序则希望服务器发送第一个应用程序数据(如SMTP,FTP,IMAP,这意味着处理任意的应用程序协议,不能只监听传入的数据,因为如果客户端期望对等端首先开始发送,则不会有数据传入。
除此之外,今天的许多协议在应用程序级别的传输中使用加密,通常使用TLS。(与SMTP中的STARTTLS一样)许多将直接从TLS握手开始,这开始于客户端发送ClientHello。在ClientHello中没有或几乎没有指示符,这可以区分协议-存在ALPN扩展,但这仅允许对可能的应用协议进行非常粗略的检测。
简而言之:如果您只有非常有限的一组可能的协议,那么您可以基于此有限的集合编写自定义检测器。但前提是这些协议与客户端发送的第一个数据可以清楚区分,而客户端不希望将数据发送到服务器。因此,这实际上取决于您的实际用例,并且没有涵盖所有可能协议的通用检测。
64jmpszr2#
正如Steffen所说,在TCP连接出现之前,没有办法知道客户端将要发送的应用程序数据是什么,直到它发送它(如果它甚至要发送的话)。
当你有WebSocket这样的东西介入时,你会遇到一个问题,因为WebSocket只是在使用它的应用程序和网络之间实现另一层网络堆栈的应用程序数据。对于一个使用WebSocket进行数据传输的应用程序来说,完全有可能代表一个新的应用程序类在其之上实现另一个协议层。等等。
最好的方法是,对于不同的客户端类型,提供不同的端口号供它们连接到特定的TCP或WebSocket。因此,8081可以用于TCP,8082可以用于WebSocket,等等。
这样,您可以假设连接到端口8081的客户端将传输一个简单的TCP流,连接到端口8082的客户端将传输WebSocket,并且将有额外的工作要做才能获得以这种方式传输的数据。