由于您没有提供手点链接,所以这里有一些注释,以下是自己的测试!
我猜问题出在wss部分,php需要先检索证书,这样才能加密数据。
您的代码应该可以在 ws:// 流上正常工作。
要连接到常规的ws:// 流,只需使用fsockopen()。
<?php
$fp = fsockopen("udp://echo.websocket.org", 13, $errno, $errstr);
if (!$fp) {
echo "ERROR: $errno - $errstr<br />\n";
} else {
fwrite($fp, "\n");
echo "Connected!";
echo fread($fp, 26);
fclose($fp);
}
但是要连接到wss:// 安全的 websocket 流,使用 php,没有库,我们需要首先创建一个隧道,通过使用 @ 查询 公钥 987654322@.
这是一种握手机制。这可以按如下方式完成。
注意第一个ssl:// 呼叫。这是TLS 1.0 协议。
<?php
$sock = stream_socket_client("ssl://echo.websocket.org:443",$e,$n,30,STREAM_CLIENT_CONNECT,stream_context_create(null));
if(!$sock){
echo"[$n]$e".PHP_EOL;
} else {
fwrite($sock,"GET / HTTP/1.1\r\nHost: echo.websocket.org\r\nAccept: */*\r\nConnection: Upgrade\r\nUpgrade: websocket\r\nSec-WebSocket-Version: 13\r\nSec-WebSocket-Key: ".rand(0,999)."\r\n\r\n");
while(!feof($sock)){
var_dump(fgets($sock,2048));
}
}
输出应该是这样的:
string(44) "HTTP/1.1 101 Web Socket Protocol Handshake"
string(21) "Connection: Upgrade"
string(37) "Date: Thu, 12 Dec 2019 04:06:27 GMT"
string(52) "Sec-WebSocket-Accept: fTYwcEa6D9kJBtghptkz1e9CtBI="
string(25) "Server: Kaazing Gateway"
string(20) "Upgrade: websocket"
相同的基本代码,另一个例子,从币安wss://流中提取数据。
我们也可以使用TLS 1.2 来代替tls:// 握手。适用于大多数服务器。
<?php
$sock = stream_socket_client("tls://stream.binance.com:9443",$error,$errnum,30,STREAM_CLIENT_CONNECT,stream_context_create(null));
if (!$sock) {
echo "[$errnum] $error" . PHP_EOL;
} else {
echo "Connected - Do NOT get rekt!" . PHP_EOL;
fwrite($sock, "GET /stream?streams=btcusdt@kline_1m HTTP/1.1\r\nHost: stream.binance.com:9443\r\nAccept: */*\r\nConnection: Upgrade\r\nUpgrade: websocket\r\nSec-WebSocket-Version: 13\r\nSec-WebSocket-Key: ".rand(0,999)."\r\n\r\n");
while (!feof($sock)) {
var_dump(explode(",",fgets($sock, 512)));
}
}
这是一种从 php.ini 获取仅远程手柄的 ssl RSA 公钥的方法。可用于加速以后的连接。
<?php
$opt = [
"capture_peer_cert" => true,
"capture_peer_cert_chain" => true
];
$a = stream_context_create(["ssl"=>$opt]);
$b = stream_socket_client("ssl://stream.binance.com:9443", $errno, $errstr, 30, STREAM_CLIENT_CONNECT, $a);
$cont = stream_context_get_params($b);
$key = openssl_pkey_get_public($cont["options"]["ssl"]["peer_certificate"]);
$c = openssl_pkey_get_details($key);
var_dump($c["key"]);
输出类似:
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhki(...)7aEsFtUNkwM5R5b1mpqzAwqHyvdamJx20bT6SS6
PYXSr/dv8ak1d4e2Q0nIa1O7l3w0bZZ4wnp5B8Z+tjPd1W8uaZoRO2iVkPMh2yPl
j0mmtUw1YlfDyutH/t4FlRCDiD4JjdREQGs381/+jbkdjl2SIb1IyNiCdAXA6zsq
xwIDAQAB
-----END PUBLIC KEY-----
可能还有其他怪癖,可以肯定的是,我们需要主手点^。很高兴能测试一下。否则祝你好运,关于这个主题的文档非常缺乏。
这是still a new born protocol(2011 年!)。最好的细节在 RFC 规范中:
IETF 将 WebSocket 协议标准化为 RFC 6455 在
2011
关于握手,必须由GET请求发起。
客户端将发送一个非常标准的 HTTP 请求,其标头
看起来像这样(HTTP 版本必须是 1.1 或更高版本,并且
方法必须是 GET)
Writing_WebSocket_servers#Client_handshake_request
简而言之:
如果未加密的 WebSocket 流量通过显式或
不支持 WebSockets 的透明代理服务器,连接
可能会失败。
WebSocket#Proxy_traversal
Transport_Layer_Security#Digital_certificates