Skip to content

Commit 350bcbe

Browse files
committed
Enabled user to specify which type of collection shall be used to hold the currently connected websockets. (TooTallNate#138)
Also removed the setAddress method since it is misleading and unnecessary.
1 parent f8529fb commit 350bcbe

File tree

1 file changed

+70
-35
lines changed

1 file changed

+70
-35
lines changed

src/main/java/org/java_websocket/server/WebSocketServer.java

Lines changed: 70 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,15 @@
1313
import java.nio.channels.ServerSocketChannel;
1414
import java.nio.channels.SocketChannel;
1515
import java.util.ArrayList;
16+
import java.util.Collection;
1617
import java.util.Collections;
1718
import java.util.HashSet;
1819
import java.util.Iterator;
1920
import java.util.LinkedList;
2021
import java.util.List;
2122
import java.util.Set;
2223
import java.util.concurrent.BlockingQueue;
24+
import java.util.concurrent.CopyOnWriteArraySet;
2325
import java.util.concurrent.LinkedBlockingQueue;
2426
import java.util.concurrent.atomic.AtomicBoolean;
2527
import java.util.concurrent.atomic.AtomicInteger;
@@ -49,12 +51,12 @@ public abstract class WebSocketServer extends WebSocketAdapter implements Runnab
4951
* Holds the list of active WebSocket connections. "Active" means WebSocket
5052
* handshake is complete and socket can be written to, or read from.
5153
*/
52-
private final Set<WebSocket> connections = new HashSet<WebSocket>();
54+
private final Collection<WebSocket> connections;
5355
/**
5456
* The port number that this WebSocket server should listen on. Default is
5557
* WebSocket.DEFAULT_PORT.
5658
*/
57-
private InetSocketAddress address;
59+
private final InetSocketAddress address;
5860
/**
5961
* The socket channel for this WebSocket server.
6062
*/
@@ -82,10 +84,11 @@ public abstract class WebSocketServer extends WebSocketAdapter implements Runnab
8284

8385
private WebSocketServerFactory wsf = new DefaultWebSocketServerFactory();
8486

85-
// CONSTRUCTORS ////////////////////////////////////////////////////////////
8687
/**
87-
* Nullary constructor. Creates a WebSocketServer that will attempt to
88+
* Creates a WebSocketServer that will attempt to
8889
* listen on port <var>WebSocket.DEFAULT_PORT</var>.
90+
*
91+
* @see #WebSocketServer(InetSocketAddress, int, List, Collection) more details here
8992
*/
9093
public WebSocketServer() throws UnknownHostException {
9194
this( new InetSocketAddress( WebSocket.DEFAULT_PORT ), DECODERS, null );
@@ -94,37 +97,64 @@ public WebSocketServer() throws UnknownHostException {
9497
/**
9598
* Creates a WebSocketServer that will attempt to bind/listen on the given <var>address</var>.
9699
*
97-
* @param address
98-
* The address (host:port) this server should listen on.
100+
* @see #WebSocketServer(InetSocketAddress, int, List, Collection) more details here
99101
*/
100102
public WebSocketServer( InetSocketAddress address ) {
101103
this( address, DECODERS, null );
102104
}
103105

106+
/**
107+
* @see #WebSocketServer(InetSocketAddress, int, List, Collection) more details here
108+
*/
104109
public WebSocketServer( InetSocketAddress address , int decoders ) {
105110
this( address, decoders, null );
106111
}
107112

108113
/**
109-
* Creates a WebSocketServer that will attempt to bind/listen on the given <var>address</var>,
110-
* and comply with <tt>Draft</tt> version <var>draft</var>.
111-
*
112-
* @param address
113-
* The address (host:port) this server should listen on.
114-
* @param draft
115-
* The version of the WebSocket protocol that this server
116-
* instance should comply to.
114+
* @see #WebSocketServer(InetSocketAddress, int, List, Collection) more details here
117115
*/
118116
public WebSocketServer( InetSocketAddress address , List<Draft> drafts ) {
119117
this( address, DECODERS, drafts );
120118
}
121119

120+
/**
121+
* @see #WebSocketServer(InetSocketAddress, int, List, Collection) more details here
122+
*/
122123
public WebSocketServer( InetSocketAddress address , int decodercount , List<Draft> drafts ) {
124+
this( address, decodercount, drafts, new HashSet<WebSocket>() );
125+
}
126+
127+
/**
128+
* Creates a WebSocketServer that will attempt to bind/listen on the given <var>address</var>,
129+
* and comply with <tt>Draft</tt> version <var>draft</var>.
130+
*
131+
* @param address
132+
* The address (host:port) this server should listen on.
133+
* @param decodercount
134+
* The number of {@link WebSocketWorker}s that will be used to process the incoming network data. By default this will be <code>Runtime.getRuntime().availableProcessors()</code>
135+
* @param drafts
136+
* The versions of the WebSocket protocol that this server
137+
* instance should comply to. Clients that use an other protocol version will be rejected.
138+
*
139+
* @param connectionscontainer
140+
* Allows to specify a collection that will be used to store the websockets in. <br>
141+
* If you plan to often iterate through the currently connected websockets you may want to use a collection that does not require synchronization like a {@link CopyOnWriteArraySet}. In that case make sure that you overload {@link #removeConnection(WebSocket)} and {@link #addConnection(WebSocket)}.<br>By default a {@link HashSet} will be used.
142+
*
143+
* @see #removeConnection(WebSocket) for more control over syncronized operation
144+
* @see <a href="https://github.com/TooTallNate/Java-WebSocket/wiki/Drafts" > more about drafts
145+
*/
146+
public WebSocketServer( InetSocketAddress address , int decodercount , List<Draft> drafts , Collection<WebSocket> connectionscontainer ) {
147+
if(address ==null || decodercount<1||connectionscontainer==null){
148+
throw new IllegalArgumentException( "address and connectionscontainer must not be null and you need at least 1 decoder" );
149+
}
150+
123151
if( drafts == null )
124152
this.drafts = Collections.emptyList();
125153
else
126154
this.drafts = drafts;
127-
setAddress( address );
155+
156+
this.address = address;
157+
this.connections = connectionscontainer;
128158

129159
oqueue = new LinkedBlockingQueue<WebSocketImpl>();
130160
iqueue = new LinkedList<WebSocketImpl>();
@@ -207,20 +237,10 @@ public void stop() throws IOException , InterruptedException {
207237
*
208238
* @return The currently connected clients.
209239
*/
210-
public Set<WebSocket> connections() {
240+
public Collection<WebSocket> connections() {
211241
return this.connections;
212242
}
213243

214-
/**
215-
* Sets the address (host:port) that this WebSocketServer should listen on.
216-
*
217-
* @param address
218-
* The address (host:port) to listen on.
219-
*/
220-
public void setAddress( InetSocketAddress address ) {
221-
this.address = address;
222-
}
223-
224244
public InetSocketAddress getAddress() {
225245
return this.address;
226246
}
@@ -352,7 +372,7 @@ public void run() {
352372
return;// FIXME controlled shutdown
353373
}
354374
}
355-
375+
356376
} catch ( RuntimeException e ) {
357377
// should hopefully never occur
358378
handleFatal( null, e );
@@ -450,10 +470,8 @@ public final void onWebsocketMessage( WebSocket conn, ByteBuffer blob ) {
450470

451471
@Override
452472
public final void onWebsocketOpen( WebSocket conn, Handshakedata handshake ) {
453-
synchronized ( connections ) {
454-
if( this.connections.add( conn ) ) {
455-
onOpen( conn, (ClientHandshake) handshake );
456-
}
473+
if( addConnection( conn ) ) {
474+
onOpen( conn, (ClientHandshake) handshake );
457475
}
458476
}
459477

@@ -462,10 +480,8 @@ public final void onWebsocketClose( WebSocket conn, int code, String reason, boo
462480
oqueue.add( (WebSocketImpl) conn );// because the ostream will close the channel
463481
selector.wakeup();
464482
try {
465-
synchronized ( connections ) {
466-
if( this.connections.remove( conn ) ) {
467-
onClose( conn, code, reason, remote );
468-
}
483+
if( removeConnection( conn ) ) {
484+
onClose( conn, code, reason, remote );
469485
}
470486
} finally {
471487
try {
@@ -477,6 +493,25 @@ public final void onWebsocketClose( WebSocket conn, int code, String reason, boo
477493

478494
}
479495

496+
/**
497+
* This method performs remove operations on the connection and therefore also gives control over whether the operation shall be synchronized
498+
* <p>
499+
* {@link #WebSocketServer(InetSocketAddress, int, List, Collection)} allows to specify a collection which will be used to store current connections in.<br>
500+
* Depending on the type on the connection, modifications of that collection may have to be synchronized.
501+
**/
502+
protected boolean removeConnection( WebSocket ws ) {
503+
synchronized ( connections ) {
504+
return this.connections.remove( ws );
505+
}
506+
}
507+
508+
/** @see #removeConnection(WebSocket) */
509+
protected boolean addConnection( WebSocket ws ) {
510+
synchronized ( connections ) {
511+
return this.connections.add( ws );
512+
}
513+
}
514+
480515
/**
481516
* @param conn
482517
* may be null if the error does not belong to a single connection

0 commit comments

Comments
 (0)