DatagramChannel I/O

I have the following code and I can't figure out why it's looping out of control. If it only reads messages sent to it, it's fine and works as it should. If you try to write to the channel after reading, it goes into an infinite loop and doesn't stop. Anyone see something wrong with my code? I can't figure it out.
    ByteBuffer send = ByteBuffer.allocate(10);
    send.put((byte)'G');
    send.put((byte)'O');
    send.put((byte)'T');
    send.put((byte)' ');
    send.put((byte)'M');
    send.put((byte)'S');
    send.put((byte)'G');
    send.flip();
    //Allocate buffers
    ByteBuffer dst = ByteBuffer.allocateDirect(100);
    CharBuffer charBuffer = CharBuffer.allocate(100);
    DatagramChannel channel = DatagramChannel.open();
    channel.configureBlocking(false);
    DatagramSocket socket = channel.socket();
    InetSocketAddress isA = new InetSocketAddress(InetAddress.getByName("0.0.0.0"),4162);
    socket.bind(isA);
    boolean run = true;
    //New selector code!!
    while(run){
      Selector selector = Selector.open();
      channel.register(selector,SelectionKey.OP_READ);
      System.out.println("Channel registered,Selector opened");
      while(selector.isOpen()){
        int n = selector.select(50);
        if(n==0){
          //Nothing to do
          Thread.sleep(100);  //leave some room for other processes
          continue;
        //Get set of ready objects
        Iterator it = selector.selectedKeys().iterator();
        System.out.println("Iterator setup");
        //Look at each key in the set
        while(it.hasNext()){
          SelectionKey key =(SelectionKey)it.next();
          if(key.isReadable()){
            //read what is ready
            //Get Channel
            DatagramChannel dChannel = (DatagramChannel)key.channel();
            dst.clear();
            SocketAddress a = dChannel.receive(dst);
            System.out.println("Datapacket read from: " + a.toString() );
            dst.flip(); //Make buffer readable
            System.out.println("\n");
            for(int i=0; i < dst.limit(); i++ ){
              System.out.print((char)dst.get(i));
            dst.clear();
          }//End if readable
          it.remove();   //Remove key it's been handled
          channel.send(send,new InetSocketAddress(InetAddress.getByName("192.168.1.255"),4162));
        }//End while iterator
        selector.close();
      }//End while selector
    }

I made the changes to the code and here's what it's at now. If you see anything else that's strange let me know.
      Selector selector = Selector.open();
      channel.register(selector,SelectionKey.OP_READ);
      System.out.println("Channel registered,Selector opened");
      while(selector.isOpen()){
        int n = selector.select(50);
        if(n==0){
          //Nothing to do
          Thread.sleep(100);  //leave some room for other processes
          continue;
        //Get set of ready objects
        Iterator it = selector.selectedKeys().iterator();
        System.out.println("Iterator setup");
        //Look at each key in the set
        while(it.hasNext()){
          SelectionKey key =(SelectionKey)it.next();
          if(key.isReadable()){
            //read what is ready
            //Get Channel
            DatagramChannel dChannel = (DatagramChannel)key.channel();
            dst.clear();
            SocketAddress a = dChannel.receive(dst);
            System.out.println("Datapacket read from: " + a.toString() );
            dst.flip(); //Make buffer readable
            System.out.println("\n");
            for(int i=0; i < dst.limit(); i++ ){
              System.out.print((char)dst.get(i));
            send.flip();
            channel.send(send,new InetSocketAddress(InetAddress.getByName("192.168.1.255"),4162));
            send.rewind();
          }//End if readable
          it.remove();   //Remove key it's been handled         
        }//End while iterator
        selector.close();
      }//End while selector

Similar Messages

  • Acquiring local address for datagram socket created by DatagramChannel.open

    I've found that when I open an anonymous DatagramChannel (i.e. unbound, unconnected), the socket that it creates has no local address info I.e. no local port. Hopefully the example below will explain the problem...
    import java.nio.channels.DatagramChannel;
    import java.io.IOException;
    import java.net.DatagramSocket;
    import java.net.DatagramPacket;
    import java.net.InetAddress;
    public class QuickTest {
        public static void main( String[] args )    {
            try {
                DatagramChannel dc = DatagramChannel.open();
                DatagramSocket ds = dc.socket();
                byte[] ba = new byte[]{0,1,2,3};
                DatagramPacket dp = new DatagramPacket(ba,4,InetAddress.getLocalHost(),8000);
                ds.send(dp);
                System.out.println( "DatagramSocket from DatagramChannel");
                System.out.println();
                System.out.println( "          getInetAddress(): " + ds.getInetAddress());
                System.out.println( "         getLocalAddress(): " + ds.getLocalAddress ());
                System.out.println( "            getLocalPort(): " + ds.getLocalPort());
                System.out.println( "   getLocalSocketAddress(): " + ds.getLocalSocketAddress());
                System.out.println( "                 getPort(): " + ds.getPort());
                System.out.println( "  getRemoteSocketAddress(): " + ds.getRemoteSocketAddress());
                ds = new DatagramSocket();
                System.out.println();
                System.out.println();
                System.out.println();
                System.out.println( "DatagramSocket from new DatagramSocket()");
                System.out.println();
                System.out.println( "          getInetAddress(): " + ds.getInetAddress());
                System.out.println( "         getLocalAddress(): " + ds.getLocalAddress ());
                System.out.println( "            getLocalPort(): " + ds.getLocalPort());
                System.out.println( "   getLocalSocketAddress(): "    + ds.getLocalSocketAddress());
                System.out.println( "                 getPort(): " + ds.getPort());
                System.out.println( "  getRemoteSocketAddress(): " + ds.getRemoteSocketAddress());
            } catch (IOException e) {
                e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
    }Running this program yields the following information....
    DatagramSocket from DatagramChannel
    getInetAddress(): null
    getLocalAddress(): 0.0.0.0/0.0.0.0
    getLocalPort(): 0
    getLocalSocketAddress(): 0.0.0.0/0.0.0.0:0
    getPort(): -1
    getRemoteSocketAddress(): null
    DatagramSocket from new DatagramSocket()
    getInetAddress(): null
    getLocalAddress(): 0.0.0.0/0.0.0.0
    getLocalPort(): 1194
    getLocalSocketAddress(): 0.0.0.0/0.0.0.0:1194
    getPort(): -1
    getRemoteSocketAddress(): null
    I understand that the sockets address will be included in any packets sent, but why can I determine the port for one and not the other? I would like to continue using an anonymous channel, but I also would like to have the port for use in my test harness and for logging info...
    Any info and possible work around for this behavior would be much appreciated.
    tx in advance.

    This looks like a bug in the socket returned by DatagramSocketChannel and you should report it.
    In the meantime you could either just use DatagramSocket, or if you must have NIO you could try binding this socket to null or new InetSocketAddress(null,0) and see whether getLocalPort() now returns the right data.

  • DatagramChannel

    I want to develop an distributed application using multicast communication. For this I choose to usse the new IO APi(java.nio) but I have a problem. All the samples with this API show how to use ServerSocketChannels and SocketChannels. Can someone show me an sample of using DatagramChannel?

    It seems like you cannot use multicast sockets with the new API. See http://developer.java.sun.com/developer/bugParade/bugs/4527345.html

  • Bug in DatagramChannel close?

    The following code leaves an open (unbound UDP) socket on Linux and Solaris with J2SE 1.4.2_08 and JDK 1.5.0_03.
    DatagramChannel dc = DatagramChannel.open();
    dc.socket().bind(new InetSocketAddress(12345));
    dc.close();
    Is this a bug in Java or am I missing something?

    I have verified that the following code leaves a socket open on Linux with 1.4.2_08:
    DatagramChannel dc = DatagramChannel.open();
    DatagramSocket ds = dc.socket();
    ds.close();
    dc.close();
    The socket left open is the one created with the dc.socket() call. It is closed only after a full GC run (probably when the DatagramSocket is finalized), so I have to modify my application to call System.gc periodically. I'm not too happy with this workaround :(

  • Few question about reset DatagramChannel

    Hello,
    Im doing a communication program that uses Selectors with DatagramChannels, and implement bradcast receiving and sending.
    I was assigned to create a reset function, that should reset the communication in cases it gets stuck.
    When I close the DatagramSocket of the channel, it stays bounded, so I can't create new channel and bind it to the same port.
    Im new to this subject so i have some questions:
    1. When Im broadcasting, i don't have to connect, only to bind, right?
    2. Is there any way to "unbind"?
    3. Is it neccessary to do the reset? I mean, can a DatagramCahnnel even get stuck?
    Thanks
    Udi

    When I close the DatagramSocket of the channel, it
    stays bounded, so I can't create new channel and bind
    it to the same port.Call Selector.selectNow() after closing the DatagramSocketChannel or its DatagramSocket.
    1. When Im broadcasting, i don't have to connect,
    only to bind, right?Right
    2. Is there any way to "unbind"?See above
    3. Is it neccessary to do the reset? I mean, can a
    DatagramCahnnel even get stuck?No.

  • Maximum number of NIO DatagramChannels per instance

    Hi all
    im coding an application which requires to create over 1000 DatagramChannels per instance of the application.
    My environment is Solaris 8 & JDK 1.4.2._05.
    Im able to create only 508 channels, if i try to create 509th channel it throws the following exception:
    java.net.SocketException: Too many open files
    at sun.nio.ch.Net.socket0(Native Method)
    at sun.nio.ch.Net.socket(Net.java:96)
    at sun.nio.ch.DatagramChannelImpl.<init>(DatagramChannelImpl.java:83)
    at sun.nio.ch.SelectorProviderImpl.openDatagramChannel(SelectorProviderImpl.java:23)
    at java.nio.channels.DatagramChannel.open(DatagramChannel.java:82)
    Please note my solaris environment states the ulimit to be "unlimited"
    Can anybody throw some light on this??
    Thanks,

    I can open 3968 on Windows XP with this:
    import java.net.*;
    import java.util.*;
    import java.nio.channels.*;
    public class DatagramChannelCount
         public static void     main(String[] args) throws Exception
              int     count = 0;
              List<DatagramChannel>     list = new LinkedList<DatagramChannel>();
              try
                   for (;;)
                        DatagramChannel     dsch = DatagramChannel.open();
                        dsch.socket().bind(new InetSocketAddress(0));
                        list.add(dsch);
                        count++;
                        if ((count % 10) == 0)
                             System.out.println(count+" channels open.");
              catch (Exception exc)
                   exc.printStackTrace();
              System.out.println("Created "+count+" datagram channels.");
    }

  • DatagramChannel and ServerSocketChannel question

    For some reasons I need to switch between DatagramChannel and ServerSocketChannel. My program will use functions e.g. open(), socket(), etc. However, sometimes they do not use the same interface; for instance, DatagramChannel.socket() returns DatagramSocket whereas ServerSocketChannel.socket() ServerSocket. At the moment I make use of reflection to dynamic calling underlying functions.
    ServerSocketChannel ssc = ServerSocketChannel.open();
    ssc.socket().setReuseAddress(true);
    ssc.socket().bind(...);
    obj.getClass().getMethod("open", null).invoke(null, null);
    if (obj instanceof DatagramChannel){
        ((DatagramChannel)obj).socket().getClass().getMethod("setReuseAddress", Boolean.TYPE).invoke(((DatagramChannel)Obj).socket(), new Boolean("true"));
    }else if (obj instanceof ServerSocketChannel){
        .... // similar action
    ...This looks ugly because there are some other method executions (e.g. ServerSocketChannel.socket().configureBlocking(...) ) staying on the other part of the class/ program. So my question - is there any pattern that may simplify such kind of usage?
    I appreciate any suggestion.

    I would guess that your communications layer is ill defined. Or perhaps non-existent.
    Since you are using two different protocols it would seem likely that there is some differentiation in terms of messages on the two protocols. The communications layer should provide that differentiation and hide all of the details of that (and other communications details) from the levels that use it.

  • Bug: DatagramChannel bind/connect local address

    What are the chances of getting bug 6431343 fixed in JRockit?
    Basically, I need to be able to send a message from a specific local UDP port, and I also need to know the local address that the message will originate from.
    So when I bind using
    channel.socket().bind(new InetSocketAddress(9999));
    and then connect to the remote address
    channel.connect(new InetSocketAddress("localhost", 0));
    Then DatagramChannel should report the local address that any messages will originate from when I call
    channel2.socket().getLocalSocketAddress();
    but it instead seems to return a cached copy of the wildcard address as the local address.
    However, the behavior IS correct in a plain DatagramSocket.
    Here's a link to the bug:
    http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6431343
    Thanks very much for your attention.

    As you have assumed, we use Sun's networking code and therefore inherit their bugs. All bugs that Sun fix are fixed in the JRockit version with the same JDK level (i.e. Sun 5.0u8 -> JR 5.0u8).
    However, if you have a support contract with BEA (for JRockit, WebLogic etc) then you can open a ticket with BEA Support. The issue will be investigated, and if it is critical and no good workaround can be found then you will be provided with a patch.
    -- Henrik

  • Need help on DatagramChannel in new i/o api

    i have worked with new i/o but i never used DatagramChannel before. now i need this for more speed. i tried with this but failed. i dont find it works exactly the way api says. i need examples for both server side and client side programs. pls somebody help me.

    There is no guarentee that using DatagramChannel will make your program faster, unless you know that network traffic is your bottleneck.
    Have you seraches for examples on google.
    http://www.google.co.uk/search?q=java+DatagramChannel+%2Bexample

  • DatagramChannel and MulticastSocket

    Hi,
    I want to use DatagramChannel for reading and sending multicast data. However, I want to use a particular network interface. Only MulticastSocket has the API to bind to a particular network interface.
    The question is that DatagramChannel only can return a DatagramSocket. How can I use DatagramChannel with MulticastSocket?
    Regards
    Freddie

    DatagramChannel only supports unicast datagrams at this time. Multicast support is on the list for tiger, see :-
    http://developer.java.sun.com/developer/bugParade/bugs/4527345.html

  • In DatagramChannels - what is the difference between

    connect() and socket().bind()? i know that in connect i limit the send/receive to the address, but is this the case also in bind() or i can receive from any address?
    Thanks.

    In DatagramChannels - what is the difference between
    Socket.connect() and Socket.bind()? A server socket uses bind() before listen().
    Usually a client socket does not use bind() before connect().
    I know that in connect I limit the send/receive to the address, but is this
    the case also in bind() or i can receive from any address?When you say 'address' - do you mean 'port'?

  • DatagramChannel wont connect()/bind()

    im currently using an NIO-selector which has SocketChannel and DatagramChannel registered.
    TCP over SocketChannel works fine, UDP over the DatagramChannels does not, the NIO-selector does not fire any events on incoming udp-packets.
    i already sniffed the traffic, everything fine.
    i just read chapter3 of Java NIO from oreilly and thought and experimented with their DatagramChannel examples, the results are more than confusing:
    UDPChannel.connect(new InetSocketAddress("localhost", 20123));
    UDPChannel.isConnected() == true
    no events whatsoever
    UDPChannel.socket().bind(new InetSocketAddress("localhost", 20123));
    UDPChannel.isConnected() == false
    BUT read-event is fired on incoming udp-packets. but the Exception NotYetConnected is thrown when trying to read from the channel
    UDPChannel.socket().connect(new InetSocketAddress("localhost", 20123));
    UDPChannel.isConnected() == false and no read-event
    so the only possibility to get a read-event from the NIO-selector is to bind the listing/serving DatagramChannel using the socket().bind()-construct but this does not "connect()" ....
    what to do???
    yours,
    kai

    As it says in the Javadoc, if you are using NIO and DatagramChannel.write() you have to connect the channel to the target, so that NIO knows where to send the packets, because the write() API doesn't have the target address and neither does the ByteBuffer.
    If you use DatagramChannel.send() you don't have to connect: the send() API includes a target address parameter.
    If you want to receive datagram packets at a certain local port you have to bind to that port.
    So:
    (a) if you use DatagramChannel.send() you only have to do the bind()
    (b) if you use DatagramChannel.write() you have to do bind() and connect().
    This is all documented in the Javadoc.

  • NIO DatagramChannels

    I can't get my DatagramChannel to receive input after it sends a packet out on the network. I want to be able to send a receive on the same socket (non-blocking). It's not throwing any exceptions, it's just not getting data. My infinite while loop is in there just for testing the network. The whole problem is that the receive method just doesn't fill my buffer. Any reason why?
        ByteBuffer send = ByteBuffer.allocate(4);
        send.put((byte)'T');
        send.put((byte)'E');
        send.put((byte)'S');
        send.put((byte)'T');
        send.flip();
        ByteBuffer dst = ByteBuffer.allocate(10);
        DatagramChannel channel = DatagramChannel.open();
        channel.configureBlocking(false);
        InetSocketAddress isa = new InetSocketAddress(4163);
        DatagramSocket socket = channel.socket();
          while(true){
            send.position(0);
            channel.send(send,new InetSocketAddress(InetAddress.getByName("192.168.0.255"),4162));
            channel.receive(dst);
          }

    Below is a copy/paste of part of an inner class that I use to manage input from a DatagramChannel. You're on your own figuring this out, I will say that the code that this was copied from does work for me and is currently in production even though parts are quite ugly. Maybe you can learn something from it.
    static class ServerUpdater implements Runnable {
            private static final transient Logger logger = Logger.getLogger(ServerUpdater.class.getName());
            private Thread threadUpdater;
            private Selector acceptSelector = null;
            ServerUpdater() {
                logger.finest("UpdateManager.ServerUpdate.<init>()");
            void register(DatagramChannel channel, DatagramChannelConsumer consumer) {
                logger.finest("UpdateManager.ServerUpdate.register(DatagramChannel,DatagramChannelConsumer)");
                init();
                try {
                    channel.register(acceptSelector, SelectionKey.OP_READ, consumer);
                } catch (ClosedChannelException e) {
                    e.printStackTrace();
                acceptSelector.wakeup(); // Make this get processed asap.
            synchronized void init() {
                logger.finest("UpdateManager.ServerUpdate.init()");
                if (acceptSelector == null) {
                    logger.fine("if (acceptSelector == null)");
                    try {
                        acceptSelector = SelectorProvider.provider().openSelector();
                    } catch (IOException ioe) {
                        logger.log(Level.SEVERE, "Problem getting a selector", ioe);
                    threadUpdater = new Thread(this, "Server UpdateManager");
                    threadUpdater.setDaemon(true);
                    threadUpdater.start();
            public void run() {
                logger.finest("UpdateManager.ServerUpdate.run()");
                //Thread.sleep(1000 * 0); // TODO: Do this right
                run0();
            private void run0() {
                logger.finest("UpdateManager.ServerUpdate.run0()");
                // TODO: We need to only start this while loop when we have at least one
                // Here's where everything happens. The select method will
                // return when any operations registered above have occurred, the
                // thread has been interrupted, etc.
                logger.finer("START: while ((numKeysAdded = acceptSelector.select()) > 0)");
                while (acceptSelector.isOpen()) {
                    try {
                        acceptSelector.select(2000);
                        logger.finer("LOOP: while ((numKeysAdded = acceptSelector.select()) > 0)");
                        // Someone is ready for I/O, get the ready keys
                        Set readyKeys = acceptSelector.selectedKeys();
                        processKeys(readyKeys.iterator());
                    } catch (IOException ioe) {
                        logger.log(Level.WARNING, "IOExcpetion in run0()", ioe);
                logger.finer("END: while ((numKeysAdded = acceptSelector.select()) > 0)");
            private void processKeys(Iterator iter) {
                logger.finest("UpdateManager.ServerUpdate.processKeys(Iterator)");
                // Walk through the ready keys collection and process new data.
                while (iter.hasNext()) {
                    SelectionKey selectionKey = (SelectionKey)iter.next();
                    iter.remove();
                    // The key indexes into the selector so you
                    // can retrieve the socket that'socket ready for I/O
                    DatagramChannel channel = (DatagramChannel)selectionKey.channel();
                    DatagramChannelConsumer consumer = (DatagramChannelConsumer)selectionKey.attachment();
                    consumer.consume(channel);
    }and
    interface DatagramChannelConsumer {
        public void consume(DatagramChannel channel);
    }

  • Can i write to a DatagramChannel from 2 threads?

    Without using a Selector - i wanna give one thread an option to read from the channel and right after that - to write, and give another thread that receives the channel as parameter
    the option to write whenever it needs (a condition i'm using).
    The API says "Datagram channels are safe for use by multiple concurrent threads. They support concurrent reading and writing, though at most one thread may be reading and at
    most one thread may be writing at any given time." - can i rely on that?
    Thanks,
    Snayit

    This works fine for other Channel types but I haven't tried DatagramChannel

  • Possible to get ReadableByteChannel from MulticastSocket???

    Hi,
    I am trying to get a ReadableByteChannel from a Multicast socket. The MulticastSocket class inherits from DatagramSocket which has a getChannel() method. The channel is always null when I try to use it (I dont' think it is getting initialized properly....see below)
    InetAddress group = InetAddress.getByName(hostname);
    MulticastSocket s = new MulticastSocket(port);
    ReadableByteChannel source = s.getChannel();  // this is always returning null
    s.joinGroup(group);
    I think the reason it is null is because:
    A datagram socket will have a channel if, and only if, the channel itself was created via the DatagramChannel.open method.
    I can't figure out how to use this properly. Any ideas???

    You are correct. As there is no MulticastSocketChannel (yet), you can't have created one by calling MulticastSocketChannel.open(), so MulticastSocket.getChannel() returns null.
    It's coming in 1.7 (finally ...)

Maybe you are looking for