Jetty 9.2.x Websocket Server连接在使用Firefox而不是Chrome时连接后自动关闭

Posted

技术标签:

【中文标题】Jetty 9.2.x Websocket Server连接在使用Firefox而不是Chrome时连接后自动关闭【英文标题】:Jetty 9.2.x Websocket Server connection automatically closed after connect when using Firefox, not with Chrome 【发布时间】:2015-02-17 02:11:08 【问题描述】:

我想使用 Jetty 构建一个嵌入式 Java WebSocket 服务器。我正在使用码头 9.2.6。 我的客户端是一个 html javascript 客户端。

使用 Google Chrome(39,WebSocket 版本 13)我可以建立连接并双向发送数据。 当我使用 Firefox(34,WebSocket 版本 13)时,连接在建立连接后直接关闭。在我的 SocketListenerClass 中调用 onWebSocketConnect 事件,立即调用 onWebSocketClose 事件。 我为我的 Socket 尝试了 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();
      
    

小服务程序:

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,空

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

【问题讨论】:

您的代码适用于 Jetty 9.2.3 至 9.2.6(甚至 9.3.0)、Linux 和 OSX,使用 Firefox 34.0 也许这是一个 html/javascript 问题。你也可以在你的问题中发布吗? 感谢您的回答。我在上面添加了客户端 javascript 代码。你如何运行代码?我尝试在 IDE IntelliJ 和 NetBeans 中运行服务器。这里也没有区别。 (我也试过不同的端口(80、8080、8081,...))谢谢。 【参考方案1】:

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

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

非常愚蠢的错误...抱歉。 :-)

我在问自己,为什么它仍然可以在 Chrome 中运行。 :-)

【讨论】:

能否请您添加对导致此问题的原因的描述? “在我的 HTML 客户端中,我使用的是正文中的标签”——到底是什么标签? 我的意思是脚本标签,我写在““,所以***编辑器不显示它......脚本块包含websocket代码并存储处理。所以通过 document.write() 它被覆盖并且会话被删除。【参考方案2】:

改变

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

每个demo都加载一个HTML+JavaScript来演示connect/hello world/close

它们都适用于 Chrome 和 Firefox

【讨论】:

以上是关于Jetty 9.2.x Websocket Server连接在使用Firefox而不是Chrome时连接后自动关闭的主要内容,如果未能解决你的问题,请参考以下文章

Jetty 如何创建自定义 WebSocket

Jetty 8.1.1 Websocket 客户端握手

Jetty:套接字连接作为 websocket 连接

Jetty WebSocket 代理

jetty 9,websockets 和关闭服务器端的 websocket 连接

如何让 eclipse-jetty 插件扫描和识别 websocket 类?