UDP-based kernel now does its writes on a background

thread.  Most of the time UDP packets go right out
but not always... depending on the network layer it can
take a couple of milliseconds.  And that's alot when
you're blasting packets out to a dozen users 20 times
a second.


git-svn-id: https://jmonkeyengine.googlecode.com/svn/trunk@7245 75d07b2b-3a1a-0410-a2c5-0572b91ccdca
3.0
PSp..om 14 years ago
parent 1f1c2ac15b
commit 593d9bf35a
  1. 9
      engine/src/networking/com/jme3/network/kernel/udp/UdpEndpoint.java
  2. 48
      engine/src/networking/com/jme3/network/kernel/udp/UdpKernel.java

@ -114,10 +114,17 @@ public class UdpEndpoint implements Endpoint
if( !isConnected() ) {
throw new KernelException( "Endpoint is not connected:" + this );
}
try {
DatagramPacket p = new DatagramPacket( data.array(), data.position(),
data.remaining(), address );
socket.send(p);
// Just queue it up for the kernel threads to write
// out
kernel.enqueueWrite( this, p );
//socket.send(p);
} catch( IOException e ) {
throw new KernelException( "Error sending datagram to:" + address, e );
}

@ -37,6 +37,8 @@ import java.net.*;
import java.nio.ByteBuffer;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Executors;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.logging.Level;
import java.util.logging.Logger;
@ -57,6 +59,8 @@ public class UdpKernel extends AbstractKernel
private InetSocketAddress address;
private HostThread thread;
private ExecutorService writer = Executors.newFixedThreadPool(2);
// The nature of UDP means that even through a firewall,
// a user would have to have a unique address+port since UDP
// can't really be NAT'ed.
@ -104,6 +108,7 @@ public class UdpKernel extends AbstractKernel
try {
thread.close();
writer.shutdown();
thread = null;
} catch( IOException e ) {
throw new KernelException( "Error closing host connection:" + address, e );
@ -120,8 +125,13 @@ public class UdpKernel extends AbstractKernel
if( reliable )
throw new UnsupportedOperationException( "Reliable send not supported by this kernel." );
// We ignore the copy flag because we know all outbound traffic
// goes instantly.
if( copy )
{
// Copy the data just once
byte[] temp = new byte[data.remaining()];
System.arraycopy(data.array(), data.position(), temp, 0, data.remaining());
data = ByteBuffer.wrap(temp);
}
// Hand it to all of the endpoints that match our routing
for( UdpEndpoint p : socketEndpoints.values() ) {
@ -177,6 +187,40 @@ public class UdpKernel extends AbstractKernel
addEnvelope( env );
}
protected void enqueueWrite( Endpoint endpoint, DatagramPacket packet )
{
writer.execute( new MessageWriter(endpoint, packet) );
}
protected class MessageWriter implements Runnable
{
private Endpoint endpoint;
private DatagramPacket packet;
public MessageWriter( Endpoint endpoint, DatagramPacket packet )
{
this.endpoint = endpoint;
this.packet = packet;
}
public void run()
{
// Not guaranteed to always work but an extra datagram
// to a dead connection isn't so big of a deal.
if( !endpoint.isConnected() ) {
return;
}
try {
thread.getSocket().send(packet);
} catch( Exception e ) {
KernelException exc = new KernelException( "Error sending datagram to:" + address, e );
exc.fillInStackTrace();
reportError(exc);
}
}
}
protected class HostThread extends Thread
{
private DatagramSocket socket;

Loading…
Cancel
Save