Procházet zdrojové kódy

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

PSp..om před 14 roky
rodič
revize
b46a09066d

+ 3 - 5
engine/src/networking/com/jme3/network/base/DefaultServer.java

@@ -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);
             }
         }
         

+ 10 - 1
engine/src/networking/com/jme3/network/kernel/Endpoint.java

@@ -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);
 }

+ 25 - 1
engine/src/networking/com/jme3/network/kernel/tcp/NioEndpoint.java

@@ -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 );
     }
 

+ 8 - 0
engine/src/networking/com/jme3/network/kernel/tcp/SelectorKernel.java

@@ -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

+ 9 - 0
engine/src/networking/com/jme3/network/kernel/udp/UdpEndpoint.java

@@ -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 ) {