Opera 12 中的 WebSocket 握手失败(错误请求)

Posted

技术标签:

【中文标题】Opera 12 中的 WebSocket 握手失败(错误请求)【英文标题】:WebSocket handshake failure (bad request) in Opera 12 【发布时间】:2012-08-25 18:56:56 【问题描述】:

我目前正在为我的学士论文工作,最近开始“深入研究”node.js 和 webSocket 的使用。在 Firefox 15.0 和 Chrome 21.0.1180.89 m 中访问时,我的 webSocket 服务器运行没有问题。在 Opera 12.02 中,客户端-服务器握手似乎存在问题。这是 Opera 的错误控制台所说的:

[31.08.2012 01:03:51] WebSockets - http://10.0.0.2/
Connection
WebSocket handshake failure, invalid response code '400'.

有趣的是:我在 Dragonfly 控制台的网络日志中的任何地方都找不到这个错误。访问网站时请求的所有字段(index.html、client.js 等)都已找到并按原样提供(HTTP 状态代码 200 OK)。另外,我的服务器返回的唯一状态码是 200、404 和 500,所以这看起来像是来自 webSocket 本身。

是的,在 Opera 中启用了 webSocket...我不知道可能是什么问题

任何帮助将不胜感激:)

编辑: 到目前为止,这是我的代码,因此您可以查看我的服务器发送了哪些标头以及我如何使用我的 client.js 创建 webSocket 连接:

server.js:

// load required modules:
var http = require("http");
var WebSocketServer = require("websocket").server;
path = require("path");
url = require("url");
filesys = require("fs");

// declare listening port vars:
var httpListeningPort = 80;
var webSocketListeningPort = 80;

// create HTTP-server:
var httpSrv = http.createServer(function(request, response) 
    console.log((new Date()) + ":\tReceived request for " + request.url);
//  response.writeHead(200);
//  response.end();
    var myPath = url.parse(request.url).pathname;
    var fullPath = path.join(process.cwd(), myPath);
    if(myPath === "/") 
        fullPath += "index.html";
        console.log("Full path:\t" + fullPath);
        filesys.readFile(fullPath, "binary", function(err, file) 
            if(err) 
                response.writeHeader(500, "Content-Type": "text/plain");
                response.write(err + "\n");
                response.end();
            
            else 
                response.writeHeader(200);
                response.write(file, "binary");
                response.end();
            
        );
    
    else 
        path.exists(fullPath, function(exists) 
        if(!exists) 
            response.writeHeader(404, "Content-Type": "text/plain");
            response.write("404 Not Found\n");
            response.end();
        
        else 
            filesys.readFile(fullPath, "binary", function(err, file) 
                if(err) 
                    response.writeHeader(500, "Content-Type": "text/plain");
                    response.write(err + "\n");
                    response.end();
                
                else 
                    response.writeHeader(200);
                    response.write(file, "binary");
                    response.end();
                
            );
        
        );
       
);
httpSrv.listen(httpListeningPort, function() 
    console.log((new Date()) + ":\tServer is now listening on port " + httpListeningPort);
);

// create webSocket server and tie it to the http server:
wsServer = new WebSocketServer(
    httpServer: httpSrv
);

function originChecker(origin) 
    if(origin) 
        console.log("Origin " + origin + " is allowed");
        return true;
     else 
        console.log("origin is NOT allowed.");
        return false;
    


// how to handle requests:
wsServer.on("request", function(request) 
    // check whether origin is allowed or not:
    if(originChecker(request.origin) === false) 
        request.reject();
        console.log((new Date()) + ":\tConnection request from origin " + request.origin + " rejected.");
        return;
    

    // accept the connecteion request -> open the connection:
    var connection = request.accept(null, request.origin);
    console.log((new Date()) + ":\tConnection request from " + request.origin + " accepted.");

    // handle incoming messages from the clients:
    connection.on("message", function(message) 
        if(message.type === "utf8") 
            console.log((new Date()) + ":\tReceived message from " + request.origin + ":\nType: " + message.type + "\nLength: " + message.utf8Data.length + "\nMessage: " + message.utf8Data);
            // echo "Message received":
            connection.sendUTF(JSON.stringify(  type: "message", data: "Message received !"  ));
         else 
            // send error message back to client:
            console.log((new Date()) + ":\tReceived message from " + request.origin + ":\nERROR:\tMessage is NOT UTF-8! it's " + message.type);
            connection.sendUTF(JSON.stringify(  type: "message", data: "ONLY UTF-8 accepted !"  ));
        
    );

    // what to do when connection is closed:
    connection.on("close", function() 
        console.log((new Date()) + ":\tClient @" + connection.remoteAddress + " disconnected.");
    );
);

client.js:

function client() 

    if("WebSocket" in window) 
        alert("WebSocket is supported by your browser!");

        // try to connect to the webSocket server:
        var connection = null;
        connection = new WebSocket("ws://10.0.0.2:80");

        // things to do once the connection is opened:
        connection.onopen = function() 
            alert("INFO:\tConnection to server is OPEN");

            document.getElementById("msgInput").focus();
            document.getElementById("msgInput").disabled = false;
            document.getElementById("msgInput").value = "";

            document.getElementById("msgInput").onkeyup = function(key) 
                switch(key.keyCode) 
                    case 13:    if(document.getElementById("msgInput").value === "")  
                                break;
                                
                                var messageText = document.getElementById("msgInput").value;
                                document.getElementById("msgInput").disabled = true;
                                document.getElementById("msgInput").value = "";
                                document.getElementById("statusHeader").innerHTML = "Sending...";
                                connection.send(messageText);
                    break;
                    default: document.getElementById("statusHeader").innerHTML = "Press ENTER to send!";
                
            ;
        ;

        connection.onerror = function(error) 
            document.body.style.backgroundColor = "#220000";
            document.body.style.color = "#aa0000";
            document.getElementById("statusHeader").innerHTML = "ERROR connecting to server -> OFFLINE";
            return;
        ;

        connection.onmessage = function(message) 
            try 
                var json = JSON.parse(message.data);
             catch (error) 
                alert("ERROR parsing message:\t" + error);
                return;
            

            document.getElementById("statusHeader").innerHTML = json.data;
            document.getElementById("msgInput").disabled = false;
        ;

        connection.onclose = function() 
            setTimeout(function()  
            document.body.style.backgroundColor = "#808080";
            document.body.style.color = "#ffffff";
            document.getElementById("statusHeader").innerHTML = "OFFLINE";
            document.getElementById("msgInput").disabled = true;
            document.getElementById("msgInput").value = "OFFLINE";
            , 5000);
            return;
        ;
     else 
        alert("WebSocket is NOT supported by your browser! Exiting now.");
        return;
       
;

【问题讨论】:

您能否提供更多信息:您使用的是什么服务器?您使用什么 javascript 创建连接?您的服务器会为握手失败返回哪些标头? 嗨 simonc,我编辑了我的问题并添加了我的服务器和客户端脚本的源代码。如您所见,atm 我的服务器还没有专门处理错误的握手 - 如果找不到请求 URI,我发送的唯一标头是 404,如果打开请求的文件时出错(例如缺少文件权限等),则为 500。 ) 和 200 如果一切顺利。在 Firefox 和 Chrome 中访问服务器工作正常,这让我感到奇怪,但在 Opera 中,由于握手失败,我收到了一个错误的请求,jsut 对我来说没有多大意义。 “我在使用哪个 JS”是什么意思? 谢谢。我刚刚注意到previous SO question,它声称 Opera 12 仅支持旧的、已弃用的 websockets 版本。你现在可以坚持使用其他浏览器并在 Opera 更新后再次测试它吗? 我也看到了这个问题,但它似乎描述了另一种错误。我不认为 Opera 支持旧版本的协议是原因。但是我现在也发现,老版本的ebSockets和现在正式的RFC版本有很多问题。此外,当已经存在 RFC 6455 时......我肯定不会支持已弃用的版本:)。我现在可以坚持使用 Firefox 和 Chrome。 Opera 有望在即将到来的更新中支持 RFC 版本,据我所知,IE 10 也将支持。感谢您的帮助,我很感激。 有没有办法将我的问题标记为已解决之类的? 【参考方案1】:

根据recent question Opera 12 支持旧的、不兼容的 websockets 版本。此版本 (Hixie-76) 在其握手中使用了一组不同的标头。您的服务器可能不理解这些解释了它的 400 错误响应。

如果您有能力等待 Opera 迎头赶上,最简单的“解决方案”是暂时使用其他浏览器进行测试。 hixie 协议草案已被弃用,因此 Opera 最终必然会升级到 RFC 6455。

【讨论】:

以上是关于Opera 12 中的 WebSocket 握手失败(错误请求)的主要内容,如果未能解决你的问题,请参考以下文章

https中的WebSocket打开握手超时

websocket-rails,websocket握手错误

websocket的握手源代码中的laddr和raddr是啥

WebSocket - 关闭握手 Gorilla

“WebSocket 握手期间出错:状态行无效”

Django:WebSocket 握手期间出错:意外的响应代码:500