Loading [MathJax]/jax/input/TeX/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >专栏 >【投稿】actix-websocket 使用 protocol的一点个人理解

【投稿】actix-websocket 使用 protocol的一点个人理解

作者头像
MikeLoveRust
发布于 2021-01-07 02:19:41
发布于 2021-01-07 02:19:41
98400
代码可运行
举报
运行总次数:0
代码可运行

actix的docs和example对protocol的使用有点省略,对着源码实验了下,终于搞清楚了。

标准浏览器websocket的构造函数WebSocket(url[, protocols])会有个可选参数protocols,即一个字符串形式的约定协议。

对于actix的websocket的例子一般如下,即用actix_web_actors::ws::start来初始化websocket。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
struct MyWebSocket{}

async fn ws_index(r: HttpRequest, stream: web::Payload) -> Result<HttpResponse, Error> {
    ws::start(MyWebSocket::new(), &r, stream)
}

如果前端传了protocol,actix会响应请求然后自动关闭连接,并不能正常构建websocket连接。

这里整了我半天,后来才发现actix_web_actors::ws有一个初始函数叫start_with_protocols,必须用这个函数才能接收带有protocol的websocket连接。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
pub fn start_with_protocols<A, T>(
    actor: A,
    protocols: &[&str],
    req: &HttpRequest,
    stream: T,
) -> Result<HttpResponse, Error>
where
    A: Actor<Context = WebsocketContext<A>>
        + StreamHandler<Result<Message, ProtocolError>>,
    T: Stream<Item = Result<Bytes, PayloadError>> + 'static,
{
    let mut res = handshake_with_protocols(req, protocols)?;
    Ok(res.streaming(WebsocketContext::create(actor, stream)))
}

start_with_protocols比普通的start多了个protocols参数,试试了这个protocols其实代表的是合法的协议名列表,即前端传来的protocol必须在protocols里面才能正常构建websocket连接。

然后顺便看了start方法的源码,发现其实也调用了handshake_with_protocols这个方法,但会默认令合法协议protocols=&[],也就是置空, 这样如果前端如果没传protocol,actix处理出的protocol则为None,可以满足构建要求, 如果不为空,则必然不在合法协议列表protocols=&[]里面,所以无法正常构建websocket连接。

不过令人困惑的是,在初始化以后,如果想在websocket的帧里获取protocol是什么,并不能像在处理路由句柄时里的r: HttpRequest里面直接r.headers().get(&header::SEC_WEBSOCKET_PROTOCOL).unwrap().to_str().unwrap()获取,所以我的解决办法是在自定义的MyWebSocket结构体里进行保存。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
struct MyWebSocket {
    protocol: String
}

impl MyWebSocket {
    fn new(protocol: String) -> Self {
        Self {protocol}
    }
}

const PROTOCOLS: &[&str] = &["chat"];

async fn ws_index(r: HttpRequest, stream: web::Payload) -> Result<HttpResponse, Error> {
    let protocol = r.headers().get(&header::SEC_WEBSOCKET_PROTOCOL).unwrap().to_str().unwrap();
    ws::start_with_protocols(MyWebSocket::new(protocol.to_string()), PROTOCOLS, &r, stream)
}

这样就可以在接收流处理句柄里拿到protocol了,根据websocket的帧协议来看,似乎确实不包含protocol的信息,所以大概也只能从请求头headers那里拿到protocol信息了。本来想在ctx: &mut Self::Context里找信息的,不过看了看源码似乎并没有找到存取protocol的api,实在整不明白,只能自己存了,不知道还有没有更正统的办法。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
impl StreamHandler<Result<ws::Message, ws::ProtocolError>> for MyWebSocket {
    fn handle(
        &mut self,
        msg: Result<ws::Message, ws::ProtocolError>,
        ctx: &mut Self::Context,
    ) {

        println!("WS({}): {:?}", self.protocol, msg);

        match msg {
            Ok(ws::Message::Ping(msg)) => ctx.pong(&msg),
            Ok(ws::Message::Pong(_)) => (),
            Ok(ws::Message::Text(text)) => ctx.text(text),
            Ok(ws::Message::Binary(bin)) => ctx.binary(bin),
            Ok(ws::Message::Close(reason)) => {
                ctx.close(reason);
                ctx.stop();
            }
            _ => ctx.stop(),
        }
    }
}

总结一下,关于actix的websocket连接里获取protocol方法就是用start_with_protocols来初始化连接,通过HttpRequest.headers().get(&header::SEC_WEBSOCKET_PROTOCOL).unwrap().to_str().unwrap()来获取protocol,如果想在流处理获取protocol的信息,则需要在处理路由句柄时通过自定义结构体里提前存储protocol的信息。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2020-12-31,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Rust语言学习交流 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
你应该知晓的Rust Web 框架
在之前的用 Rust 搭建 React Server Components 的 Web 服务器我们利用了Axum构建了RSC的服务器。也算是用Rust在构建Web服务上的小试牛刀。
前端柒八九
2023/11/17
2.9K0
你应该知晓的Rust Web 框架
服务端常用的WebSocket框架
输入命令 需要修改的 url、groupId、artifactId、version
码客说
2021/01/20
1.4K0
Rust:axum学习笔记(7) websocket
核心就是handle_socket这个function,这里我们只是简单的将收到的内容,原封不动的发回浏览器。
菩提树下的杨过
2022/04/27
2.2K1
Rust:axum学习笔记(7) websocket
Python 实现 WebSocket 通信
WebSocket 协议主要用于解决Web前端与后台数据交互问题,在WebSocket技术没有被定义之前,前台与后端通信需要使用轮询的方式实现,WebSocket则是通过握手机制让客户端与服务端建立全双工通信,从而实现了更多复杂的业务需求。
王瑞MVP
2022/12/28
1.9K0
开源的C#实现WebSocket协议客户端和服务器websocket-sharp组件解析
彭泽0902
2018/01/04
14.9K1
2023 年值得关注的 6 个 Rust web开发框架
在 2023 年,在开始开发 API 和 Web 应用程序之前,哪个 Rust Web 框架最适合研究?在这里,我们将看看一些目前使用或看起来很有前途的最流行的框架。
程序那些事儿
2023/03/07
10.1K0
2023 年值得关注的 6 个 Rust web开发框架
一文读懂 WebSocket 通信过程与实现
来源:Python那些事 ID:PythonSomething 什么是 WebSocket ? WebSocket 是一种标准协议,用于在客户端和服务端之间进行双向数据传输。但它跟 HTTP 没什么关系,它是一种基于 TCP 的一种独立实现。 以前客户端想知道服务端的处理进度,要不停地使用 Ajax 进行轮询,让浏览器隔个几秒就向服务器发一次请求,这对服务器压力较高。另外一种轮询就是采用 long poll 的方式,这就跟打电话差不多,没收到消息就一直不挂电话,也就是说,客户端发起连接后,如果没消息,就一
小小科
2018/06/20
2.2K0
一文读懂 WebSocket 通信过程与实现
WebSocket 是一种标准协议,用于在客户端和服务端之间进行双向数据传输。但它跟 HTTP 没什么关系,它是一种基于 TCP 的一种独立实现。
前端教程
2018/07/27
6660
一文读懂 WebSocket 通信过程与实现
JavaScript 连接消息(RabbitMQ)
STOMP是一个简单的面向文本的消息传递协议。它定义了一种可互操作的有线格式 ,以便任何可用的 STOMP 客户端都可以与任何 STOMP 消息代理进行通信,从而在语言和平台之间提供简单而广泛的消息互操作性(STOMP 网站有一个STOMP 客户端和服务器实现列表。
鱼找水需要时间
2023/02/16
7630
JavaScript 连接消息(RabbitMQ)
深度:手写一个WebSocket协议 [7000字]
我之前是做IM相关桌面端软件的开发,基于TCP长链接自己封装的一套私有协议,目前公司也有项目用到了ws协议,好像无论什么行业,都会遇到这个ws协议。
Peter谭金杰
2020/05/09
1.5K0
深度:手写一个WebSocket协议 [7000字]
springboot vue整合websocket
1.引入包 compile 'org.springframework.boot:spring-boot-starter-websocket' 2.新建类MyWebsocket import org.springframework.stereotype.Component; import javax.websocket.*; import javax.websocket.server.ServerEndpoint; import java.io.IOException; import ja
似水的流年
2018/07/04
2.1K0
【websocket】spring boot 集成 websocket 的四种方式
这个配置类很简单,通过这个配置 spring boot 才能去扫描后面的关于 websocket 的注解
猿天地
2019/10/31
43.8K2
腾讯云CDN支持WebSocket
Websocket是用于服务端主动向客户端推送消息的技术。传统的HTTP/HTTPS只能由客户端向服务端发起请求,服务端对请求一一响应。在需要获取服务端状态变化的场景下,如:提交的后台任务是否执行成功,只能通过客户端轮询向服务端发起请求,不仅效率低,还浪费资源(HTTP1.0下每次轮询都需要经过TCP三次握手重新建立连接)。而WebSocket的出现较好的解决了这个问题,在TCP首次建立完连接之后,该连接不自动关闭,在有效期内客户端可以继续向服务端发送消息,服务端也能主动给客户端发送消息。
yaho
2020/05/02
23.9K0
腾讯云CDN支持WebSocket
you-dont-know-websocket
本文阿宝哥将从多个方面入手,全方位带你一起探索 WebSocket 技术。阅读完本文,你将了解以下内容:
阿宝哥
2020/07/29
1.8K0
you-dont-know-websocket
php实现websocket实时消息推送
软件通信有七层结构,下三层结构偏向与数据通信,上三层更偏向于数据处理,中间的传输层则是连接上三层与下三层之间的桥梁,每一层都做不同的工作,上层协议依赖与下层协议。基于这个通信结构的概念。
OwenZhang
2021/12/08
2.2K0
php实现websocket实时消息推送
HTML5中的WebSocket
在传统方式下,很多网站为了实现即时通讯,所用的技术都是轮询。轮询是在特定的的时间间隔(如每1秒),由浏览器对伺服器发出HTTP request,然后由伺服器返回最新的数据给客户端的浏览器。这种传统的模式带来很明显的缺点,即浏览器需要不断的向伺服器发出请求,然而HTTP request 的header是非常长的,里面包含的数据可能只是一个很小的值,这样会占用很多的带宽和服务器资源。
用户7353950
2022/05/10
1.2K0
HTML5中的WebSocket
PHP是如何实现websocket实时消息推送的
什么是WebSocket WebSocket用于在Web浏览器和服务器之间进行任意的双向数据传输的一种技术。WebSocket协议基于TCP协议实现,包含初始的握手过程,以及后续的多次数据帧双向传输过程。 其目的是在WebSocket应用和WebSocket服务器进行频繁双向通信时,可以使服务器避免打开多个HTTP连接进行工作来节约资源,提高了工作效率和资源利用率。
友儿
2022/09/11
1.1K0
Netty 系列八(基于 WebSocket 的简单聊天室).
    之前写过一篇 Spring 集成 WebSocket 协议的文章 —— Spring消息之WebSocket ,所以对于 WebSocket 协议的介绍就不多说了,可以参考这篇文章。这里只做一些补充说明。另外,Netty 对 WebSocket 协议的支持要比 Spring 好太多了,用起来舒服的多。
JMCui
2018/09/27
1.8K0
Netty 系列八(基于 WebSocket 的简单聊天室).
Golang中用到的的Websocket库
在不刷新页面的情况下发送消息并获得即时响应是我们认为理所当然的事情。但在过去,启用实时功能对开发人员来说是一个真正的挑战。开发者社区已经从 HTTP 长轮询和 AJAX 走了很长一段路,终于找到了构建真正实时应用程序的解决方案。该解决方案以 WebSockets 的形式出现,它可以在用户的浏览器和服务器之间打开交互式会话。WebSockets 允许浏览器向服务器发送消息并接收事件驱动的响应,而无需轮询服务器以获取回复。目前,WebSockets 是构建实时应用程序的首选解决方案:在线游戏、即时通讯工具、跟踪应用程序等。本指南解释了 WebSockets 的运行方式,并展示了我们如何使用 Go 编程语言构建 WebSocket 应用程序。
没有故事的陈师傅
2021/09/09
2K0
你知道在springboot中如何使用WebSocket吗
  我们都知道 http 协议只能浏览器单方面向服务器发起请求获得响应,服务器不能主动向浏览器推送消息。想要实现浏览器的主动推送有两种主流实现方式:
用户2038589
2019/05/24
2.8K0
相关推荐
你应该知晓的Rust Web 框架
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验