我用PHP做了一个WebSocket服务器,并添加了将SSL/TLS添加到服务器的功能。现在我用stream_socket_enable_crypto启用了加密,一切正常。我读取数据并解密。只有HTTP请求有点奇怪:
客户端发送:
GET / HTTP/1.1
Host: example.com:8080
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:120.0) Gecko/20100101 Firefox/120.0
Accept: */*
...
字符串
服务器接收:
HTTP/1.1
Host: example.com:8080
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:120.0) Gecko/20100101 Firefox/120.0
Accept: */*
...
型
我的问题是:丢失字节的原因是什么?我可以做些什么来找回这些字节?
我使用PHP 8.2
服务器:
终端:
openssl genrsa -out wss.key 2048 && openssl req -key wss.key -new -x509 -days 365 -out wss.crt
型
PHP:
error_reporting(E_ALL);
ini_set("display_errors", "1");
if(ob_get_level() == 0) ob_start();
$server = stream_socket_server("tcp://example.com:8080", $errno, $errstr, STREAM_SERVER_BIND | STREAM_SERVER_LISTEN);
stream_context_set_option($server, ["ssl" => [
"local_cert" => __DIR__."/wss.crt",
"local_pk" => __DIR__."/wss.key",
"disable_compression" => true,
"verify_peer" => false,
"verify_peer_name" => false,
"allow_self_signed" => true
]]);
$done = false;
while(!$done) {
$sockets = ["server" => $server];
if(stream_select($sockets, $w, $e, 0, 20) === false)
show("ERROR");
if(in_array($server, $sockets)) {
$client = stream_socket_accept($server);
$sockets[] = $client;
stream_socket_enable_crypto($client, true, STREAM_CRYPTO_METHOD_TLS_SERVER);
}
foreach($sockets as $client) {
if(!in_array($client, $sockets))
continue;
show(fread($client, 100));
fclose($client);
$done = true;
show("EXIT");
}
}
function show(...$data) {
var_dump($data);
@ob_flush();
flush();
}
型
客户:
JS:
url = "ws://example.com:8080";
socket = new WebSocket(url);
setTimeout(() => {
socket.close();
socket = new WebSocket(url);
}, 1000);
型
使用主机和端口更改example.com:8080
详细代码请参阅PHPWS
1条答案
按热度按时间uxhixvfz1#
我现在知道这个问题了。TCP paylaod开始于
00 00
之后,在HTTP中开始于GET /
,在TLS中开始于TLS headers
:17 03 03 03 15
,TLS数据类型(应用数据23
),TLS版本(1.203 03
)和有效负载长度(78903 15
)的数据
的
在PHP中,在
stream_socket_enable_crypto
之后,第一个包被读取为TLS,前5个字节作为TLS头,失败后,因为它的HTTP,它在有效载荷中丢失了这5个字节。解决方案:
在启用加密之前,读取数据而不从缓冲区(PEEK)中清除数据
字符串
现在,如果数据只是一个HTTP请求,并且在TLS握手时没有丢失TLS头信息,则可以使用该数据。