使用HttpClientUpgradeHandler建立Websocketconnection?

时间:2018-07-31 10:30:06

标签: websocket netty handshake

我尝试建立一个websocketconnection。但是我的websocketcontent一直因为不可读而被拒绝。现在,我使用以下处理程序堆栈建立连接:

p.addLast(ClientSslHandler),
p.addLast(new HttpClientCodec()),
p.addLast(new HttpObjectAggregator(8192)),
p.addLast(new WebSocketClientProtocolHandler(...)),
p.addlast(new myHandler);

问题是(我认为)HttpClientCodec一直将我的Websocketframes编码为Httpframes。 这就是为什么我认为我可以使用HttpClientUpgradeHandler来处理握手,然后更改为纯Websocketconnection的原因。这是可行的解决方案吗?还是有其他解决方法?

编辑:将WebSocketClientProtocolHandler更改为HttpClientUpgradeHandler

Edit2:     公共类ShipSocketClient {         静态最终字符串URL = System.getProperty(“ url”,“ wss://10.2.3.44:4712”);

public static void main(String[] args) throws Exception{

    URI uri = new URI(URL);
    String scheme = uri.getScheme() == null? "ws" : uri.getScheme();
    final String host = uri.getHost() == null? "127.0.0.1" : uri.getHost();
    final int port;
    if (uri.getPort() == -1) {
        if ("ws".equalsIgnoreCase(scheme)) {
            port = 80;
        } else if ("wss".equalsIgnoreCase(scheme)) {
            port = 443;
        } else {
            port = -1;
        }
    } else {
        port = uri.getPort();
    }

    if (!"ws".equalsIgnoreCase(scheme) && !"wss".equalsIgnoreCase(scheme)) {
        System.err.println("Only WS(S) is supported.");
        return;
    }

    final boolean ssl = "wss".equalsIgnoreCase(scheme);
    final SslContext sslCtx;
    if (ssl) {          
        List<String> CipherList = new ArrayList<String>();
        CipherList.add("TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256");
        //CipherList.add("TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8");
        CipherList.add("TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256");


    File vidksFile = new File("C:\\Users\\LETTAU\\Videos\\key.pem");
    File vidcertFile = new File("C:\\Users\\LETTAU\\Videos\\cert.pem");
    //CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");


    sslCtx = SslContextBuilder.forClient()
            .trustManager(InsecureTrustManagerFactory.INSTANCE)                
            .ciphers(CipherList)
            .protocols("TLSv1.2")         
            .clientAuth(ClientAuth.REQUIRE)            
            .keyManager(vidcertFile, vidksFile)                            
            .build();  
    }
    else{
        sslCtx = null;
    }

    EventLoopGroup group = new NioEventLoopGroup();
    try{

        WebSocketClientHandshaker wsHandShaker = WebSocketClientHandshakerFactory.newHandshaker(
                uri, WebSocketVersion.V13, "ship", false, new DefaultHttpHeaders());
        WebSocketClientProtocolHandler wsPrClHandler = new WebSocketClientProtocolHandler(wsHandShaker,true);            



        Bootstrap b = new Bootstrap();
        b.group(group)
         .channel(NioSocketChannel.class)
         .handler(new ChannelInitializer<SocketChannel>() {

             @Override
             protected void initChannel(SocketChannel ch) {

                 ChannelPipeline p = ch.pipeline();
                 SslHandler ClientSslHandler = sslCtx.newHandler(ch.alloc(), host, port);                     
                 HttpClientCodec sourceCodec = new HttpClientCodec(); 

                 //New approach with HttpClientUpgradeHandler
                 //ShipClientProtocolHandler is a class which extends WebSocketClientProtocolHandler implements HttpClientUpgradeHandler.UpgradeCodec
                 HttpClientUpgradeHandler httpToWsUpgrader = new HttpClientUpgradeHandler(sourceCodec, new ShipClientProtocolHandler(wsHandShaker,true), 8096);

                 if (sslCtx != null) {                       
                     p.addLast(new LoggingHandler(LogLevel.INFO));
                     p.addLast(ClientSslHandler);
                 }
                 p.addLast(                          
                         new LoggingHandler(LogLevel.INFO),                          
                         sourceCodec,
                         new HttpObjectAggregator(8192),
                         //httpToWsUpgrader,
                         new LoggingHandler(LogLevel.INFO),
                         wsPrClHandler);
                 }
             }
         );

        Channel ch = b.connect(uri.getHost(), port).sync().channel();


        BufferedReader console = new BufferedReader(new InputStreamReader(System.in));
        while (true) {
            String msg = console.readLine();
            if (msg == null) {
                break;                
            } else if ("ping".equals(msg.toLowerCase())) {
                WebSocketFrame frame = new PingWebSocketFrame(Unpooled.wrappedBuffer(new byte[] { 8, 1, 8, 1 }));
                ch.writeAndFlush(frame);
            } else if ("cmi".equals(msg.toLowerCase())) {    
                ByteBuf bBuf = Unpooled.buffer(16);
                bBuf.writeByte(0);
                bBuf.writeByte(0);
                BinaryWebSocketFrame bytebuffer = new BinaryWebSocketFrame(bBuf); 
                ch.writeAndFlush(bytebuffer);
            } else if ("cdp".equals(msg.toLowerCase())) { 
                ByteBuf bBuf = Unpooled.buffer(1000);
                //bBuf.writeByte(0);
                //bBuf.writeByte(1);
                ByteBufUtil.writeUtf8(bBuf,"{\"connectionHello\":[{\"phase\":\"ready\"},{\"waiting\":60000}]}");
                BinaryWebSocketFrame bytebuffer = new BinaryWebSocketFrame(bBuf);                   
                ch.writeAndFlush(bytebuffer);                   
            } else {
                WebSocketFrame frame = new TextWebSocketFrame(msg);                    
                ch.writeAndFlush(frame);                    
            }
        }
    } finally {
        group.shutdownGracefully();
        }
    }

Edit3:关于为什么我认为HttpClientCodec是问题的一些其他信息: 这是收到的包裹的样子:

         +-------------------------------------------------+
         |  0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f |
+--------+-------------------------------------------------+----------------+
|00000000| 88 1d 11 30 53 54 41 54 45 5f 57 41 49 54 5f 43 |...0STATE_WAIT_C|
|00000010| 4c 4f 53 45 5f 43 4f 4e 4e 45 43 54 49 4f 4e    |LOSE_CONNECTION |
+--------+-------------------------------------------------+----------------+

这是外发包裹的样子:

         +-------------------------------------------------+
         |  0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f |
+--------+-------------------------------------------------+----------------+
|00000000| 82 9d 12 1e 8c 5a 12 1f f7 78 71 71 e2 34 77 7d |.....Z...xqq.4w}|
|00000010| f8 33 7d 70 c4 3f 7e 72 e3 78 28 3c fe 3f 73 7a |.3}p.?~r.x(<.?sz|
|00000020| f5 78 6f                                        |.xo             |
+--------+-------------------------------------------------+----------------+

1 个答案:

答案 0 :(得分:0)

如果要升级到WebSocket,则应使用WebSocketClientHandshaker

Netty本身包含一个示例:

https://github.com/netty/netty/tree/netty-4.1.28.Final/example/src/main/java/io/netty/example/http/websocketx/client