Updated the Endpoint interface to define a close() method

that can optionally flush the queued messages.  Modified
DefaultServer to close-with-flush when kicking a client
so that the disconnect message actually gets to them.


git-svn-id: https://jmonkeyengine.googlecode.com/svn/trunk@7049 75d07b2b-3a1a-0410-a2c5-0572b91ccdca
This commit is contained in:
PSp..om 2011-03-19 22:07:19 +00:00
parent 0d23903830
commit b46a09066d
5 changed files with 55 additions and 7 deletions

View File

@ -409,14 +409,12 @@ public class DefaultServer implements Server
m.setReliable( true );
send( m );
// Note: without a way to flush the pending messages
// during close, the above message may never
// go out.
// Just close the reliable endpoint
// fast will be cleaned up as a side-effect
if( reliable != null ) {
reliable.close();
// Close with flush so we make sure our
// message gets out
reliable.close(true);
}
}

View File

@ -73,7 +73,16 @@ public interface Endpoint
public void send( ByteBuffer data );
/**
* Closes this endpoint.
* Closes this endpoint without flushing any of its
* currently enqueued outbound data.
*/
public void close();
/**
* Closes this endpoint, optionally flushing any queued
* data before closing. As soon as this method is called,
* ne send() calls will fail with an exception... even while
* close() is still flushing the earlier queued messages.
*/
public void close(boolean flushData);
}

View File

@ -50,10 +50,13 @@ import com.jme3.network.kernel.*;
*/
public class NioEndpoint implements Endpoint
{
protected static final ByteBuffer CLOSE_MARKER = ByteBuffer.allocate(0);
private long id;
private SocketChannel socket;
private SelectorKernel kernel;
private ConcurrentLinkedQueue<ByteBuffer> outbound = new ConcurrentLinkedQueue<ByteBuffer>();
private boolean closing = false;
public NioEndpoint( SelectorKernel kernel, long id, SocketChannel socket )
{
@ -69,6 +72,21 @@ public class NioEndpoint implements Endpoint
public void close()
{
close(false);
}
public void close( boolean flushData )
{
if( flushData ) {
closing = true;
// Enqueue a close marker message to let the server
// know we should close
send( CLOSE_MARKER, false, true );
return;
}
try {
kernel.closeEndpoint(this);
} catch( IOException e ) {
@ -142,7 +160,13 @@ public class NioEndpoint implements Endpoint
}
public void send( ByteBuffer data )
{
{
if( data == null ) {
throw new IllegalArgumentException( "Data cannot be null." );
}
if( closing ) {
throw new KernelException( "Endpoint has been closed:" + socket );
}
send( data, true, true );
}

View File

@ -354,6 +354,14 @@ public class SelectorKernel extends AbstractKernel
// We will send what we can and move on.
ByteBuffer current = p.peekPending();
if( current == NioEndpoint.CLOSE_MARKER ) {
// This connection wants to be closed now
closeEndpoint(p);
// Nothing more to do
return;
}
c.write( current );
// If we wrote all of that packet then we need to remove it

View File

@ -74,6 +74,15 @@ public class UdpEndpoint implements Endpoint
public void close()
{
close( false );
}
public void close( boolean flush )
{
// No real reason to flush UDP traffic yet... especially
// when considering that the outbound UDP isn't even
// queued.
try {
kernel.closeEndpoint(this);
} catch( IOException e ) {