Modified Client/Server to support alternate channels. The

server can configure additional ports that will be sent to
the client upon connection.  These channels can be used to
send messages in parallel to the normal messages.  This is
useful to keeping several separate command pathways flowing
smoothly despite potentially large messages on one channel.


git-svn-id: https://jmonkeyengine.googlecode.com/svn/trunk@8938 75d07b2b-3a1a-0410-a2c5-0572b91ccdca
3.0
PSp..om 13 years ago
parent 665a7c8851
commit e84d8300dd
  1. 6
      engine/src/networking/com/jme3/network/Client.java
  2. 6
      engine/src/networking/com/jme3/network/MessageConnection.java
  3. 7
      engine/src/networking/com/jme3/network/Network.java
  4. 27
      engine/src/networking/com/jme3/network/Server.java
  5. 48
      engine/src/networking/com/jme3/network/base/ConnectorFactory.java
  6. 50
      engine/src/networking/com/jme3/network/base/DefaultClient.java
  7. 71
      engine/src/networking/com/jme3/network/base/DefaultServer.java
  8. 51
      engine/src/networking/com/jme3/network/base/KernelFactory.java
  9. 53
      engine/src/networking/com/jme3/network/base/NioKernelFactory.java
  10. 60
      engine/src/networking/com/jme3/network/base/TcpConnectorFactory.java
  11. 74
      engine/src/networking/com/jme3/network/message/ChannelInfoMessage.java
  12. 2
      engine/src/networking/com/jme3/network/serializing/Serializer.java

@ -79,6 +79,12 @@ public interface Client extends MessageConnection
*/ */
public void send( Message message ); public void send( Message message );
/**
* Sends a message to the other end of the connection using
* the specified alternate channel.
*/
public void send( int channel, Message message );
/** /**
* Closes this connection to the server. * Closes this connection to the server.
*/ */

@ -46,5 +46,11 @@ public interface MessageConnection
* Sends a message to the other end of the connection. * Sends a message to the other end of the connection.
*/ */
public void send( Message message ); public void send( Message message );
/**
* Sends a message to the other end of the connection using
* the specified alternate channel.
*/
public void send( int channel, Message message );
} }

@ -34,6 +34,7 @@ package com.jme3.network;
import com.jme3.network.base.DefaultClient; import com.jme3.network.base.DefaultClient;
import com.jme3.network.base.DefaultServer; import com.jme3.network.base.DefaultServer;
import com.jme3.network.base.TcpConnectorFactory;
import com.jme3.network.kernel.tcp.SelectorKernel; import com.jme3.network.kernel.tcp.SelectorKernel;
import com.jme3.network.kernel.tcp.SocketConnector; import com.jme3.network.kernel.tcp.SocketConnector;
import com.jme3.network.kernel.udp.UdpConnector; import com.jme3.network.kernel.udp.UdpConnector;
@ -85,7 +86,7 @@ public class Network
* @param tcpPort The port upon which the TCP hosting will listen for new connections. * @param tcpPort The port upon which the TCP hosting will listen for new connections.
* @param udpPort The port upon which the UDP hosting will listen for new 'fast' UDP * @param udpPort The port upon which the UDP hosting will listen for new 'fast' UDP
* messages. Set to -1 if 'fast' traffic should go over TCP. This will * messages. Set to -1 if 'fast' traffic should go over TCP. This will
* comletely disable UDP traffic for this server. * completely disable UDP traffic for this server.
*/ */
public static Server createServer( String gameName, int version, int tcpPort, int udpPort ) throws IOException public static Server createServer( String gameName, int version, int tcpPort, int udpPort ) throws IOException
{ {
@ -164,7 +165,7 @@ public class Network
UdpConnector fast = remoteUdpPort == -1 ? null : new UdpConnector( remoteAddress, remoteUdpPort ); UdpConnector fast = remoteUdpPort == -1 ? null : new UdpConnector( remoteAddress, remoteUdpPort );
SocketConnector reliable = new SocketConnector( remoteAddress, hostPort ); SocketConnector reliable = new SocketConnector( remoteAddress, hostPort );
return new DefaultClient( gameName, version, reliable, fast ); return new DefaultClient( gameName, version, reliable, fast, new TcpConnectorFactory(remoteAddress) );
} }
@ -185,7 +186,7 @@ public class Network
UdpConnector fast = new UdpConnector( address, remoteUdpPort ); UdpConnector fast = new UdpConnector( address, remoteUdpPort );
SocketConnector reliable = new SocketConnector( address, port ); SocketConnector reliable = new SocketConnector( address, port );
setConnectors( reliable, fast ); setPrimaryConnectors( reliable, fast, new TcpConnectorFactory(address) );
} }
} }
} }

@ -76,12 +76,39 @@ public interface Server
*/ */
public void broadcast( Filter<? super HostedConnection> filter, Message message ); public void broadcast( Filter<? super HostedConnection> filter, Message message );
/**
* Sends the specified message over the specified alternate channel to all connected
* clients that match the filter. If no filter is specified then this is the same as
* calling broadcast(message) and the message will be delivered to
* all connections.
* <p>Examples:</p>
* <pre>
* // Broadcast to connections: conn1, conn2, and conn3
* server.broadcast( Filters.in( conn1, conn2, conn3 ), message );
*
* // Broadcast to all connections exception source
* server.broadcast( Filters.notEqualTo( source ), message );
* </pre>
*/
public void broadcast( int channel, Filter<? super HostedConnection> filter, Message message );
/** /**
* Start the server so that it will began accepting new connections * Start the server so that it will began accepting new connections
* and processing messages. * and processing messages.
*/ */
public void start(); public void start();
/**
* Adds an alternate channel to the server, using the specified port. This is an
* entirely separate connection where messages are sent and received in parallel
* to the two primary default channels. All channels must be added before the connection
* is started.
* Returns the ID of the created channel for use when specifying the channel in send or
* broadcast calls. The ID is returned entirely out of convenience since the IDs
* are predictably incremented. The first channel is 0, second is 1, and so on.
*/
public int addChannel( int port );
/** /**
* Returns true if the server has been started. * Returns true if the server has been started.
*/ */

@ -0,0 +1,48 @@
/*
* Copyright (c) 2011 jMonkeyEngine
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* * Neither the name of 'jMonkeyEngine' nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.jme3.network.base;
import com.jme3.network.kernel.Connector;
import java.io.IOException;
/**
* Creates Connectors for a specific host.
*
* @version $Revision$
* @author Paul Speed
*/
public interface ConnectorFactory
{
public Connector createConnector( int channel, int port ) throws IOException;
}

@ -35,8 +35,10 @@ package com.jme3.network.base;
import com.jme3.network.ClientStateListener.DisconnectInfo; import com.jme3.network.ClientStateListener.DisconnectInfo;
import com.jme3.network.*; import com.jme3.network.*;
import com.jme3.network.kernel.Connector; import com.jme3.network.kernel.Connector;
import com.jme3.network.message.ChannelInfoMessage;
import com.jme3.network.message.ClientRegistrationMessage; import com.jme3.network.message.ClientRegistrationMessage;
import com.jme3.network.message.DisconnectMessage; import com.jme3.network.message.DisconnectMessage;
import java.io.IOException;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.util.*; import java.util.*;
import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.CopyOnWriteArrayList;
@ -62,6 +64,7 @@ public class DefaultClient implements Client
// separate. // separate.
private static final int CH_RELIABLE = 0; private static final int CH_RELIABLE = 0;
private static final int CH_UNRELIABLE = 1; private static final int CH_UNRELIABLE = 1;
private static final int CH_FIRST = 2;
private ThreadLocal<ByteBuffer> dataBuffer = new ThreadLocal<ByteBuffer>(); private ThreadLocal<ByteBuffer> dataBuffer = new ThreadLocal<ByteBuffer>();
@ -75,6 +78,8 @@ public class DefaultClient implements Client
private List<ErrorListener<? super Client>> errorListeners = new CopyOnWriteArrayList<ErrorListener<? super Client>>(); private List<ErrorListener<? super Client>> errorListeners = new CopyOnWriteArrayList<ErrorListener<? super Client>>();
private Redispatch dispatcher = new Redispatch(); private Redispatch dispatcher = new Redispatch();
private List<ConnectorAdapter> channels = new ArrayList<ConnectorAdapter>(); private List<ConnectorAdapter> channels = new ArrayList<ConnectorAdapter>();
private ConnectorFactory connectorFactory;
public DefaultClient( String gameName, int version ) public DefaultClient( String gameName, int version )
{ {
@ -82,13 +87,14 @@ public class DefaultClient implements Client
this.version = version; this.version = version;
} }
public DefaultClient( String gameName, int version, Connector reliable, Connector fast ) public DefaultClient( String gameName, int version, Connector reliable, Connector fast,
ConnectorFactory connectorFactory )
{ {
this( gameName, version ); this( gameName, version );
setPrimaryConnectors( reliable, fast ); setPrimaryConnectors( reliable, fast, connectorFactory );
} }
protected void setPrimaryConnectors( Connector reliable, Connector fast ) protected void setPrimaryConnectors( Connector reliable, Connector fast, ConnectorFactory connectorFactory )
{ {
if( reliable == null ) if( reliable == null )
throw new IllegalArgumentException( "The reliable connector cannot be null." ); throw new IllegalArgumentException( "The reliable connector cannot be null." );
@ -97,6 +103,7 @@ public class DefaultClient implements Client
if( !channels.isEmpty() ) if( !channels.isEmpty() )
throw new IllegalStateException( "Channels already exist." ); throw new IllegalStateException( "Channels already exist." );
this.connectorFactory = connectorFactory;
channels.add(new ConnectorAdapter(reliable, dispatcher, dispatcher, true)); channels.add(new ConnectorAdapter(reliable, dispatcher, dispatcher, true));
if( fast != null ) { if( fast != null ) {
channels.add(new ConnectorAdapter(fast, dispatcher, dispatcher, false)); channels.add(new ConnectorAdapter(fast, dispatcher, dispatcher, false));
@ -203,6 +210,13 @@ public class DefaultClient implements Client
send(CH_UNRELIABLE, message, true); send(CH_UNRELIABLE, message, true);
} }
} }
public void send( int channel, Message message )
{
if( channel < 0 || channel + CH_FIRST >= channels.size() )
throw new IllegalArgumentException( "Channel is undefined:" + channel );
send( channel + CH_FIRST, message, true );
}
protected void send( int channel, Message message, boolean waitForConnected ) protected void send( int channel, Message message, boolean waitForConnected )
{ {
@ -340,6 +354,29 @@ public class DefaultClient implements Client
} }
} }
protected void configureChannels( long tempId, int[] ports ) {
try {
for( int i = 0; i < ports.length; i++ ) {
Connector c = connectorFactory.createConnector( i, ports[i] );
ConnectorAdapter ca = new ConnectorAdapter(c, dispatcher, dispatcher, true);
int ch = channels.size();
channels.add( ca );
// Need to send the connection its hook-up registration
// and start it.
ca.start();
ClientRegistrationMessage reg;
reg = new ClientRegistrationMessage();
reg.setId(tempId);
reg.setReliable(true);
send( ch, reg, false );
}
} catch( IOException e ) {
throw new RuntimeException( "Error configuring channels", e );
}
}
protected void dispatch( Message m ) protected void dispatch( Message m )
{ {
// Pull off the connection management messages we're // Pull off the connection management messages we're
@ -351,7 +388,12 @@ public class DefaultClient implements Client
connecting.countDown(); connecting.countDown();
fireConnected(); fireConnected();
return; return;
} if( m instanceof DisconnectMessage ) { } else if( m instanceof ChannelInfoMessage ) {
// This is an interum step in the connection process and
// now we need to add a bunch of connections
configureChannels( ((ChannelInfoMessage)m).getId(), ((ChannelInfoMessage)m).getPorts() );
return;
} else if( m instanceof DisconnectMessage ) {
// Can't do too much else yet // Can't do too much else yet
String reason = ((DisconnectMessage)m).getReason(); String reason = ((DisconnectMessage)m).getReason();
log.log( Level.SEVERE, "Connection terminated, reason:{0}.", reason ); log.log( Level.SEVERE, "Connection terminated, reason:{0}.", reason );

@ -35,8 +35,10 @@ package com.jme3.network.base;
import com.jme3.network.*; import com.jme3.network.*;
import com.jme3.network.kernel.Endpoint; import com.jme3.network.kernel.Endpoint;
import com.jme3.network.kernel.Kernel; import com.jme3.network.kernel.Kernel;
import com.jme3.network.message.ChannelInfoMessage;
import com.jme3.network.message.ClientRegistrationMessage; import com.jme3.network.message.ClientRegistrationMessage;
import com.jme3.network.message.DisconnectMessage; import com.jme3.network.message.DisconnectMessage;
import java.io.IOException;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.util.*; import java.util.*;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
@ -60,15 +62,17 @@ public class DefaultServer implements Server
// unreliable // unreliable
private static final int CH_RELIABLE = 0; private static final int CH_RELIABLE = 0;
private static final int CH_UNRELIABLE = 1; private static final int CH_UNRELIABLE = 1;
private static final int CH_FIRST = 2;
private boolean isRunning = false; private boolean isRunning = false;
private AtomicInteger nextId = new AtomicInteger(0); private AtomicInteger nextId = new AtomicInteger(0);
private String gameName; private String gameName;
private int version; private int version;
//private KernelFactory kernelFactory = KernelFactory.DEFAULT; private KernelFactory kernelFactory = KernelFactory.DEFAULT;
private KernelAdapter reliableAdapter; private KernelAdapter reliableAdapter;
private KernelAdapter fastAdapter; private KernelAdapter fastAdapter;
private List<KernelAdapter> channels = new ArrayList<KernelAdapter>(); private List<KernelAdapter> channels = new ArrayList<KernelAdapter>();
private List<Integer> alternatePorts = new ArrayList<Integer>();
private Redispatch dispatcher = new Redispatch(); private Redispatch dispatcher = new Redispatch();
private Map<Integer,HostedConnection> connections = new ConcurrentHashMap<Integer,HostedConnection>(); private Map<Integer,HostedConnection> connections = new ConcurrentHashMap<Integer,HostedConnection>();
private Map<Endpoint,HostedConnection> endpointConnections private Map<Endpoint,HostedConnection> endpointConnections
@ -109,6 +113,42 @@ public class DefaultServer implements Server
return version; return version;
} }
public int addChannel( int port )
{
if( isRunning )
throw new IllegalStateException( "Channels cannot be added once server is started." );
// Note: it does bug me that channels aren't 100% universal and
// setup externally but it requires a more invasive set of changes
// for "connection types" and some kind of registry of kernel and
// connector factories. This really would be the best approach and
// would allow all kinds of channel customization maybe... but for
// now, we hard-code the standard connections and treat the +2 extras
// differently.
// Check for consistency with the channels list
if( channels.size() - CH_FIRST != alternatePorts.size() )
throw new IllegalStateException( "Channel and port lists do not match." );
try {
int result = alternatePorts.size();
alternatePorts.add(port);
Kernel kernel = kernelFactory.createKernel(result, port);
channels.add( new KernelAdapter(this, kernel, dispatcher, true) );
return result;
} catch( IOException e ) {
throw new RuntimeException( "Error adding channel for port:" + port, e );
}
}
protected void checkChannel( int channel )
{
if( channel < 0 || channel >= alternatePorts.size() )
throw new IllegalArgumentException( "Channel is undefined:" + channel );
}
public void start() public void start()
{ {
if( isRunning ) if( isRunning )
@ -163,7 +203,6 @@ public class DefaultServer implements Server
FilterAdapter adapter = filter == null ? null : new FilterAdapter(filter); FilterAdapter adapter = filter == null ? null : new FilterAdapter(filter);
// Ignore the filter for the moment
if( message.isReliable() || fastAdapter == null ) { if( message.isReliable() || fastAdapter == null ) {
// Don't need to copy the data because message protocol is already // Don't need to copy the data because message protocol is already
// giving us a fresh buffer // giving us a fresh buffer
@ -173,6 +212,20 @@ public class DefaultServer implements Server
} }
} }
public void broadcast( int channel, Filter<? super HostedConnection> filter, Message message )
{
if( connections.isEmpty() )
return;
checkChannel(channel);
ByteBuffer buffer = MessageProtocol.messageToBuffer(message, null);
FilterAdapter adapter = filter == null ? null : new FilterAdapter(filter);
channels.get(channel+CH_FIRST).broadcast( adapter, buffer, true, false );
}
public HostedConnection getConnection( int id ) public HostedConnection getConnection( int id )
{ {
return connections.get(id); return connections.get(id);
@ -295,7 +348,10 @@ public class DefaultServer implements Server
} }
// Else send the extra channel information to the client // Else send the extra channel information to the client
// TBD if( !alternatePorts.isEmpty() ) {
ChannelInfoMessage cim = new ChannelInfoMessage( m.getId(), alternatePorts );
c.send(cim);
}
} }
if( c.isComplete() ) { if( c.isComplete() ) {
@ -349,7 +405,7 @@ public class DefaultServer implements Server
// closed already. // closed already.
// Also note: this method will be called multiple times per // Also note: this method will be called multiple times per
// HostedConnection if it has two endpoints. // HostedConnection if it has multiple endpoints.
Connection removed = null; Connection removed = null;
synchronized( this ) { synchronized( this ) {
@ -431,6 +487,13 @@ public class DefaultServer implements Server
channels[CH_UNRELIABLE].send( buffer ); channels[CH_UNRELIABLE].send( buffer );
} }
} }
public void send( int channel, Message message )
{
checkChannel(channel);
ByteBuffer buffer = MessageProtocol.messageToBuffer(message, null);
channels[channel+CH_FIRST].send(buffer);
}
protected void closeConnection() protected void closeConnection()
{ {

@ -0,0 +1,51 @@
/*
* Copyright (c) 2011 jMonkeyEngine
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* * Neither the name of 'jMonkeyEngine' nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.jme3.network.base;
import com.jme3.network.kernel.Kernel;
import java.io.IOException;
/**
* Supplied to the DefaultServer to create any additional
* channel kernels that might be required.
*
* @version $Revision$
* @author Paul Speed
*/
public interface KernelFactory
{
public static final KernelFactory DEFAULT = new NioKernelFactory();
public Kernel createKernel( int channel, int port ) throws IOException;
}

@ -0,0 +1,53 @@
/*
* Copyright (c) 2011 jMonkeyEngine
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* * Neither the name of 'jMonkeyEngine' nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.jme3.network.base;
import com.jme3.network.kernel.Kernel;
import com.jme3.network.kernel.tcp.SelectorKernel;
import java.io.IOException;
/**
* KernelFactory implemention for creating TCP kernels
* using the NIO selector model.
*
* @version $Revision$
* @author Paul Speed
*/
public class NioKernelFactory implements KernelFactory
{
public Kernel createKernel( int channel, int port ) throws IOException
{
return new SelectorKernel(port);
}
}

@ -0,0 +1,60 @@
/*
* Copyright (c) 2011 jMonkeyEngine
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* * Neither the name of 'jMonkeyEngine' nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.jme3.network.base;
import com.jme3.network.kernel.Connector;
import com.jme3.network.kernel.tcp.SocketConnector;
import java.io.IOException;
import java.net.InetAddress;
/**
* Creates TCP connectors to a specific remote address.
*
* @version $Revision$
* @author Paul Speed
*/
public class TcpConnectorFactory implements ConnectorFactory
{
private InetAddress remoteAddress;
public TcpConnectorFactory( InetAddress remoteAddress )
{
this.remoteAddress = remoteAddress;
}
public Connector createConnector( int channel, int port ) throws IOException
{
return new SocketConnector( remoteAddress, port );
}
}

@ -0,0 +1,74 @@
/*
* Copyright (c) 2011 jMonkeyEngine
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* * Neither the name of 'jMonkeyEngine' nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.jme3.network.message;
import com.jme3.network.AbstractMessage;
import com.jme3.network.serializing.Serializable;
import java.util.Arrays;
import java.util.List;
/**
* Contains information about any extra server channels (if they exist).
*
* @author Paul Speed
*/
@Serializable()
public class ChannelInfoMessage extends AbstractMessage {
private long id;
private int[] ports;
public ChannelInfoMessage() {
super( true );
}
public ChannelInfoMessage( long id, List<Integer> ports ) {
super( true );
this.id = id;
this.ports = new int[ports.size()];
for( int i = 0; i < ports.size(); i++ ) {
this.ports[i] = ports.get(i);
}
}
public long getId() {
return id;
}
public int[] getPorts() {
return ports;
}
public String toString() {
return "ChannelInfoMessage[" + id + ", " + Arrays.asList(ports) + "]";
}
}

@ -33,6 +33,7 @@
package com.jme3.network.serializing; package com.jme3.network.serializing;
import com.jme3.math.Vector3f; import com.jme3.math.Vector3f;
import com.jme3.network.message.ChannelInfoMessage;
import com.jme3.network.message.ClientRegistrationMessage; import com.jme3.network.message.ClientRegistrationMessage;
import com.jme3.network.message.DisconnectMessage; import com.jme3.network.message.DisconnectMessage;
import com.jme3.network.message.GZIPCompressedMessage; import com.jme3.network.message.GZIPCompressedMessage;
@ -126,6 +127,7 @@ public abstract class Serializer {
registerClass(DisconnectMessage.class); registerClass(DisconnectMessage.class);
registerClass(ClientRegistrationMessage.class); registerClass(ClientRegistrationMessage.class);
registerClass(ChannelInfoMessage.class);
} }
/** /**

Loading…
Cancel
Save