Ratchet未从浏览器接收WebSocket数据包



我正在尝试测试简单的ping&使用Ratchet与WebSockets进行pong响应。我的WebSocket服务器没有看到来自我的web浏览器的WebSocket客户端的任何响应,但浏览器可以很好地看到WebSocket发送的数据包。我正在努力寻找原因。

我目前的猜测是:

  • 我缺少一些HTTP标头
  • 我必须在浏览器wsclient.send(encodeFrame("{'action': 'pong'}"));上对数据包进行编码
  • CloudFlare未将WS流中的数据包识别为有效数据包,并对其进行了猛烈抨击
  • EC2实例中的CloudFlare或nginx正在进行一些奇怪的缓冲
  • Ratchet无法识别最低IOServer级别的数据包,并对其进行了猛烈抨击
    • 但我从未从这个级别得到任何错误或异常

设置:

  • Linux服务器@亚马逊EC2
  • DNS@CloudFlare提供免费计划和加速+强制HTTPS重定向
  • HTTP服务器是nginx
  • nginx上没有HTTPS(Cloudflare重定向HTTPS->EC2 HTTP)
  • WebSocket服务器(棘轮)在EC2上的127.0.0.1:65000上运行
  • Nginx将/api重定向到127.0.0.1:65000(棘轮)

在EC2实例上使用自己的WebSocket客户端进行了测试:

  • 127.0.0.1:65000运行良好
  • <Amazon NAT IP of instance>:80工作良好
  • <Amazon public IP of instance>:80运行良好
  • <CloudFlare IP of Amazon public IP>:80连接到应用程序实现级别的WebSocket服务器,但在任何级别(App、WsServer、HTTPServer)的onMessage方法上都看不到数据包
  • <CloudFlare IP of Amazon public IP>:443给出400 Bad Request,因为测试客户端只是简单的TCP流

从本地机器测试:

直接连接到CloudFlare缓存IP提供的主机。Dojox.Socket连接到wss://host/api。在Ratchet上的应用程序实现级别上再次看到连接(onOpen被激发)。我的浏览器看到ping数据包很好,所以从Ratchet发送也很好。

但后来我尝试从浏览器向ping发送pong回复,并且onMessage方法在Ratched上的任何级别上都不会被激发。连接保持打开,如果我用Fiddler观察,ping和pong都会不断发送,但WebSocket服务器从未接收到这些pong(onMessage)。

以下Fiddler的WebSocket流显示,来自浏览器的pongs具有"密钥屏蔽的数据:<some hex>",但来自Ratched的ping是而不是屏蔽的。

连接摘要:

页面加载:

本地机器http://host/&rar;CloudFlare HTTPS重定向https://host/&rar;http://host-with-amazon-public-ip/&rar;http://host-with-amazon-NAT-ip/&rar;加载wss WebSocket连接到/api 的HTML+JS页面

/api:的WebSocket连接

CloudFlare HTTPS重定向wss://host/api&rar;http://host-with-amazon-public-ip/api&rar;http://host-with-amazon-NAT-ip/api&rar;本地服务器nginx重定向/api&rar;127.0.0.1:65000&rar;连接升级&rar;WebSocket流.rar;web浏览器的WebSocket流

nginx.conf

server {
  listen 80;
  server_name test.example.com;
  root /home/raspi/test/public;
  autoindex off;
  index index.php;
  access_log /home/raspi/test/http-access.log;
  error_log /home/raspi/test/http-error.log notice;
  location / { 
    index index.php; 
    try_files $uri $uri/ /index.php?$args;
  }
 location /api {
    access_log /home/raspi/test/api-access.log;
    error_log /home/raspi/test/api-error.log;
    expires epoch;
    proxy_ignore_client_abort on;
    proxy_buffering off;
    proxy_request_buffering off;
    proxy_cache off;
    proxy_pass http://127.0.0.1:65000/;
    proxy_http_version 1.1;
    proxy_set_header Host $host;
    proxy_set_header Connection "keep-alive, Upgrade";
    proxy_set_header Upgrade "websocket";
    proxy_set_header Accept-Encoding "gzip, deflate";
    proxy_set_header Sec-WebSocket-Extensions "permessage-deflate";
    proxy_set_header Sec-WebSocket-Protocol "game";
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
  }
  location ^~ /js/app/ {
    try_files $uri /;
    expires epoch;
    add_header Cache-Control "no-cache" always;
  }
  location ~* ^.+.(jpg|jpeg|gif|css|png|js|ico|html|xml|txt)$ {
    try_files $uri /;
    access_log off;
    expires max;
  }
  location = /robots.txt  { access_log off; log_not_found off; }
  location = /favicon.ico { access_log off; log_not_found off; }    
  location ~ /. { access_log off; log_not_found off; deny all; }
  location ~ .php$ {
    try_files $uri =404;
    fastcgi_split_path_info ^(.+.php)(/.+)$; 
    fastcgi_pass unix:/var/run/php-fpm/php-fpm.sock; 
    fastcgi_index index.php; 
    fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; 
    include fastcgi_params; 
  }
}

Web套接字目前仅在业务和企业级别可用。你提到你在免费计划中。这就是问题所在。

问题是您的提供程序拒绝Connection和Update标头。您可以访问Ratchet/WebSocket/Version/RFC6455/HandshakeVerifier.php并将代码修改为:

    ...
    public function verifyAll(RequestInterface $request) {
    $passes = 0;
    $passes += (int)$this->verifyMethod($request->getMethod());
    $passes += (int)$this->verifyHTTPVersion($request->getProtocolVersion());
    $passes += (int)$this->verifyRequestURI($request->getPath());
    $passes += (int)$this->verifyHost((string)$request->getHeader('Host'));
    $passes += (int)$this->verifyUpgradeRequest((string)$request->getHeader('Upgrade'));
    $passes += (int)$this->verifyConnection((string)$request->getHeader('Connection'));
    die((string)$request);
    ...

您将看到结果请求没有必需的字段;

解决方法:覆盖WsServer::onOpen函数并手动添加要请求的字段。但这是不安全的。。。

相关内容

  • 没有找到相关文章

最新更新