Skip to Main Content

Java APIs

Announcement

For appeals, questions and feedback about Oracle Forums, please email oracle-forums-moderators_us@oracle.com. Technical questions should be asked in the appropriate category. Thank you!

Having troubles with Selector and lost UDP messages.

843790Jan 4 2010 — edited Jan 5 2010
First disclaimer, I am not a seasoned JAVA developer. Just working on my pet project and having some problems with NIO, selector and DatagramChannel. The end result seem to imply some UDP messages are lost!? My code can work as a client and a server. When I start both (server and client), client says 1000 messages sent, and the server acknowledges number much less than that (could be around 600, could be more, could be less).

Design-wise, I have have the following concept:
1) There are 2 threads, one in charge of sending messages and one responsible for accepting incoming messages.
2) A selector is opened and a channel is registered with it. Receive buffer is attached to the key. Here is the code:
   initialChannel = DatagramChannel.open();
            initialChannel.configureBlocking(false);
            initialChannel.socket().setReuseAddress(true);
            initialChannel.socket().bind(new InetSocketAddress(localAddress, localPort));
            if (selector != null)
            {
                initialKey = initialChannel.register(selector,
                    SelectionKey.OP_READ);
                ByteBuffer rcvdBytes = ByteBuffer.allocateDirect(4096);
                rcvdBytes.clear();
                initialKey.attach(rcvdBytes);
            }
3) A registered channel receives the packets in following fashion:
   public MyPacket receive(SelectionKey key) throws IOException
    {
        DatagramChannel sc = (DatagramChannel)key.channel();
        ByteBuffer rcvdBytes;

        // Check if the socket channel is open and connected
        if (sc == null || sc.isOpen() == false)
        {
            throw new IOException();
        }

        rcvdBytes = (ByteBuffer)key.attachment();
        rcvdBytes.clear();
        InetSocketAddress addr = (InetSocketAddress)sc.receive(rcvdBytes);
        if (addr == null)
        {
            // Failure to receive a packet
            return null;
        }
        MyPacket myPacket = new MyPacket(rcvdBytes);
        myPacket.setAddress(addr.getAddress());
        myPacket.setPort(addr.getPort());
        logIncomingMsg(key, myPacket);
        return myPacket;
    }
4. The receiver thread looks pretty much like following:
 public void run()
    {
        try
        {
            while (true)
            {
                /* Make sure the maximum number of allowed concurrent calls never
                 * goes beyond an allowed limit
                 */
                // Time to accept incoming messages
                socket.getSelector().select();
                Set keys = socket.getSelector().selectedKeys();
                if (keys.size() <= 0)
                {
                    break;
                }
                handleIncomingMsgs(keys);
            }
        }
        catch (IOException exc)
        {
        }
    }

    private void handleIncomingMsgs(Set keys)
    {
        boolean newCallFlag;

        Iterator iterator = keys.iterator();
        while (iterator.hasNext())
        {
            SelectionKey key = (SelectionKey) iterator.next();
            iterator.remove();
            try
            {
                if (key.isAcceptable() == true)
                {
                    SocketChannel client = (SocketChannel) socket.getSocket();
                    client.configureBlocking(false);
                    client.register(socket.getSelector(), client.validOps());
                }
                else if (key.isReadable() == true)
                {
                    MyPacket packet;
                    while ((packet = socket.receive(key)) != null) // receive function is defined under 3)
                    {
                        SIPCall currCall =
                                callDB.findCallForMsg(packet.getMessageTxt());
                        newCallFlag = false;
                        if (currCall == null)
                        {
                            if (socket.isDaemon() == true)
                            {
                                // Check if received message is equal to the first
                                // expected incoming message. If so, then, everything is
                                // legit and create a new call. Otherwise, drop the
                                // message
                                currCall = new SIPCall(progressDialog, key, packet);
                                newCallFlag = true;
                            }
                            else
                            {
                                // when client receives message for the call it does
                                // not know about
                                return;
                            }
                        }
                        try
                        {
                            if (currCall.processIncomingMsg(packet.getMessageTxt()) == true &&
                                    newCallFlag == true)
                            {
                                   callDB.addCall(currCall);
                            }
                        }
                        catch (ScenarioException ex)
                        {
                            currCall.nextEntry();
                        }
                    }
                }
            }
            catch (IOException exc)
            {
            }
        }
    }
Regarding the last code snippet, I have few questions:
a) When selector selects, does it mean a single UDP packet arrived or it could mean multiple packets arrived?
b) Could it be, that due to a relatively high rate of incoming UDP packets, some of them are discarded?
c) Do you see any mistake in my code or logic?

Thanks in advance for all responses and guidances :-)
Comments
Locked Post
New comments cannot be posted to this locked post.
Post Details
Locked on Feb 2 2010
Added on Jan 4 2010
3 comments
524 views