Home | History | Annotate | Download | only in udp
      1 /*
      2  * Copyright (c) 2011 jMonkeyEngine
      3  * All rights reserved.
      4  *
      5  * Redistribution and use in source and binary forms, with or without
      6  * modification, are permitted provided that the following conditions are
      7  * met:
      8  *
      9  * * Redistributions of source code must retain the above copyright
     10  *   notice, this list of conditions and the following disclaimer.
     11  *
     12  * * Redistributions in binary form must reproduce the above copyright
     13  *   notice, this list of conditions and the following disclaimer in the
     14  *   documentation and/or other materials provided with the distribution.
     15  *
     16  * * Neither the name of 'jMonkeyEngine' nor the names of its contributors
     17  *   may be used to endorse or promote products derived from this software
     18  *   without specific prior written permission.
     19  *
     20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     21  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     22  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     23  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
     24  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
     25  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     26  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
     27  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
     28  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
     29  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
     30  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     31  */
     32 
     33 package com.jme3.network.kernel.udp;
     34 
     35 import com.jme3.network.kernel.Connector;
     36 import com.jme3.network.kernel.ConnectorException;
     37 import java.io.IOException;
     38 import java.net.*;
     39 import java.nio.ByteBuffer;
     40 import java.util.concurrent.atomic.AtomicBoolean;
     41 
     42 
     43 /**
     44  *  A straight forward datagram socket-based UDP connector
     45  *  implementation.
     46  *
     47  *  @version   $Revision: 8843 $
     48  *  @author    Paul Speed
     49  */
     50 public class UdpConnector implements Connector
     51 {
     52     private DatagramSocket sock = new DatagramSocket();
     53     private SocketAddress remoteAddress;
     54     private byte[] buffer = new byte[65535];
     55     private AtomicBoolean connected = new AtomicBoolean(false);
     56 
     57     /**
     58      *  In order to provide proper available() checking, we
     59      *  potentially queue one datagram.
     60      */
     61     private DatagramPacket pending;
     62 
     63     /**
     64      *  Creates a new UDP connection that send datagrams to the
     65      *  specified address and port.
     66      */
     67     public UdpConnector( InetAddress remote, int remotePort ) throws IOException
     68     {
     69         InetSocketAddress localSocketAddress = new InetSocketAddress(0);
     70         this.sock = new DatagramSocket( localSocketAddress );
     71         remoteAddress = new InetSocketAddress( remote, remotePort );
     72 
     73         // Setup to receive only from the remote address
     74         sock.connect( remoteAddress );
     75 
     76         connected.set(true);
     77     }
     78 
     79     protected void checkClosed()
     80     {
     81         if( sock == null )
     82             throw new ConnectorException( "Connection is closed:" + remoteAddress );
     83     }
     84 
     85     public boolean isConnected()
     86     {
     87         if( sock == null )
     88             return false;
     89         return sock.isConnected();
     90     }
     91 
     92     public void close()
     93     {
     94         checkClosed();
     95         DatagramSocket temp = sock;
     96         sock = null;
     97         connected.set(false);
     98         temp.close();
     99     }
    100 
    101     /**
    102      *  This always returns false since the simple DatagramSocket usage
    103      *  cannot be run in a non-blocking way.
    104      */
    105     public boolean available()
    106     {
    107         // It would take a separate thread or an NIO Selector based implementation to get this
    108         // to work.  If a polling strategy is never employed by callers then it doesn't
    109         // seem worth it to implement all of that just for this method.
    110         checkClosed();
    111         return false;
    112     }
    113 
    114     public ByteBuffer read()
    115     {
    116         checkClosed();
    117 
    118         try {
    119             DatagramPacket packet = new DatagramPacket( buffer, buffer.length );
    120             sock.receive(packet);
    121 
    122             // Wrap it in a ByteBuffer for the caller
    123             return ByteBuffer.wrap( buffer, 0, packet.getLength() );
    124         } catch( IOException e ) {
    125             if( !connected.get() ) {
    126                 // Nothing to see here... just move along
    127                 return null;
    128             }
    129             throw new ConnectorException( "Error reading from connection to:" + remoteAddress, e );
    130         }
    131     }
    132 
    133     public void write( ByteBuffer data )
    134     {
    135         checkClosed();
    136 
    137         try {
    138             DatagramPacket p = new DatagramPacket( data.array(), data.position(), data.remaining(),
    139                                                    remoteAddress );
    140             sock.send(p);
    141         } catch( IOException e ) {
    142             throw new ConnectorException( "Error writing to connection:" + remoteAddress, e );
    143         }
    144     }
    145 }
    146 
    147