View Javadoc
1   /*
2    * Copyright 2014 The Netty Project
3    *
4    * The Netty Project licenses this file to you under the Apache License,
5    * version 2.0 (the "License"); you may not use this file except in compliance
6    * with the License. You may obtain a copy of the License at:
7    *
8    *   https://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12   * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13   * License for the specific language governing permissions and limitations
14   * under the License.
15   */
16  package io.netty.example.http.websocketx.client;
17  
18  import io.netty.bootstrap.Bootstrap;
19  import io.netty.buffer.Unpooled;
20  import io.netty.channel.Channel;
21  import io.netty.channel.ChannelInitializer;
22  import io.netty.channel.ChannelPipeline;
23  import io.netty.channel.EventLoopGroup;
24  import io.netty.channel.nio.NioEventLoopGroup;
25  import io.netty.channel.socket.SocketChannel;
26  import io.netty.channel.socket.nio.NioSocketChannel;
27  import io.netty.handler.codec.http.DefaultHttpHeaders;
28  import io.netty.handler.codec.http.HttpClientCodec;
29  import io.netty.handler.codec.http.HttpObjectAggregator;
30  import io.netty.handler.codec.http.websocketx.CloseWebSocketFrame;
31  import io.netty.handler.codec.http.websocketx.PingWebSocketFrame;
32  import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
33  import io.netty.handler.codec.http.websocketx.WebSocketClientHandshakerFactory;
34  import io.netty.handler.codec.http.websocketx.WebSocketFrame;
35  import io.netty.handler.codec.http.websocketx.WebSocketVersion;
36  import io.netty.handler.codec.http.websocketx.extensions.compression.WebSocketClientCompressionHandler;
37  import io.netty.handler.ssl.SslContext;
38  import io.netty.handler.ssl.SslContextBuilder;
39  import io.netty.handler.ssl.util.InsecureTrustManagerFactory;
40  
41  import java.io.BufferedReader;
42  import java.io.InputStreamReader;
43  import java.net.URI;
44  
45  /**
46   * This is an example of a WebSocket client.
47   * <p>
48   * In order to run this example you need a compatible WebSocket server.
49   * Therefore you can either start the WebSocket server from the examples
50   * by running {@link io.netty.example.http.websocketx.server.WebSocketServer}
51   * or connect to an existing WebSocket server such as
52   * <a href="https://www.websocket.org/echo.html">ws://echo.websocket.org</a>.
53   * <p>
54   * The client will attempt to connect to the URI passed to it as the first argument.
55   * You don't have to specify any arguments if you want to connect to the example WebSocket server,
56   * as this is the default.
57   */
58  public final class WebSocketClient {
59  
60      static final String URL = System.getProperty("url", "ws://127.0.0.1:8080/websocket");
61  
62      public static void main(String[] args) throws Exception {
63          URI uri = new URI(URL);
64          String scheme = uri.getScheme() == null? "ws" : uri.getScheme();
65          final String host = uri.getHost() == null? "127.0.0.1" : uri.getHost();
66          final int port;
67          if (uri.getPort() == -1) {
68              if ("ws".equalsIgnoreCase(scheme)) {
69                  port = 80;
70              } else if ("wss".equalsIgnoreCase(scheme)) {
71                  port = 443;
72              } else {
73                  port = -1;
74              }
75          } else {
76              port = uri.getPort();
77          }
78  
79          if (!"ws".equalsIgnoreCase(scheme) && !"wss".equalsIgnoreCase(scheme)) {
80              System.err.println("Only WS(S) is supported.");
81              return;
82          }
83  
84          final boolean ssl = "wss".equalsIgnoreCase(scheme);
85          final SslContext sslCtx;
86          if (ssl) {
87              sslCtx = SslContextBuilder.forClient()
88                  .trustManager(InsecureTrustManagerFactory.INSTANCE).build();
89          } else {
90              sslCtx = null;
91          }
92  
93          EventLoopGroup group = new NioEventLoopGroup();
94          try {
95              // Connect with V13 (RFC 6455 aka HyBi-17). You can change it to V08 or V00.
96              // If you change it to V00, ping is not supported and remember to change
97              // HttpResponseDecoder to WebSocketHttpResponseDecoder in the pipeline.
98              final WebSocketClientHandler handler =
99                      new WebSocketClientHandler(
100                             WebSocketClientHandshakerFactory.newHandshaker(
101                                     uri, WebSocketVersion.V13, null, true, new DefaultHttpHeaders()));
102 
103             Bootstrap b = new Bootstrap();
104             b.group(group)
105              .channel(NioSocketChannel.class)
106              .handler(new ChannelInitializer<SocketChannel>() {
107                  @Override
108                  protected void initChannel(SocketChannel ch) {
109                      ChannelPipeline p = ch.pipeline();
110                      if (sslCtx != null) {
111                          p.addLast(sslCtx.newHandler(ch.alloc(), host, port));
112                      }
113                      p.addLast(
114                              new HttpClientCodec(),
115                              new HttpObjectAggregator(8192),
116                              WebSocketClientCompressionHandler.INSTANCE,
117                              handler);
118                  }
119              });
120 
121             Channel ch = b.connect(uri.getHost(), port).sync().channel();
122             handler.handshakeFuture().sync();
123 
124             BufferedReader console = new BufferedReader(new InputStreamReader(System.in));
125             while (true) {
126                 String msg = console.readLine();
127                 if (msg == null) {
128                     break;
129                 } else if ("bye".equals(msg.toLowerCase())) {
130                     ch.writeAndFlush(new CloseWebSocketFrame());
131                     ch.closeFuture().sync();
132                     break;
133                 } else if ("ping".equals(msg.toLowerCase())) {
134                     WebSocketFrame frame = new PingWebSocketFrame(Unpooled.wrappedBuffer(new byte[] { 8, 1, 8, 1 }));
135                     ch.writeAndFlush(frame);
136                 } else {
137                     WebSocketFrame frame = new TextWebSocketFrame(msg);
138                     ch.writeAndFlush(frame);
139                 }
140             }
141         } finally {
142             group.shutdownGracefully();
143         }
144     }
145 }