Skip to content

Commit 822d40f

Browse files
committed
WebSocketClient supports reconnecting
Added two methods, reconnect() and reconnectBlocking() Added ReconnectExample Reused the Test 580 for this issue to make sure no threads are left running
1 parent 45390ea commit 822d40f

File tree

5 files changed

+308
-1
lines changed

5 files changed

+308
-1
lines changed

pom.xml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,14 @@
7373
</execution>
7474
</executions>
7575
</plugin>
76+
<plugin>
77+
<groupId>org.apache.maven.plugins</groupId>
78+
<artifactId>maven-compiler-plugin</artifactId>
79+
<configuration>
80+
<source>1.6</source>
81+
<target>1.6</target>
82+
</configuration>
83+
</plugin>
7684
</plugins>
7785
</build>
7886
<dependencies>
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
/*
2+
* Copyright (c) 2010-2018 Nathan Rajlich
3+
*
4+
* Permission is hereby granted, free of charge, to any person
5+
* obtaining a copy of this software and associated documentation
6+
* files (the "Software"), to deal in the Software without
7+
* restriction, including without limitation the rights to use,
8+
* copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
* copies of the Software, and to permit persons to whom the
10+
* Software is furnished to do so, subject to the following
11+
* conditions:
12+
*
13+
* The above copyright notice and this permission notice shall be
14+
* included in all copies or substantial portions of the Software.
15+
*
16+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17+
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
18+
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19+
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
20+
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
21+
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22+
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
23+
* OTHER DEALINGS IN THE SOFTWARE.
24+
*/
25+
26+
import org.java_websocket.WebSocketImpl;
27+
28+
import java.net.URI;
29+
import java.net.URISyntaxException;
30+
31+
/**
32+
* Simple example to reconnect blocking and non-blocking.
33+
*/
34+
public class ReconnectClientExample {
35+
public static void main( String[] args ) throws URISyntaxException, InterruptedException {
36+
WebSocketImpl.DEBUG = true;
37+
ExampleClient c = new ExampleClient( new URI( "ws://localhost:8887" ) );
38+
//Connect to a server normally
39+
c.connectBlocking();
40+
c.send( "hi" );
41+
Thread.sleep( 10 );
42+
c.closeBlocking();
43+
//Disconnect manually and reconnect blocking
44+
c.reconnectBlocking();
45+
c.send( "it's" );
46+
Thread.sleep( 10000 );
47+
c.closeBlocking();
48+
//Disconnect manually and reconnect
49+
c.reconnect();
50+
Thread.sleep( 100 );
51+
c.send( "me" );
52+
Thread.sleep( 100 );
53+
c.closeBlocking();
54+
}
55+
}

src/main/java/org/java_websocket/client/WebSocketClient.java

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,51 @@ public Socket getSocket() {
158158
return socket;
159159
}
160160

161+
/**
162+
* Reinitiates the websocket connection. This method does not block.
163+
* @since 1.3.8
164+
*/
165+
public void reconnect() {
166+
reset();
167+
connect();
168+
}
169+
170+
/**
171+
* Same as <code>reconnect</code> but blocks until the websocket reconnected or failed to do so.<br>
172+
* @return Returns whether it succeeded or not.
173+
* @throws InterruptedException Thrown when the threads get interrupted
174+
* @since 1.3.8
175+
*/
176+
public boolean reconnectBlocking() throws InterruptedException {
177+
reset();
178+
return connectBlocking();
179+
}
180+
181+
/**
182+
* Reset everything relevant to allow a reconnect
183+
*
184+
* @since 1.3.8
185+
*/
186+
private void reset() {
187+
close();
188+
this.draft.reset();
189+
if (this.socket != null) {
190+
try {
191+
this.socket.close();
192+
} catch ( IOException e ) {
193+
e.printStackTrace();
194+
}
195+
try {
196+
this.socket = new Socket( this.socket.getInetAddress(), this.socket.getPort() );
197+
} catch ( IOException e ) {
198+
e.printStackTrace();
199+
}
200+
}
201+
connectLatch = new CountDownLatch( 1 );
202+
closeLatch = new CountDownLatch( 1 );
203+
this.engine = new WebSocketImpl( this, this.draft );
204+
}
205+
161206
/**
162207
* Initiates the websocket connection. This method does not block.
163208
*/
@@ -538,6 +583,7 @@ public void run() {
538583
handleIOException( e );
539584
} finally {
540585
closeSocket();
586+
writeThread = null;
541587
}
542588
}
543589
}

src/test/java/org/java_websocket/issues/AllIssueTests.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,8 @@
3232
@Suite.SuiteClasses({
3333
org.java_websocket.issues.Issue609Test.class,
3434
org.java_websocket.issues.Issue621Test.class,
35-
org.java_websocket.issues.Issue580Test.class
35+
org.java_websocket.issues.Issue580Test.class,
36+
org.java_websocket.issues.Issue256Test.class
3637
})
3738
/**
3839
* Start all tests for issues
Lines changed: 197 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,197 @@
1+
/*
2+
* Copyright (c) 2010-2018 Nathan Rajlich
3+
*
4+
* Permission is hereby granted, free of charge, to any person
5+
* obtaining a copy of this software and associated documentation
6+
* files (the "Software"), to deal in the Software without
7+
* restriction, including without limitation the rights to use,
8+
* copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
* copies of the Software, and to permit persons to whom the
10+
* Software is furnished to do so, subject to the following
11+
* conditions:
12+
*
13+
* The above copyright notice and this permission notice shall be
14+
* included in all copies or substantial portions of the Software.
15+
*
16+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17+
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
18+
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19+
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
20+
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
21+
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22+
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
23+
* OTHER DEALINGS IN THE SOFTWARE.
24+
*/
25+
26+
package org.java_websocket.issues;
27+
28+
import org.java_websocket.WebSocket;
29+
import org.java_websocket.WebSocketImpl;
30+
import org.java_websocket.client.WebSocketClient;
31+
import org.java_websocket.handshake.ClientHandshake;
32+
import org.java_websocket.handshake.ServerHandshake;
33+
import org.java_websocket.server.WebSocketServer;
34+
import org.java_websocket.util.SocketUtil;
35+
import org.java_websocket.util.ThreadCheck;
36+
import org.junit.Rule;
37+
import org.junit.Test;
38+
39+
import java.net.InetSocketAddress;
40+
import java.net.URI;
41+
import java.util.concurrent.CountDownLatch;
42+
43+
public class Issue256Test {
44+
45+
@Rule
46+
public ThreadCheck zombies = new ThreadCheck();
47+
48+
private void runTestScenarioReconnect(boolean reconnectBlocking) throws Exception {
49+
final CountDownLatch countServerDownLatch = new CountDownLatch( 1 );
50+
int port = SocketUtil.getAvailablePort();
51+
WebSocketServer ws = new WebSocketServer( new InetSocketAddress( port ) ) {
52+
@Override
53+
public void onOpen( WebSocket conn, ClientHandshake handshake ) {
54+
55+
}
56+
57+
@Override
58+
public void onClose( WebSocket conn, int code, String reason, boolean remote ) {
59+
60+
}
61+
62+
@Override
63+
public void onMessage( WebSocket conn, String message ) {
64+
65+
}
66+
67+
@Override
68+
public void onError( WebSocket conn, Exception ex ) {
69+
70+
}
71+
72+
@Override
73+
public void onStart() {
74+
countServerDownLatch.countDown();
75+
}
76+
};
77+
ws.start();
78+
countServerDownLatch.await();
79+
WebSocketClient clt = new WebSocketClient( new URI( "ws://localhost:" + port ) ) {
80+
@Override
81+
public void onOpen( ServerHandshake handshakedata ) {
82+
83+
}
84+
85+
@Override
86+
public void onMessage( String message ) {
87+
88+
}
89+
90+
@Override
91+
public void onClose( int code, String reason, boolean remote ) {
92+
93+
}
94+
95+
@Override
96+
public void onError( Exception ex ) {
97+
98+
}
99+
};
100+
clt.connectBlocking();
101+
clt.send("test");
102+
clt.getSocket().close();
103+
if (reconnectBlocking) {
104+
clt.reconnectBlocking();
105+
} else {
106+
clt.reconnect();
107+
}
108+
Thread.sleep( 100 );
109+
110+
ws.stop();
111+
Thread.sleep( 100 );
112+
}
113+
114+
@Test
115+
public void runReconnectBlockingScenario0() throws Exception {
116+
runTestScenarioReconnect(true);
117+
}
118+
@Test
119+
public void runReconnectBlockingScenario1() throws Exception {
120+
runTestScenarioReconnect(true);
121+
}
122+
@Test
123+
public void runReconnectBlockingScenario2() throws Exception {
124+
runTestScenarioReconnect(true);
125+
}
126+
@Test
127+
public void runReconnectBlockingScenario3() throws Exception {
128+
runTestScenarioReconnect(true);
129+
}
130+
@Test
131+
public void runReconnectBlockingScenario4() throws Exception {
132+
runTestScenarioReconnect(true);
133+
}
134+
@Test
135+
public void runReconnectBlockingScenario5() throws Exception {
136+
runTestScenarioReconnect(true);
137+
}
138+
@Test
139+
public void runReconnectBlockingScenario6() throws Exception {
140+
runTestScenarioReconnect(true);
141+
}
142+
@Test
143+
public void runReconnectBlockingScenario7() throws Exception {
144+
runTestScenarioReconnect(true);
145+
}
146+
@Test
147+
public void runReconnectBlockingScenario8() throws Exception {
148+
runTestScenarioReconnect(true);
149+
}
150+
@Test
151+
public void runReconnectBlockingScenario9() throws Exception {
152+
runTestScenarioReconnect(true);
153+
}
154+
155+
@Test
156+
public void runReconnectScenario0() throws Exception {
157+
runTestScenarioReconnect(false);
158+
}
159+
@Test
160+
public void runReconnectScenario1() throws Exception {
161+
runTestScenarioReconnect(false);
162+
}
163+
@Test
164+
public void runReconnectScenario2() throws Exception {
165+
runTestScenarioReconnect(false);
166+
}
167+
@Test
168+
public void runReconnectScenario3() throws Exception {
169+
runTestScenarioReconnect(false);
170+
}
171+
@Test
172+
public void runReconnectScenario4() throws Exception {
173+
runTestScenarioReconnect(false);
174+
}
175+
@Test
176+
public void runReconnectScenario5() throws Exception {
177+
runTestScenarioReconnect(false);
178+
}
179+
@Test
180+
public void runReconnectScenario6() throws Exception {
181+
runTestScenarioReconnect(false);
182+
}
183+
@Test
184+
public void runReconnectScenario7() throws Exception {
185+
runTestScenarioReconnect(false);
186+
}
187+
@Test
188+
public void runReconnectScenario8() throws Exception {
189+
runTestScenarioReconnect(false);
190+
}
191+
@Test
192+
public void runReconnectScenario9() throws Exception {
193+
runTestScenarioReconnect(false);
194+
}
195+
196+
}
197+

0 commit comments

Comments
 (0)