Linux Bash:如何作为客户端打开WebSocket连接

aydmsdu9  于 2023-01-30  发布在  Linux
关注(0)|答案(5)|浏览(352)

我已经创建了一个Node.JS应用程序,它提供了一个Web Socket服务器(使用npm ws)。这个web套接字等待连接建立。一旦连接到达服务器,web套接字就执行一个作业。当作业完成时,通过套接字发送一个消息,然后关闭套接字。这个套接字按预期工作;我已经用另一个Node.JS脚本测试过了。
如何只使用linux命令行**工具连接到Web Socket*?我已经尝试了here所述的curl。但是,我找不到如何正确连接到运行在localhost:8088/socket/的websocket

**编辑:**我的问题被认为可能与another问题重复。但是,链接的问题只问是否有一种方法可以用curl来完成。我很高兴看到任何可以在bash上工作的解决方案。另外,链接问题的答案是一个javascript文件,使用autobahn.ws

gdrx4gfi

gdrx4gfi1#

我的工具websocat就是专门为此设计的。

websocat ws://your_server/url

您可以连接到服务器并与之交换数据。默认情况下,每一行都变成一条WebSocket文本消息,反之亦然。
在Linux上,使用readline操作它会更方便:

rlwrap websocat ws://your_server/url.

它并不是唯一的CLI WebSocket客户端,还有“ws”和“wscat”项目。

jmp7cifd

jmp7cifd2#

从这里试试这个: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
引用本网站的内容以备将来使用:
那些旗子写着:
1.在输出中返回标头
1.不缓冲响应
1.设置此连接从HTTP升级到其他连接所需的标头
1.设置此连接升级为WebSocket连接所需的标头
1.设置一个标头来定义主机(以后的WebSocket标准需要)
1.设置一个标头来定义请求的来源(以后的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
iibxawm4

iibxawm43#

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服务器实现可能需要特定的细节。www.example.com需要Origin标头和\r字节在结束行之前。websocket.org requires Origin header and \r byte before end line.
然后我们可以启动连接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升级输出:

$ 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连接。
现在是最难的部分。
我们需要发送数据。我们可以在RFC6455的第5节中学习如何发送数据。
客户端必须屏蔽它发送到服务器的所有帧(更多细节请参见第5.3节)
以及
服务器必须在收到未屏蔽的帧时关闭连接
阅读RFC第5.2节了解如何屏蔽数据。
RFC甚至为数据屏蔽提供了一种方法:

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数据,但是我现在做不到。我稍后会更新这篇文章。

monwx1rj

monwx1rj4#

我一直在使用wscat,一个npm包。
发布时软件包自述文件中的说明:

安装

此模块需要全局安装,因此在安装时使用-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?
vuktfyat

vuktfyat5#

    • tl; dr**curl -H 'Upgrade: websocket' -H "Sec-WebSocket-Key:openssl rand -base64 16" -H 'Sec-WebSocket-Version: 13' --http1.1 -sSv https://ws.ifelse.io(取决于您可能需要提供Origin和/或Connection: Upgrade的服务器)

首先,Websocket协议是如何工作的?客户端连接到服务器,发送握手请求,接收"101交换协议"(握手响应),之后他们来回发送帧。
握手过程如下:

GET / HTTP/1.1
Host: ws.example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw==
Sec-WebSocket-Version: 13
Origin: http://example.com

HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: HSmrc0sMlYUkAGmm5OPpG2HaGWk=

Upgrade使其从HTTP(s)切换到websocket协议。
Connection指定Upgrade是一个逐跳报头(中介应该使用而不是转发的报头),但我的实验表明,没有这个报头也可以工作,或者更准确地说,如果服务器前面有一个反向代理(例如nginx),它可能是可选的。
Sec-WebSocket-Key/Sec-WebSocket-Accept是这里、这里和这里描述的安全措施。
Sec-WebSocket-Version指定websocket协议版本。根据RFC 6455,它应该等于13。
当客户端是浏览器并且请求页面的来源与websocket服务器URL的来源不匹配时,需要Origin
关于websocket握手请求的详细描述可以在这里找到。
HTTP/1.1就是这样的,HTTP/2是一个different story
了解这一点后,可以使用curl建立websocket连接:

$ curl -H 'Upgrade: websocket' \
       -H "Sec-WebSocket-Key: `openssl rand -base64 16`" \
       -H 'Sec-WebSocket-Version: 13' \
       --http1.1 \
       -sSv \
       https://ws.ifelse.io
...
> GET / HTTP/1.1
> Host: ws.ifelse.io
> Upgrade: websocket
> Sec-WebSocket-Key: e2dujvcbYbN747lapeH+WA==
> Sec-WebSocket-Version: 13
...
< HTTP/1.1 101 Switching Protocols
< Connection: upgrade
< upgrade: websocket
< sec-websocket-accept: 6wmMGMtN00aWw3loYd6P36EHKMI=

其他选项为wscatwebsocat

相关问题