You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PHP服务端配置SSL后WebSocket wss连接收到二进制乱码如何解决

问题核心原因

仅为服务端监听Socket配置了SSL上下文,未对stream_socket_accept返回的客户端连接执行TLS握手操作,你直接读取的是未解密的TLS加密原始二进制数据,因此会出现乱码。

修复方案

按以下步骤调整代码即可解决:

  • 客户端连接成功后,先调用stream_socket_enable_crypto开启SSL加密层,完成握手后再读取数据
  • 证书配置如果是证书、私钥分离的情况,需要补充local_pk配置指定私钥文件路径
  • 测试用自签名证书保留当前的allow_self_signed、verify_peer配置即可

修正后的完整可运行代码

<?php
// 创建SSL上下文
$context = stream_context_create();
// 合并了证书和私钥的pem文件只需要配置local_cert,如果分离则要加local_pk指定私钥路径
stream_context_set_option($context, 'ssl', 'local_cert', '../ssl/cert.pem');
// stream_context_set_option($context, 'ssl', 'local_pk', '../ssl/privkey.pem'); // 私钥分离时打开本行
stream_context_set_option($context, 'ssl', 'allow_self_signed', true);
stream_context_set_option($context, 'ssl', 'verify_peer', false);

// 创建监听Socket
$socket = stream_socket_server(
    'tcp://127.0.0.1:8888',
    $errno, $errstr,
    STREAM_SERVER_BIND | STREAM_SERVER_LISTEN,
    $context
);

if (!$socket) {
    die("创建Socket失败: $errstr ($errno)");
}

// 接受客户端连接
$cn = stream_socket_accept($socket, 99999, $name);

// 关键:开启SSL加密,完成TLS握手
stream_socket_enable_crypto($cn, true, STREAM_CRYPTO_METHOD_TLS_SERVER);

// 此时读取的就是解密后的正常WebSocket升级请求
$text = fread($cn, 1024);
echo $text;
?>

可选优化方案

生产环境更推荐用Nginx/Apache做SSL卸载:

  • 反向代理配置WSS请求转发到本地PHP的WS服务端口
  • PHP服务不需要做任何SSL配置,保持原有普通WS逻辑即可,稳定性和性能更好

内容的提问来源于stack exchange,提问作者Andrei Nikolaenko

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.25 20:45:07