1

我正在尝试使用 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));
}
4

1 回答 1

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);此处理程序中的内容。

看看这个井字游戏了解更多信息。github中还有很多关于如何执行此操作的链接信息。

于 2012-08-15T16:41:31.933 回答