Jetty的WebSocket连接中的消息不能包含任何HTTP方法关键字?

时间:2012-09-22 16:18:45

标签: html5 websocket jetty

我正在实施Jetty的WebSocket.OnTextMessage。当我在onMessage(String)中收到消息时,我可以使用之前从onOpen(Connection)获取的Connection对象进行回复,并且客户端会正确接收它。

但是,当我想使用connection.sendMessage(String)从服务器推送消息(即没有来自客户端的初始消息)时,客户端不会收到它。看起来消息正在被缓冲,但我找不到任何方法来刷新它。

有谁知道如何解决这个问题?也许我做错了。 这就是我所做的

public void onOpen(final Connection connection) {
    this.connection = connection;
}

然后是另一个事件

public void onReceive(BytesXMLMessage bytesXMLMessage) {
    byte[] data = ((BytesMessageImpl) bytesXMLMessage).getData();
    String msgToClient = new String(data);
    this.connection.sendMessage(msgToClient);
    System.out.println("onReceive:" + msgToClient);
}

但客户端从未收到该消息

更新:找到模式,只要包含HTTP方法关键字(如GET,POST,PUT,HEAD等),无论是大写还是小写,都不会将消息发送到客户端。

无论如何都要缓解这个问题吗?

更新:这是可以模拟问题的WebSocketServlet的非常简化的实现

package com.test.websocket;

import org.eclipse.jetty.websocket.WebSocket;

import javax.servlet.http.HttpServletRequest;
import java.io.IOException;

public class WebSocketServlet extends org.eclipse.jetty.websocket.WebSocketServlet {
    @Override
    public WebSocket doWebSocketConnect(HttpServletRequest request, String protocol) {
        return new WebSocket.OnTextMessage() {
            private Connection connection;
            @Override
            public void onMessage(String data) {
                try {
                    connection.sendMessage("Echo: " + data);
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

            @Override
            public void onOpen(Connection connection) {
                this.connection = connection;
            }

            @Override
            public void onClose(int closeCode, String message) {
                connection.close();
            }
        };
    }
}

这是web.xml

<!DOCTYPE web-app PUBLIC
 "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
 "http://java.sun.com/dtd/web-app_2_3.dtd" >

<web-app>
    <servlet>
        <servlet-name>EchoWebSocket</servlet-name>
        <servlet-class>com.test.websocket.WebSocketServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>EchoWebSocket</servlet-name>
        <url-pattern>/*</url-pattern>
    </servlet-mapping>
</web-app>

3 个答案:

答案 0 :(得分:2)

找到无法发送HTTP方法关键字的根本原因。它是由在网络层拦截所有HTTP方法关键字的开发机器上运行的Antivirus Kaspersky引起的,它必须在适当的标准HTTP协议下工作。也许它还不支持websocket协议。

感谢@jesse mcconnell正在帮助创建单元测试。

答案 1 :(得分:0)

[edit]

我无法通过单元测试验证这一点,我让客户端发送“GET”消息,然后服务器端返回相同的字符串,客户端接收它。如果您有更多相关信息,请打开一个问题,如果您愿意,可以在RT / Jetty项目下的bugs.eclipse.org上进行复制。

此时,如果您可以发布一些代码来查看或可能有所帮助的内容,我倾向于您的实施问题。

这是您描述的新测试用例: http://git.eclipse.org/c/jetty/org.eclipse.jetty.project.git/commit/?id=494f7e48fcc20c51066cd91a6dac1d738cacb54e

答案 2 :(得分:0)

websocket协议旨在避免看起来像HTTP流量。具体来说,它将随机掩码应用于从客户端发送到服务器的所有帧的有效负载,这样websocket消息就不太可能看起来像HTTP请求。

然而,该协议不会屏蔽从服务器发送到客户端的有效负载,因为他们认为可能会在该方向上利用流量来利用攻击媒介。

我想我们并不认为像你的防火墙那样的中间人可能会对他们所寻找和阻止的内容有点严格。我无法想象为什么他们阻止这样的流量,因为我可以想象它也会像XMPP消息一样阻止像“不要忘记吃牛奶!”这样的文字。但它确实......所以唯一真正的选择是你:

  1. 自己编码有效负载内容并在客户端解码。
  2. 关闭防火墙(或使其失谐)
  3. 修复防火墙。