1

Nettyを使用してWebSocketを実装しようとしています。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コードを実行し、JavaアプリケーションとしてWebsocketServer.classを実行して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はChainofResponsibleデザインパターンを使用しているため、プロトコルを使用する必要がある場合は常に、パイプラインに適切なデコーダー/エンコーダーを作成する必要があります。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 に答える