Linux Bash:如何作为客户端打开 websocket 连接
Posted
技术标签:
【中文标题】Linux Bash:如何作为客户端打开 websocket 连接【英文标题】:Linux Bash: How to open a websocket connection as client 【发布时间】:2017-04-15 22:17:17 【问题描述】:我创建了一个提供 Web 套接字服务器的 Node.JS 应用程序(使用 npm ws)。这个 websocket 一直等到建立连接。一旦连接到达服务器,websocket 就会执行一个作业。工作完成后,将通过套接字发送一条消息,然后关闭套接字。 此套接字按预期工作;已经用另一个 Node.JS 脚本对其进行了测试。
如何仅使用 linux 命令行 工具连接到网络套接字? 我已经按照here 的描述尝试过 curl。但是,我找不到如何正确连接到在 localhost:8088/socket/ 上运行的 websocket
编辑: 我的问题已被确定为可能与 another 问题重复。但是,链接的问题仅询问是否有办法使用 curl。我很高兴看到任何适用于 bash 的解决方案。此外,链接问题的答案是使用 autobahn.ws 的 javascript 文件
【问题讨论】:
How to hit the WebSocket Endpoint?的可能重复 【参考方案1】:从这里试试这个:How to hit the WebSocket Endpoint?
$ curl -i -N \
-H "Connection: Upgrade" \
-H "Upgrade: websocket" \
-H "Host: echo.websocket.org" \
-H "Origin: http://www.websocket.org" \
http://echo.websocket.org
他从这里得到的:http://www.thenerdary.net/post/24889968081/debugging-websockets-with-curl
为了将来引用本网站的内容:
那些旗帜说:
在输出中返回标头 不要缓冲响应 设置此连接需要从 HTTP 升级到其他内容的标头 设置此连接需要升级为 WebSocket 连接的标头 设置一个标头来定义主机(后面的 WebSocket 标准要求) 设置一个标头来定义请求的来源(后来的 WebSocket 标准要求)
如果 websocket 正在工作,它应该返回以下内容:
$ curl -i -N \
-H "Connection: Upgrade" \
-H "Upgrade: websocket" \
-H "Host: echo.websocket.org" \
-H "Origin:http://www.websocket.org" \
http://echo.websocket.org
HTTP/1.1 101 Web Socket Protocol Handshake
Upgrade: WebSocket
Connection: Upgrade
WebSocket-Origin: http://www.websocket.org
WebSocket-Location: ws://echo.websocket.org/
Server: Kaazing Gateway
Date: Mon, 11 Jun 2012 16:34:46 GMT
Access-Control-Allow-Origin: http://www.websocket.org
Access-Control-Allow-Credentials: true
Access-Control-Allow-Headers: content-type
Access-Control-Allow-Headers: authorization
Access-Control-Allow-Headers: x-websocket-extensions
Access-Control-Allow-Headers: x-websocket-version
Access-Control-Allow-Headers: x-websocket-protocol
【讨论】:
... 我已经在我的问题中提到过:P 不认真:我无法让它与 localhost 一起工作。我在 express.js 网络服务器上收到 HTTP/1.1 400 Bad Request Content-type: text/html 哦,对不起!也许您需要自己处理更新请求?如果服务器只服务于 ws 协议?因为如果我理解正确,curl 请求会尝试执行 http 并将其更新为 ws 协议 - 但如果网络服务器不接受 http 传入调用,则不会发生任何事情 ***.com/questions/18045352/… 好吧,我想到了你说的。我以前没有听说过这种升级机制。但是,这当然可能是它不起作用的原因;)所以我现在已将我的 node.js 应用程序上传到在线云提供商。因此我现在有一个 http url。我想我的 express.js 框架也可以在内部使用升级机制。如何将路径和端口添加到 curl 命令? 好的。我很好奇如果在升级后建立连接会发生什么。因为它是双向流,所以它必须以某种方式在终端中打开。但是怎么做?会发生什么?然后我试了一下,得到了这个:curl: (1) Protocol "ws" not supported or disabled in libcurl
来自这个:curl -i -N -H "Connection: Upgrade" -H "Upgrade: websocket" -H "Host: echo.websocket.org" -H "Origin:http://www.websocket.org" ws://echo.websocket.org/
好的,所以回答你的问题:我认为你不能走那么远,在升级后使用 linux curl 工具进行通信。既然您询问了linux tools
,也许可以安装类似github.com/progrium/wssh 的东西,然后从命令行运行(可以处理协议)【参考方案2】:
我一直在使用 wscat,一个 npm 包。 https://github.com/websockets/wscat.
发布时软件包自述文件中的说明:
安装
这个模块需要全局安装,所以安装时使用 -g 标志:
npm install -g wscat
示例
$ wscat -c ws://echo.websocket.org
Connected (press CTRL+C to quit)
> hi there
< hi there
> are you a happy parrot?
< are you a happy parrot?
【讨论】:
请注意 ws://echo.websocket.org 服务不再可用【参考方案3】:vianswer 提供了一个非常有用的工具。 websocat
非常好用。
我只想用 bash
内置函数来做。我认为对其他人更好地理解协议很有用。
websocket protocol 握手很简单。
要在 bash 中打开 tcp
频道,我们可以使用:
wshost=echo.websocket.org
wsport=80
exec 3<>/dev/tcp/$wshost/$wsport
然后我们可以使用文件描述符&3
读写数据到tcp
连接。
首先让我们打开一个读取通道:
CR=$(echo -en "\r")
while read <&3; do echo "WS MSG:[$REPLY//$CR/]"; done &
我们真的不需要替换回车字节\r
,但是如果我们不这样做,终端输出会很奇怪。
每个 websocket 服务器实现都可能需要特定的细节。 websocket.org 在结束行之前需要Origin
标头和\r
字节。
然后我们可以开始连接upgrade
:
echo -e "GET / HTTP/1.1\r
Host: $wshost\r
Connection: Upgrade\r
Upgrade: websocket\r
Sec-WebSocket-Accept: $(echo -n "somekey"|base64)\r
Origin: http://www.websocket.org\r
\r" >&3
我们立即看到 ws upgrade 输出:
$ WS MSG:[HTTP/1.1 101 Web Socket Protocol Handshake]
WS MSG:[Access-Control-Allow-Credentials: true]
WS MSG:[Access-Control-Allow-Headers: content-type]
WS MSG:[Access-Control-Allow-Headers: authorization]
WS MSG:[Access-Control-Allow-Headers: x-websocket-extensions]
WS MSG:[Access-Control-Allow-Headers: x-websocket-version]
WS MSG:[Access-Control-Allow-Headers: x-websocket-protocol]
WS MSG:[Access-Control-Allow-Origin: http://www.websocket.org]
WS MSG:[Connection: Upgrade]
WS MSG:[Date: Thu, 29 Oct 2020 15:08:01 GMT]
WS MSG:[Sec-WebSocket-Accept: eXT5yQBZ/TOhFBUi6nLY8cfzs1s=]
WS MSG:[Server: Kaazing Gateway]
WS MSG:[Upgrade: websocket]
WS MSG:[]
您看到 Sec-WebSocket-Accept
标头了吗?服务器按照RFC 6455 中的描述解析它。我们可以计算它:
$ echo -n "$(echo -n "somekey" | base64)258EAFA5-E914-47DA-95CA-C5AB0DC85B11" |
sha1sum | cut -d " " -f1 | xxd --ps -r | base64
eXT5yQBZ/TOhFBUi6nLY8cfzs1s=
我知道...cut
、xxd
、base64
和 sha1sum
不是内置的,但此验证步骤只是为了澄清。
握手完成,我们的 tcp 连接现在升级为 websocket 连接。
现在是困难的部分。
我们需要发送数据。我们可以在section 5 of the RFC6455 中学习如何操作。
客户端必须屏蔽它发送到服务器的所有帧(有关详细信息,请参阅第 5.3 节)
和
服务器必须在收到未屏蔽的帧时关闭连接
Read the RFC Section 5.2 to know how to mask data.
RFC 甚至提供了用于数据屏蔽的 ascii-art:
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-------+-+-------------+-------------------------------+
|F|R|R|R| opcode|M| Payload len | Extended payload length |
|I|S|S|S| (4) |A| (7) | (16/64) |
|N|V|V|V| |S| | (if payload len==126/127) |
| |1|2|3| |K| | |
+-+-+-+-+-------+-+-------------+ - - - - - - - - - - - - - - - +
| Extended payload length continued, if payload len == 127 |
+ - - - - - - - - - - - - - - - +-------------------------------+
| |Masking-key, if MASK set to 1 |
+-------------------------------+-------------------------------+
| Masking-key (continued) | Payload Data |
+-------------------------------- - - - - - - - - - - - - - - - +
: Payload Data continued ... :
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
| Payload Data continued ... |
+---------------------------------------------------------------+
我想写一个bash函数来屏蔽ws数据,但我现在做不到。我稍后会更新这篇文章。
【讨论】:
【参考方案4】:我的工具websocat 就是专门为此设计的。
websocat ws://your_server/url
您可以与您的服务器连接并交换数据。默认情况下,每一行都变成一个 WebSocket 文本消息,反之亦然。
在 Linux 上使用 readline 玩起来更舒服:
rlwrap websocat ws://your_server/url.
它不是唯一的 CLI websocket 客户端。还有“ws”和“wscat”项目。
【讨论】:
嗨!谢谢你的工具。是否可以无权限安装?在办公室,我们没有 sudo 访问权限 @GeorgiosPligoropoulos 是的,只需从 Github 版本下载适当的预构建可执行文件并运行它。可以运行多个变体。也可以下载解压deb包。 当我尝试:websocat -H "Authorization: Bearer ...." ws://server/url
时,我会收到帮助消息。这个工具似乎不能处理带有选项的网络套接字监听。
@NicolasRouquette 在此模式下,应在连接的 URL 之后指定选项。请注意,用于侦听和连接的标头是单独的选项。以上是关于Linux Bash:如何作为客户端打开 websocket 连接的主要内容,如果未能解决你的问题,请参考以下文章
macOS - 给Terminal终端命令行配置网络代理的方法
linux下.bashrc为啥每次打开终端都要source一下才有效,如何才能永远生效?