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