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

然后我们可以使用文件描述符&amp;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=

我知道...cutxxdbase64sha1sum 不是内置的,但此验证步骤只是为了澄清。

握手完成,我们的 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 连接的主要内容,如果未能解决你的问题,请参考以下文章

c语言中如何使用android ADB命令??

macOS - 给Terminal终端命令行配置网络代理的方法

不过时的技术——Bash脚本

linux下.bashrc为啥每次打开终端都要source一下才有效,如何才能永远生效?

linux虚拟机下bash shell编程,制作一个音乐播放器,可以实现用代码打开mp3文件吗?

从 JavaScript 打开终端并运行 bash 命令 Linux