Jetty 9.2.x Websocket 服务器连接在使用 Firefox 连接后自动关闭,而不是使用 Chrome



我想使用 Jetty 构建一个嵌入式 Java WebSocket Server。我正在使用码头 9.2.6。My Client 是一个 HTML JavaScript 客户端。

使用谷歌浏览器(39,WebSocket版本13(,我可以建立连接并双向发送数据。当我使用 Firefox(34,WebSocket 版本 13(时,连接在建立连接后直接关闭。在我的 SocketListenerClass 中,onWebSocketConnect 事件被调用,onWebSocketClose 事件立即被调用。我为我的套接字尝试了 3 个版本。实现 WebSocketListener,扩展 WebSocketAdapter 并使用注释。到处都一样。

我得到接近的原因编号 1005 (CLOSE_NO_STATUS(,但有时是 1001。

这是我的代码:服务器:

import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.servlet.ServletHolder;
public static void main(String[] args)
    {
    Server server = new Server(80);
    ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS);
    context.setContextPath("/");
    server.setHandler(context);
    context.addServlet(new ServletHolder(new MyServlet()), "/*");
    try
      {
      server.start();
      server.join();
      }
    catch (Exception e)
      {
      e.printStackTrace();
      }
    }

Servlet:

import javax.servlet.annotation.WebServlet;
import org.eclipse.jetty.websocket.servlet.WebSocketServlet;
import org.eclipse.jetty.websocket.servlet.WebSocketServletFactory;
@SuppressWarnings("serial")
@WebServlet(name = "MyEcho WebSocket Servlet", urlPatterns = { "/egal" })
public class MyServlet extends WebSocketServlet
  {
    @Override
    public void configure(WebSocketServletFactory factory) {
        factory.register(MyEchoSocketWithListener.class);
    }
}

插座:

import org.eclipse.jetty.websocket.api.Session;
import org.eclipse.jetty.websocket.api.WebSocketListener;
public class MyEchoSocketWithListener implements WebSocketListener
  {
  private Session outbound;
  public void onWebSocketClose(int statusCode, String reason)
    {
    this.outbound = null;
    System.out.println("Session has been closed. Reason: +"+statusCode + " , "+reason);
    }
  public void onWebSocketConnect(Session session)
    {
    this.outbound = session;
    System.out.println("New Connection established...");
    }
  public void onWebSocketError(Throwable cause)
    {
    cause.printStackTrace(System.err);
    }
  public void onWebSocketText(String message)
    {
    if ((outbound != null) && (outbound.isOpen()))
      {
      System.out.printf("Echoing back message [%s]%n n", message);
      outbound.getRemote().sendString("Server-Echo: " + message, null);
      }
    }

JavaScript 客户端:

<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title>page title</title>
    <link rel="stylesheet" href="css/style.css">
</head>
<body>
<h1>WebSocket Test</h1>
<section id="content"></section>
<script>
var ws;
setTimeout(function (){initWebsocket();}, 3000);
function initWebsocket()
    {
    ws = new WebSocket("ws://127.0.0.1:80/egal");
    window.onbeforeunload = function ()
        {
        ws.onclose = function ()
            {
            }; // disable onclose handler first
        ws.close()
        };
    ws.onopen = function ()
        {
        document.write("WebSocket opened <br>");
        ws.send("Hello Server");
        document.write("Hello Message sent... <br>");
        };
    ws.onmessage = function (evt)
        {
        document.write("Message: " + evt.data + "<br>");
        };
    ws.onclose = function ()
        {
        document.write("<br>WebSocket closed<br>");
        };
    ws.onerror = function (err)
        {
        document.write("Error: " + err);
        };
    }
</script>
</body>
</html>

服务器输出:新连接已建立...
会话已关闭。原因: +1005 , 空

为什么它适用于铬而不是 FF?他们使用相同的 websocket 版本 13。我还尝试了Jetty 9.2.5,以及新的Mozilla Nightly和较旧的Firefox版本。这里没有区别。

更改

context.addServlet(new ServletHolder(new MyServlet()), "/*");

context.addServlet(new ServletHolder(new MyServlet()), "/egal");

这是次要的,不是问题的根本原因。

Firefox 正在正确处理关闭,在您从服务器返回响应之前,它刚刚关闭。

收盘代码

1005 仅表示收盘在没有传递收盘代码的情况下发生。如果您将onbeforeunload()实现更改为使用ws.close(1000)您将看到您自己的 javascript 正在关闭连接。 注释掉该行,您将看到响应消息。

继续在以下 github 项目中模拟了在嵌入式码头中创建 websocket 的 5 种不同方法。

https://github.com/jetty-project/embedded-websocket-echo-examples

每个演示加载一个HTML + JavaScript来演示连接/hello world/close

它们都可以与Chrome和Firefox一起使用

感谢您的回答。我解决了问题,这是由另一个愚蠢的错误引起的。

在我的 HTML 客户端中,我在正文中使用脚本标签。我也在我的 websocket 事件中使用了 document.write((。document.write(( 方法覆盖整个正文内容。所以我的javascript代码此时被删除了。

非常愚蠢的错误...对此感到抱歉。:-)

我在问自己,为什么它在Chrome中工作。