View Javadoc
1   /*
2    * Copyright 2012 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    *   http://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  //The MIT License
17  //
18  //Copyright (c) 2009 Carl Bystršm
19  //
20  //Permission is hereby granted, free of charge, to any person obtaining a copy
21  //of this software and associated documentation files (the "Software"), to deal
22  //in the Software without restriction, including without limitation the rights
23  //to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
24  //copies of the Software, and to permit persons to whom the Software is
25  //furnished to do so, subject to the following conditions:
26  //
27  //The above copyright notice and this permission notice shall be included in
28  //all copies or substantial portions of the Software.
29  //
30  //THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
31  //IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
32  //FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
33  //AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
34  //LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
35  //OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
36  //THE SOFTWARE.
37  package org.jboss.netty.example.http.websocketx.client;
38  
39  import org.jboss.netty.bootstrap.ClientBootstrap;
40  import org.jboss.netty.buffer.ChannelBuffers;
41  import org.jboss.netty.channel.Channel;
42  import org.jboss.netty.channel.ChannelFuture;
43  import org.jboss.netty.channel.ChannelPipeline;
44  import org.jboss.netty.channel.ChannelPipelineFactory;
45  import org.jboss.netty.channel.Channels;
46  import org.jboss.netty.channel.socket.nio.NioClientSocketChannelFactory;
47  import org.jboss.netty.handler.codec.http.HttpRequestEncoder;
48  import org.jboss.netty.handler.codec.http.HttpResponseDecoder;
49  import org.jboss.netty.handler.codec.http.websocketx.CloseWebSocketFrame;
50  import org.jboss.netty.handler.codec.http.websocketx.PingWebSocketFrame;
51  import org.jboss.netty.handler.codec.http.websocketx.TextWebSocketFrame;
52  import org.jboss.netty.handler.codec.http.websocketx.WebSocketClientHandshaker;
53  import org.jboss.netty.handler.codec.http.websocketx.WebSocketClientHandshakerFactory;
54  import org.jboss.netty.handler.codec.http.websocketx.WebSocketVersion;
55  import org.jboss.netty.handler.ssl.SslContext;
56  import org.jboss.netty.handler.ssl.util.SelfSignedCertificate;
57  
58  import java.net.InetSocketAddress;
59  import java.net.URI;
60  import java.util.HashMap;
61  import java.util.Map;
62  import java.util.concurrent.Executors;
63  
64  public final class WebSocketClient {
65  
66      static final String URL = System.getProperty("url", "ws://127.0.0.1:8080/websocket");
67  
68      public static void main(String[] args) throws Exception {
69          URI uri = new URI(URL);
70          String scheme = uri.getScheme() == null? "http" : uri.getScheme();
71          final String host = uri.getHost() == null? "127.0.0.1" : uri.getHost();
72          final int port;
73          if (uri.getPort() == -1) {
74              if ("http".equalsIgnoreCase(scheme)) {
75                  port = 80;
76              } else if ("https".equalsIgnoreCase(scheme)) {
77                  port = 443;
78              } else {
79                  port = -1;
80              }
81          } else {
82              port = uri.getPort();
83          }
84  
85          if (!"ws".equalsIgnoreCase(scheme) && !"wss".equalsIgnoreCase(scheme)) {
86              System.err.println("Only WS(S) is supported.");
87              return;
88          }
89  
90          final boolean ssl = "wss".equalsIgnoreCase(scheme);
91          final SslContext sslCtx;
92          if (ssl) {
93              SelfSignedCertificate ssc = new SelfSignedCertificate();
94              sslCtx = SslContext.newServerContext(ssc.certificate(), ssc.privateKey());
95          } else {
96              sslCtx = null;
97          }
98  
99          Map<String, String> customHeaders = new HashMap<String, String>();
100         customHeaders.put("MyHeader", "MyValue");
101 
102         ClientBootstrap bootstrap =
103                 new ClientBootstrap(
104                         new NioClientSocketChannelFactory(
105                                 Executors.newCachedThreadPool(),
106                                 Executors.newCachedThreadPool()));
107 
108         Channel ch = null;
109         try {
110             // Connect with V13 (RFC 6455 aka HyBi-17). You can change it to V08 or V00.
111             // If you change it to V00, ping is not supported and remember to change
112             // HttpResponseDecoder to WebSocketHttpResponseDecoder in the pipeline.
113             final WebSocketClientHandshaker handshaker =
114                     new WebSocketClientHandshakerFactory().newHandshaker(
115                             uri, WebSocketVersion.V13, null, false, customHeaders);
116 
117             bootstrap.setPipelineFactory(new ChannelPipelineFactory() {
118                 public ChannelPipeline getPipeline() {
119                     ChannelPipeline pipeline = Channels.pipeline();
120 
121                     if (sslCtx != null) {
122                         pipeline.addLast("ssl", sslCtx.newHandler(host, port));
123                     }
124                     pipeline.addLast("decoder", new HttpResponseDecoder());
125                     pipeline.addLast("encoder", new HttpRequestEncoder());
126                     pipeline.addLast("ws-handler", new WebSocketClientHandler(handshaker));
127                     return pipeline;
128                 }
129             });
130 
131             // Connect.
132             ChannelFuture future = bootstrap.connect(new InetSocketAddress(host, port));
133             ch = future.sync().getChannel();
134 
135             handshaker.handshake(ch).sync();
136 
137             // Send 10 messages and wait for responses
138             for (int i = 0; i < 1000; i++) {
139                 ch.write(new TextWebSocketFrame("Message #" + i));
140             }
141 
142             // Ping
143             ch.write(new PingWebSocketFrame(ChannelBuffers.wrappedBuffer(new byte[] { 1, 2, 3, 4, 5, 6 })));
144 
145             // Close
146             ch.write(new CloseWebSocketFrame());
147 
148             // WebSocketClientHandler will close the connection when the server
149             // responds to the CloseWebSocketFrame.
150             ch.getCloseFuture().sync();
151         } finally {
152             if (ch != null) {
153                 ch.close();
154             }
155             bootstrap.releaseExternalResources();
156         }
157     }
158 }