@@ -74,6 +74,8 @@ public WebSocketClient(URI serverURI) {
7474 * specified URI. The client does not attampt to connect automatically. You
7575 * must call <var>connect</var> first to initiate the socket connection.
7676 * @param serverUri The <tt>URI</tt> of the WebSocket server to connect to.
77+ * @throws IllegalArgumentException If <var>draft</var>
78+ * is <code>WebSocketDraft.AUTO</code>
7779 */
7880 public WebSocketClient (URI serverUri , WebSocketDraft draft ) {
7981 this .uri = serverUri ;
@@ -94,7 +96,7 @@ public URI getURI() {
9496
9597 @ Override
9698 public WebSocketDraft getDraft () {
97- return this . draft ;
99+ return draft ;
98100 }
99101
100102 /**
@@ -103,8 +105,10 @@ public WebSocketDraft getDraft() {
103105 * <var>setURI</var>.
104106 */
105107 public void connect () {
106- this .running = true ;
107- (new Thread (this )).start ();
108+ if (!running ) {
109+ this .running = true ;
110+ (new Thread (this )).start ();
111+ }
108112 }
109113
110114 /**
@@ -113,9 +117,11 @@ public void connect() {
113117 * @throws IOException When socket related I/O errors occur.
114118 */
115119 public void close () throws IOException {
116- this .running = false ;
117- selector .wakeup ();
118- conn .close ();
120+ if (running ) {
121+ this .running = false ;
122+ selector .wakeup ();
123+ conn .close ();
124+ }
119125 }
120126
121127 /**
@@ -124,22 +130,18 @@ public void close() throws IOException {
124130 * @throws IOException When socket related I/O errors occur.
125131 */
126132 public void send (String text ) throws IOException {
127- conn .send (text );
128- }
129-
130- // Runnable IMPLEMENTATION /////////////////////////////////////////////////
131- public void run () {
132- int port = uri .getPort ();
133- if (port == -1 ) {
134- port = WebSocket .DEFAULT_PORT ;
133+ if (conn != null ) {
134+ conn .send (text );
135135 }
136-
136+ }
137+
138+ private boolean tryToConnect (InetSocketAddress remote ) {
137139 // The WebSocket constructor expects a SocketChannel that is
138140 // non-blocking, and has a Selector attached to it.
139141 try {
140142 client = SocketChannel .open ();
141143 client .configureBlocking (false );
142- client .connect (new InetSocketAddress ( uri . getHost (), port ) );
144+ client .connect (remote );
143145
144146 selector = Selector .open ();
145147
@@ -149,10 +151,16 @@ public void run() {
149151
150152 } catch (IOException ex ) {
151153 ex .printStackTrace ();
152- return ;
154+ return false ;
153155 }
156+
157+ return true ;
158+ }
159+
160+ // Runnable IMPLEMENTATION /////////////////////////////////////////////////
161+ public void run () {
162+ running = tryToConnect (new InetSocketAddress (uri .getHost (), getPort ()));
154163
155- // Continuous loop that is only supposed to end when "close" is called.
156164 while (this .running ) {
157165 try {
158166 selector .select ();
@@ -163,44 +171,10 @@ public void run() {
163171 SelectionKey key = i .next ();
164172 i .remove ();
165173
166- // When 'conn' has connected to the host
167174 if (key .isConnectable ()) {
168-
169- // Ensure connection is finished
170- if (client .isConnectionPending ()) {
171- client .finishConnect ();
172- }
173-
174- // Now that we're connected, re-register for only 'READ' keys.
175- client .register (selector , SelectionKey .OP_READ );
176-
177- // Now send the WebSocket client-side handshake
178- String path = uri .getPath ();
179- if (path .indexOf ("/" ) != 0 ) {
180- path = "/" + path ;
181- }
182- String host = uri .getHost () + (port != WebSocket .DEFAULT_PORT ? ":" + port : "" );
183- String origin = null ; // TODO: Make 'origin' configurable
184- String request = "GET " + path + " HTTP/1.1\r \n " +
185- "Upgrade: WebSocket\r \n " +
186- "Connection: Upgrade\r \n " +
187- "Host: " + host + "\r \n " +
188- "Origin: " + origin + "\r \n " ;
189- if (this .draft == WebSocketDraft .DRAFT76 ) {
190- request += "Sec-WebSocket-Key1: " + this .generateKey () + "\r \n " ;
191- request += "Sec-WebSocket-Key2: " + this .generateKey () + "\r \n " ;
192- this .key3 = new byte [8 ];
193- (new Random ()).nextBytes (this .key3 );
194- }
195- //extraHeaders.toString() +
196- request +="\r \n " ;
197- conn .socketChannel ().write (ByteBuffer .wrap (request .getBytes (WebSocket .UTF8_CHARSET )));
198- if (this .key3 != null ) {
199- conn .socketChannel ().write (ByteBuffer .wrap (this .key3 ));
200- }
175+ finishConnect ();
201176 }
202177
203- // When 'conn' has recieved some data
204178 if (key .isReadable ()) {
205179 conn .handleRead ();
206180 }
@@ -214,6 +188,50 @@ public void run() {
214188
215189 //System.err.println("WebSocketClient thread ended!");
216190 }
191+
192+ private int getPort () {
193+ int port = uri .getPort ();
194+ return port == -1 ? WebSocket .DEFAULT_PORT : port ;
195+ }
196+
197+ private void finishConnect () throws IOException {
198+ if (client .isConnectionPending ()) {
199+ client .finishConnect ();
200+ }
201+
202+ // Now that we're connected, re-register for only 'READ' keys.
203+ client .register (selector , SelectionKey .OP_READ );
204+
205+ sendHandshake ();
206+ }
207+
208+ private void sendHandshake () throws IOException {
209+ String path = uri .getPath ();
210+ if (path .indexOf ("/" ) != 0 ) {
211+ path = "/" + path ;
212+ }
213+ int port = getPort ();
214+ String host = uri .getHost () + (port != WebSocket .DEFAULT_PORT ? ":" + port : "" );
215+ String origin = null ; // TODO: Make 'origin' configurable
216+ String request = "GET " + path + " HTTP/1.1\r \n " +
217+ "Upgrade: WebSocket\r \n " +
218+ "Connection: Upgrade\r \n " +
219+ "Host: " + host + "\r \n " +
220+ "Origin: " + origin + "\r \n " ;
221+
222+ if (this .draft == WebSocketDraft .DRAFT76 ) {
223+ request += "Sec-WebSocket-Key1: " + this .generateKey () + "\r \n " ;
224+ request += "Sec-WebSocket-Key2: " + this .generateKey () + "\r \n " ;
225+ this .key3 = new byte [8 ];
226+ (new Random ()).nextBytes (this .key3 );
227+ }
228+
229+ request += "\r \n " ;
230+ conn .socketChannel ().write (ByteBuffer .wrap (request .getBytes (WebSocket .UTF8_CHARSET )));
231+ if (this .key3 != null ) {
232+ conn .socketChannel ().write (ByteBuffer .wrap (this .key3 ));
233+ }
234+ }
217235
218236 private String generateKey () {
219237 Random r = new Random ();
0 commit comments