Sec-WebSocket-Accept not found以及 Sec-WebSocket-Protocol问题

zed6621314

我希望通过 AsyncTcpConnection连接到“wss://premws-pt2.365lpodds.com/zap/?uid=896502538598419”这个地址。当我将$transport设置为”ssl”时,会报错。
关键代码:
截图
执行结果:
截图

后来将$transport设置成 “sslv3”,不报”Sec-WebSocket-Accept not found”错误了,但是只触发了 onConnect和onClose回调,没有触发onWebSocketConnect回调。
截图
执行结果:
截图

另外,在浏览器中可以连接( 需要设置子协议 ),以下是在chrome下的测试。
截图
截图

因此,我不知道问题出在哪?是不是没有设置”Sec-Websocket-Protocol:zap-protocol-v1”的原因,如果是这个原因,那么在何处设置,希望群主帮忙看一下这个问题。

6755 4 1
4个回答

walkor

应该是你请求的服务端需要Sec-WebSocket-Protocol 和 Sec-WebSocket-Extensions这2个http头,你可以这样写。

$ws_connection = new AsyncTcpConnection("ws://premws-pt2.365lpodds.com:443/zap/?uid=896502538598419");
$ws_connection->transport = 'ssl';
$ws_connection->headers = [
    'Sec-WebSocket-Extensions' => 'permessage-deflate; client_max_window_bits',
    'Sec-WebSocket-Protocol' => 'zap-protocol-v1',
];
  • zed6621314 2020-01-07

    搞定!谢谢群主哈,眼眶瞬间湿润,昨天搞了一天。。。

zed6621314

承上。
环境PHP 7.0.23,Workerman 3.5.24

第一个问题解决了,但是又碰到了新的问题。我预期通过wss连接获取的数据如下(下面截图来自于正常浏览器调界面):
截图

蓝色高亮部分的文本对应图中第二个红框,红框里面有两个小圆点,这是目标网站使用的消息分隔符(不可见,我在这里特意说明,是怀疑问题可能是这些不可见字符造成的,这两个字符分别是\X14和\X01)。

我通过workerman 3.5.24 + PHP7.0.23获取执行脚本(test.php),截图如下:
截图

里面有部分消息乱码,将这段响应保存到txt文件,以Hex View方式观看,可以看到第一条数据 ( “·__time·|...” )是没有问题的,而后面接受的数据是乱码
截图

紧接着的数据应该是"·CONFIG_2_0·F|CG;AD=..."才是。

我另外从王网上找了一个python程序,也是通过websocket连接该URL,获取的数据是正常的,如下图:(最开始我怀疑是站点做的反爬虫措施,重要数据故意扰乱了,但这个程序证明了不是。因为之前使用workerman也不是所有的数据都获取不到,部分较短的消息是可以获取的。)
截图

由于对方的业务数据里面会出现一些\x00,\x01,\0x14,\x015这些不可见字符作为分隔符,所以是否会对解析数据产生影响。

后来,我考虑有可能是PHP版本的问题,于是安装了PHP7.3。再次运行,效果如下:截图
出现了上个问题所描述的那个问题:当获取一个服务器的握手消息,并且客户端发送一个响应消息后,服务器不再发送消息,卡住了。(这次是在添加了前一个问题中服务器要求的header “'Sec-WebSocket-Extensions:permessage-deflate; client_max_window_bits'”)情况下。

不知道是否遇到了workerman的一个bug或者是我有哪些地方没有设置正确。请群主帮忙看一下。脚本文件已经作为附件上传(test.rar)。

  • 暂无评论
walkor

它的数据应该是被压缩了,还有数据应该是用了zap-protocol-v1协议又打包了一次。
你要自己研究下怎么破解它的压缩和zap-protocol-v1协议。

  • zed6621314 2020-01-09

    好的,在研究RFC7692,11号给你个反馈。

zed6621314

承上。

问题已经找到了,当前Workerman没有处理Sec-WebSocket-Extension的情况。我所遇到的问题是服务端启用了 permessage-deflate扩展(这个扩展已经是在IANA注册了的,很多浏览器都已经实现了),因此服务端发送的ws数据负载部分可能会通过deflate算法进行压缩(表现在WS头部则为: RSV1比特位设置为1),而workerman的ws客户端在decode()接口中尚未处理之。
原decode()函数如下:
截图

下面我针对上面我描述的问题修改了一decode()方法,足以解决我自己的问题了。但是对于permessage-deflate扩展,还有很多细节没有处理( 不能通用,因此不能提交代码,项目太紧 )。
修改的文件是:Workerman\Protocols\Ws.php
增加了一个方法 convertCharsToBinStr($chars),修改了方法 decode()
截图
截图

ws压缩相关RFC文档链接为:
https://tools.ietf.org/html/rfc7692#page-12
希望楼主能够抽空升个级。握爪。

  • licaoping 2020-03-13

    大佬,你好,我想问下你上面说的python程序能分享下么,因为我使用Python的websocke-client进行连接时,老是在返回第一次数据之后就自动断开连接了,求大佬指点

  • MoJeffrey 2020-05-17

    加我微信:MoJeffrey

年代过于久远,无法发表回答
🔝