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

0

我希望通过 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”的原因,如果是这个原因,那么在何处设置,希望群主帮忙看一下这个问题。

已邀请:

walkor

赞同来自: zed6621314

应该是你请求的服务端需要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

赞同来自:

承上。
环境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

赞同来自:

承上。


问题已经找到了,当前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
希望楼主能够抽空升个级。握爪。

要回复问题请先登录注册