jcifs.util
Class MultiDatagramSocket

java.lang.Object
  |
  +--jcifs.util.MultiDatagramSocket

public class MultiDatagramSocket
extends Object
implements Runnable

MultiDatagramSocket employs a simple linked list queuing mechanism and an internal thread dedicated to reading from the socket to allow multiple threads to concurrently send and receive datagram packets on the same port at rates independent from one another. There are three classes that encapsulate this functionality: MultiDatagramSocket, PacketEventQueue, and PacketEvent.

MultiDatagramSocket is, at first glance, almost identical to DatagramSocket but instead of calling receive you obtain a PacketEventQueue by calling createPacketEventQueue() and read in PacketEvents at liesure by calling PacketEventQueue.getNextPacketEvent() on the PacketEventQueue. PacketEvent encapsulates the DatagramPacket, the reception time, and is Cloneable. The PacketEventQueue.getNextPacketEvent() method will block until a packet is received if there are no PacketEvents in the queue.

This is useful when different tasks are servicing request on the same port. You don't have to worry about tasks stealing each other's packets. The netbios name service of jcifs uses it to send and receive requests synchronously. Without this, a failing request(which can take up to 15 seconds) would prevent another request from being serviced until it finished. This may all seem overkill but it is surprisingly easy to implement. All three classes total a meager 250 lines of code. See MultiDatagramSocket.txt for more information.

Important Note: When the internal thread enqueues an incoming packet it clones it only once so that when another packet comes in the data is not overwritten in the queues. But the data(DatagramPacket, it's buffer, and so on) are not cloned for entry into each queue. In other words, with each incoming packet, the same PacketEvent object is queued to all PacketEventQueues. So you CANNOT MODIFY the data of a PacketEvent without cloning it first or other PacketEventQueues will observe the changes. This is one reason why PacketEvent is Cloneable. This was done for purposes of efficiency. I have found that in practice packets are simply examined and not modified. So if you want to recycle a packet for it's data just PacketEvent.clone() it first.

Since:
jcifs-0.1
Author:
Michael B. Allen
See Also:
PacketEventQueue, PacketEvent, DatagramSocket, DatagramPacket, Cloneable

Constructor Summary
MultiDatagramSocket()
          Construct a new MultiDatagramSocket.
MultiDatagramSocket(int port)
          Construct a new MultiDatagramSocket on the specified port.
MultiDatagramSocket(int port, InetAddress addr)
          Construct a new MultiDatagramSocket on the specified port that binds to the specified interface.
 
Method Summary
 PacketEventQueue createPacketEventQueue()
          Create a new PacketEventQueue.
 InetAddress getLocalAddress()
          Retrieves the local hosts interface this socket is running bound to.
 int getLocalPort()
          Returns the local port this socket is set to run on.
 int getSize()
          The number of open PacketEventQueues.
 void interruptPacketEventQueues()
          Interrupt any threads waiting for PacketEvents on their PacketEventQueues.
 boolean isEmpty()
          Checks if there are any open PacketEventQueues.
 void removePacketEventQueue(PacketEventQueue peq)
          Discard the PacketEventQueue(ie stop listening).
 void run()
           
 void send(DatagramPacket p)
          Send a datagram.
 void start()
          Start this MultiDatagramSocket.
 void stop()
          Stop the MultiDatagramSocket.
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
 

Constructor Detail

MultiDatagramSocket

public MultiDatagramSocket()
Construct a new MultiDatagramSocket.

MultiDatagramSocket

public MultiDatagramSocket(int port)
Construct a new MultiDatagramSocket on the specified port.

MultiDatagramSocket

public MultiDatagramSocket(int port,
                           InetAddress addr)
Construct a new MultiDatagramSocket on the specified port that binds to the specified interface.
Method Detail

run

public void run()
Specified by:
run in interface Runnable

start

public void start()
           throws SocketException
Start this MultiDatagramSocket. After 30 seconds of no activity the socket will timeout and close. Should another packet arrive the socket will restart and service the request as normal.

stop

public void stop()
Stop the MultiDatagramSocket. You can start and stop MultiDatagramSocket any number of times without worrying about reinstantiating.

send

public void send(DatagramPacket p)
          throws IOException
Send a datagram.
Parameters:
p - the DatagramPacket to send
Throws:
IOException - if the send operation fails

getLocalAddress

public InetAddress getLocalAddress()
Retrieves the local hosts interface this socket is running bound to.

getLocalPort

public int getLocalPort()
Returns the local port this socket is set to run on.

createPacketEventQueue

public PacketEventQueue createPacketEventQueue()
Create a new PacketEventQueue. As soon as a thread creates a new PacketEventQueue it is currently queueing packets. So if the thread chooses not to call PacketEventQueue.getNextPacketEvent() for a while it may get a back log of packets. This is probably not what you want. Obtain the PacketEventQueue just before the calling thread is going to try to retrive a packet.

removePacketEventQueue

public void removePacketEventQueue(PacketEventQueue peq)
Discard the PacketEventQueue(ie stop listening). It is always very importantant to release a PacketEventQueue or the socket will maintain it's reference and queue packet events to it. Probably get a VM memory error eventually.

interruptPacketEventQueues

public void interruptPacketEventQueues()
Interrupt any threads waiting for PacketEvents on their PacketEventQueues.

isEmpty

public boolean isEmpty()
Checks if there are any open PacketEventQueues.

getSize

public int getSize()
The number of open PacketEventQueues.