在浏览器中使用Netty绑定文本消息和websocket

时间:2012-08-15 14:55:37

标签: java netty

我正在尝试使用Netty实现websockets。我尝试过DiscardServer示例,如果我只使用Telnet运行它就可以正常运行

  Telnet localhost 8090.

因此无论我在终端窗口中输入什么消息,它都会返回给我。但是现在我想在浏览器中实现相同的功能,就像我在文本区域中放置一些文本消息一样,它应该在浏览器上显示该文本消息。

我可以使用以下代码启动websocket服务器

    ChannelFactory factory = new NioServerSocketChannelFactory(
            Executors.newCachedThreadPool(),
            Executors.newCachedThreadPool());

    ServerBootstrap bootstrap = new ServerBootstrap(factory);

    bootstrap.setPipelineFactory(new ChannelPipelineFactory() {
        public ChannelPipeline getPipeline() {
            return Channels.pipeline(new DiscardServerHandler());
        }
    });

    bootstrap.setOption("child.tcpNoDelay", true);
    bootstrap.setOption("child.keepAlive", true);

    bootstrap.bind(new InetSocketAddress(8090));

但是如何将文本区域中的文本消息与websocket服务器

绑定

---- ----更新

我创建了MyServerHandler类

   public class MyServerHandler extends SimpleChannelUpstreamHandler {

@Override
public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) {
    Object msg = e.getMessage();        
    //msg.getClass();
    if (msg instanceof HttpRequest) {
                    //handleHttpRequest(ctx, (HttpRequest) msg);
        ctx.getChannel().write(msg);
    } else if (msg instanceof WebSocketFrame) {
        //handleWebSocketFrame(ctx, (WebSocketFrame) msg);
    }

}
  }

它的调用messageReceived方法,但不会进入任何if条件。

我也编写了WebSocketServerPipelineFactory类

   public class WebSocketServerPipelineFactory implements ChannelPipelineFactory {

@Override
    public ChannelPipeline getPipeline() throws Exception {
        // Create a default pipeline implementation.
        ChannelPipeline pipeline = pipeline();
        pipeline.addLast("decoder", new HttpRequestDecoder());
        pipeline.addLast("aggregator", new HttpChunkAggregator(65536));
        pipeline.addLast("encoder", new HttpResponseEncoder());
        pipeline.addLast("handler", new MyServerHandler());
        return pipeline;
    }
    }

我认为它也不是这个类的调用方法。

在jsp文件中我写了

   <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.6.4/jquery.min.js"  type="text/javascript"></script>
   <script>
   var MESSAGE_HANDSHAKE = "handshake";
   var MESSAGE_OPPONENT_UPDATE = "response";
   var MESSAGE_TURN_INDICATOR = "turn";
   var MESSAGE_GAME_OVER = "game_over";
   var WEBSOCKET_URL = "ws://localhost:8090";
   $(document).ready(function() {
   ws = new WebSocket(WEBSOCKET_URL);

   ws.onopen = function(event) { 
 alert("test");
 $('#status').text("Waiting...."); 
  };

   ws.onmessage = function(event) {
    var message = jQuery.parseJSON(event.data);

    alert(message.type);
   }

   }); 

<body>
 <p id="status">&nbsp;</p>
</body>

它不会使用任何jquery方法。我还缺少什么吗?

另外,如果我写

  ws.send("Test Message");

它抛出以下java脚本错误

 Uncaught Error: INVALID_STATE_ERR: DOM Exception 11 login.htm:33
 (anonymous function) login.htm:33
 f.extend._Deferred.e.resolveWith jquery.min.js:2
 e.extend.ready jquery.min.js:2
 c.addEventListener.C

如果我使用

   var WEBSOCKET_URL = "wss://echo.websocket.org/";

然后它的工作原理是我无法连接到我的服务器吗?

我正在使用eclipse来运行此代码。我正在使用Apache Tomcat运行我的jsp代码,并通过运行WebsocketServer.class作为java应用程序来运行websocket服务器。这有什么不同吗?

---已更新---

我在MyServerHandler类中编写了以下方法,并在浏览器中获取错误

 Error during WebSocket handshake: 'Sec-WebSocket-Accept' header is missing 

MySeverHandler.java

  private void handleHttpRequest(ChannelHandlerContext ctx, HttpRequest req)
        throws Exception {

    // Allow only GET methods.
    if (req.getMethod() != HttpMethod.GET) {
    //  sendHttpResponse(ctx, req, new DefaultHttpResponse(
        //      HttpVersion.HTTP_1_1, HttpResponseStatus.FORBIDDEN));
        return;
    }

    // Serve the WebSocket handshake request.
    if (req.getUri().equals(WEBSOCKET_PATH)
            && Values.UPGRADE.equalsIgnoreCase(req.getHeader(CONNECTION))
            && WEBSOCKET.equalsIgnoreCase(req.getHeader(Names.UPGRADE))) {

        // Create the WebSocket handshake response.
        HttpResponse res = new DefaultHttpResponse(
                HTTP_1_1,
                new HttpResponseStatus(101, "Web Socket Protocol Handshake"));
        res.addHeader(Names.UPGRADE, WEBSOCKET);
        res.addHeader(CONNECTION, Values.UPGRADE);


        // Upgrade the connection and send the handshake response.
        ChannelPipeline p = ctx.getChannel().getPipeline();
        p.remove("aggregator");
        p.replace("decoder", "wsdecoder", new WebSocketFrameDecoder());

        // Write handshake response to the channel
        ctx.getChannel().write(res);

        // Upgrade encoder to WebSocketFrameEncoder
        p.replace("encoder", "wsencoder", new WebSocketFrameEncoder());

        // Initialize the game. Assign players to a game and assign them a letter (X or O)
        ///initGame(ctx);

        return;
    }

    // Send an error page otherwise.
    sendHttpResponse(ctx, req, new DefaultHttpResponse(
            HttpVersion.HTTP_1_1, HttpResponseStatus.FORBIDDEN));
}

1 个答案:

答案 0 :(得分:1)

Netty使用责任链设计模式,因此无论何时需要使用协议,您都需要在管道中创建适当的解码器/编码器。对于websocket,这里是一个示例管道。

public class WebSocketServerPipelineFactory implements ChannelPipelineFactory {
    public ChannelPipeline getPipeline() throws Exception {
            // Create a default pipeline implementation.
            ChannelPipeline pipeline = pipeline();
            pipeline.addLast("decoder", new HttpRequestDecoder());
            pipeline.addLast("aggregator", new HttpChunkAggregator(65536));
            pipeline.addLast("encoder", new HttpResponseEncoder());
            pipeline.addLast("handler", new YourBusinessHandler());
            return pipeline;
    }

}

您可以在商务处理程序中编写任何业务逻辑。在这种情况下,您只需回显您收到的内容,这样就会在此处理程序中显示channel.write(incomingMessage);

有关详细信息,请查看此tic-tac-toe game。此外,github还有许多关于如何执行此操作的链接信息。