You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@mina.apache.org by Trustin Lee <tr...@gmail.com> on 2007/09/17 09:07:31 UTC

Request for a test on various platforms:

Hi,

I made a lot of changes to the current datagram implementation in
trunk.  DatagramAcceptor now collaborates with DatagramConnector to
create connected datagram socket which listens to the remote address
of the received packet.  The following is simplified description of
flow:

* DatagramAcceptor's underlying DatagramChannel.receive is invoked
* Once data is received, new connected datagram session is created
using DatagramConnector.connect(receivedRemoteAddress,
acceptor.getLocalAddress()).  If there's already a session instance
associated with the remote address, it's reused.

The advantages of this implementation are:

* The acceptor-side datagram sessions can perform much better in
multi-core environment.
* There's no need for IoSessionRecycler on the acceptor-side anymore.
You have full control over disconnection; probably using sessionIdle
event in most cases.
* Code duplication can be reduced once again, and most part of the
existing acceptor code can be extracted into a generic acceptor
implementation.

The disadvantage is that it forces you to set reuseAddress to true,
because multiple datagram channels are bound to the same local
address.

In Linux, connected datagram channels have priority over unconnected
channels, so most traffic will go directly into DatagramConnector's
NIOProcessors.  The only exception I've found is broadcast packets. It
is always received from the unconnected channel in DatagramAcceptor.
DatagramAcceptor immediately forwards the event to an appropriate
session that DatagramConnector is managing, or creates a new session
using connect().

I think this behavior won't have any big differences among different
platforms (e.g. Windows and SUNOS).  As long as multiple datagram
channels can be bound to the same local address, this implementation
should work fine.  To make this sure, please run the following test
code in your machine, and let me know what the result is:

-------- CODE BEGINS --------
package net.gleamynode.tmp;

import java.net.InetAddress;
import java.net.InetSocketAddress;

import org.apache.mina.common.ByteBuffer;
import org.apache.mina.common.ConnectFuture;
import org.apache.mina.common.IoHandlerAdapter;
import org.apache.mina.common.IoSession;
import org.apache.mina.transport.socket.nio.DatagramAcceptor;
import org.apache.mina.transport.socket.nio.DatagramConnector;

public class Main {

    private static final int SERVER_PORT = 1234;
    private static final int CLIENT_PORT = 5678;

    public static void main(String args[]) throws Exception {
        DatagramAcceptor acceptor = new DatagramAcceptor();
        acceptor.setLocalAddress(new InetSocketAddress(SERVER_PORT));
        acceptor.setHandler(new IoHandlerAdapter() {
            @Override
            public void sessionOpened(IoSession session) {
                System.out.println("Open: " + session);
            }

            @Override
            public void sessionClosed(IoSession session) {
                System.out.println("Closed: " + session);
            }

            @Override
            public void messageReceived(IoSession session, Object o) {
                System.out.println("Received: " + session + ", " + o);
            }
        });
        acceptor.bind();

        DatagramConnector connector = new DatagramConnector();
        connector.getSessionConfig().setReuseAddress(true);
        connector.setHandler(new IoHandlerAdapter() {
            @Override
            public void messageReceived(IoSession session, Object o) {
                System.out.println("ERR?");
            }
        });

        // Print the local host.
        System.out.println("Local host: " + InetAddress.getLocalHost());

        // Try point-to-point.
        ConnectFuture f1 = connector.connect(
                new InetSocketAddress(
                        InetAddress.getLocalHost(), SERVER_PORT),
                new InetSocketAddress(
                        InetAddress.getLocalHost(), CLIENT_PORT));
        f1.await();


        f1.getSession().write(ByteBuffer.allocate(1)).await();
        f1.getSession().write(ByteBuffer.allocate(1)).await();


        // Try broadcast.
        ConnectFuture f2 = connector.connect(
                new InetSocketAddress(
                        "255.255.255.255", SERVER_PORT),
                new InetSocketAddress(
                        InetAddress.getLocalHost(), CLIENT_PORT));

        f2.await();
        f2.getSession().write(ByteBuffer.allocate(1)).await();
        f2.getSession().write(ByteBuffer.allocate(1)).await();

        acceptor.unbind();

        System.exit(0);
    }
}
-------- CODE ENDS --------

The expected result is:

-------- RESULT BEGINS --------
Local host: primary/127.0.0.1
Open: (datagram, server, /127.0.0.1:5678 => /0:0:0:0:0:0:0:0:1234)
Received: (datagram, server, /127.0.0.1:5678 =>
/0:0:0:0:0:0:0:0:1234), HeapBuffer[pos=0 lim=1 cap=2048: 00]
Received: (datagram, server, /127.0.0.1:5678 =>
/0:0:0:0:0:0:0:0:1234), HeapBuffer[pos=0 lim=1 cap=2048: 00]
Received: (datagram, server, /127.0.0.1:5678 =>
/0:0:0:0:0:0:0:0:1234), HeapBuffer[pos=0 lim=1 cap=2048: 00]
Closed: (datagram, server, /127.0.0.1:5678 => /0:0:0:0:0:0:0:0:1234)
-------- RESULT ENDS --------

If this test fails on any platform that runs Java 5, I am doomed to
revert my changes. :)

Trustin
-- 
what we call human nature is actually human habit
--
http://gleamynode.net/
--
PGP Key ID: 0x0255ECA6

Re: Request for a test on various platforms:

Posted by Mark <el...@gmail.com>.
I have seen dozens on a box.

-- 
..Cheers
Mark

On 9/18/07, Trustin Lee <tr...@gmail.com> wrote:
>
> How many network devices exist in SunOS?
>
> Thanks!
> Trustin
>
> On 9/18/07, Maarten Bosteels <mb...@gmail.com> wrote:
> > On SunOS 5.10  sun4u sparc SUNW,Sun-Fire-V890
> >
> > java version "1.5.0_01"
> > Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0_01-b08)
> > Java HotSpot(TM) Server VM (build 1.5.0_01-b08, mixed mode)
> >
> > Open: (datagram, server, /10.0.0.120:5678 => /0.0.0.0:1234)
> > Received: (datagram, server, /10.0.0.120:5678 => /0.0.0.0:1234),
> > HeapBuffer[pos=0 lim=1 cap=2048: 00]
> > Received: (datagram, server, /10.0.0.120:5678 => /0.0.0.0:1234),
> > HeapBuffer[pos=0 lim=2 cap=2048: 00 00]
> > Received: (datagram, server, /10.0.0.120:5678 => /0.0.0.0:1234),
> > HeapBuffer[pos=0 lim=3 cap=2048: 00 00 00]
> > Received: (datagram, server, /10.0.0.120:5678 => /0.0.0.0:1234),
> > HeapBuffer[pos=0 lim=3 cap=2048: 00 00 00]
> > Received: (datagram, server, /10.0.0.120:5678 => /0.0.0.0:1234),
> > HeapBuffer[pos=0 lim=4 cap=2048: 00 00 00 00]
> > Received: (datagram, server, /10.0.0.120:5678 => /0.0.0.0:1234),
> > HeapBuffer[pos=0 lim=4 cap=2048: 00 00 00 00]
> > unbound
> > Closed: (datagram, server, /10.0.0.120:5678 => /0.0.0.0:1234)
> >
> > Maarten
> >
> > On 9/18/07, Maarten Bosteels <mb...@gmail.com> wrote:
> > >
> > > On linux 2.6.9, jdk 1.6
> > >
> > > Local host: mortimer/172.30.6.12
> > > Open: (datagram, server, /172.30.6.12:5678 => /0:0:0:0:0:0:0:0:1234)
> > > Received: (datagram, server, /172.30.6.12:5678 =>
> /0:0:0:0:0:0:0:0:1234),
> > > HeapBuffer[pos=0 lim=1 cap=2048: 00]
> > > Received: (datagram, server, /172.30.6.12:5678 =>
> /0:0:0:0:0:0:0:0:1234),
> > > HeapBuffer[pos=0 lim=2 cap=2048: 00 00]
> > > Received: (datagram, server, /172.30.6.12:5678 =>
> /0:0:0:0:0:0:0:0:1234),
> > > HeapBuffer[pos=0 lim=3 cap=2048: 00 00 00]
> > > Received: (datagram, server, /172.30.6.12:5678 =>
> /0:0:0:0:0:0:0:0:1234),
> > > HeapBuffer[pos=0 lim=4 cap=2048: 00 00 00 00]
> > > unbound
> > > Closed: (datagram, server, /172.30.6.12:5678 => /0:0:0:0:0:0:0:0:1234)
> > >
> > > Adding a virtual interface (eth0:0) doesn't make a difference.
> > > Maarten
> > >
> > > On 9/18/07, Maarten Bosteels < mbosteels.dns@gmail.com> wrote:
> > > >
> > > > Hello Trustin,
> > > >
> > > > I ran the code on Windows XP jdk 1.6 , and this is the output I got:
> > > >
> > > > Local host: kweenie/172.29.100.104
> > > > Open: (datagram, server, /172.29.100.104:5678 => /0.0.0.0:1234)
> > > > Received: (datagram, server, /172.29.100.104:5678 => /0.0.0.0:1234),
> > > > HeapBuffer[pos=0 lim=2 cap=2048: 00 00]
> > > > Received: (datagram, server, /172.29.100.104:5678 => /0.0.0.0:1234),
> > > > HeapBuffer[pos=0 lim=1 cap=2048: 00]
> > > > Received: (datagram, server, /172.29.100.104:5678 => /0.0.0.0:1234),
> > > > HeapBuffer[pos=0 lim=3 cap=2048: 00 00 00]
> > > > Received: (datagram, server, /172.29.100.104:5678 => /0.0.0.0:1234),
> > > > HeapBuffer[pos=0 lim=3 cap=2048: 00 00 00]
> > > > Received: (datagram, server, /172.29.100.104:5678 => /0.0.0.0:1234),
> > > > HeapBuffer[pos=0 lim=3 cap=2048: 00 00 00]
> > > > Received: (datagram, server, /172.29.100.104:5678 => /0.0.0.0:1234),
> > > > HeapBuffer[pos=0 lim=3 cap=2048: 00 00 00]
> > > > Received: (datagram, server, /172.29.100.104:5678 => /0.0.0.0:1234),
> > > > HeapBuffer[pos=0 lim=4 cap=2048: 00 00 00 00]
> > > > Received: (datagram, server, /172.29.100.104:5678 => /0.0.0.0:1234),
> > > > HeapBuffer[pos=0 lim=4 cap=2048: 00 00 00 00]
> > > > Received: (datagram, server, /172.29.100.104:5678 => /0.0.0.0:1234),
> > > > HeapBuffer[pos=0 lim=4 cap=2048: 00 00 00 00]
> > > > Received: (datagram, server, /172.29.100.104:5678 => /0.0.0.0:1234),
> > > > HeapBuffer[pos=0 lim=4 cap=2048: 00 00 00 00]
> > > > Closed: (datagram, server, /172.29.100.104:5678 => /0.0.0.0:1234)
> > > > unbound
> > > >
> > > > I changed the code a little bit, to be able to distinguish the
> messages.
> > > >
> > > > Also added a sleep before the unbind, (I think there's one line
> missing
> > > > in your output :-)
> > > >
> > > >        f1.getSession().write(ByteBuffer.allocate(1)).await();
> > > >        f1.getSession().write( ByteBuffer.allocate(2)).await();
> > > >
> > > >        f2.getSession().write(ByteBuffer.allocate(3)).await();
> > > >        f2.getSession().write(ByteBuffer.allocate(4)).await();
> > > >
> > > >        Thread.sleep(2000);
> > > >        acceptor.unbind();
> > > >        System.out.println ("unbound");
> > > >        System.exit(0);
> > > >
> > > > The messages sent to the broadcast address are received multiple
> times:
> > > > twice per enabled network connection.
> > > > When I enable all 4 network interfaces (LAN, wireless LAN and two
> > > > virtual ones for VMWare) I receive them 8 times !
> > > >
> > > > Maarten
> > > >
> > > > On 9/17/07, Trustin Lee < trustin@gmail.com> wrote:
> > > > >
> > > > > Hi,
> > > > >
> > > > > I made a lot of changes to the current datagram implementation in
> > > > > trunk.  DatagramAcceptor now collaborates with DatagramConnector
> to
> > > > > create connected datagram socket which listens to the remote
> address
> > > > > of the received packet.  The following is simplified description
> of
> > > > > flow:
> > > > >
> > > > > * DatagramAcceptor's underlying DatagramChannel.receive is invoked
> > > > > * Once data is received, new connected datagram session is created
> > > > > using DatagramConnector.connect(receivedRemoteAddress,
> > > > > acceptor.getLocalAddress()).  If there's already a session
> instance
> > > > > associated with the remote address, it's reused.
> > > > >
> > > > > The advantages of this implementation are:
> > > > >
> > > > > * The acceptor-side datagram sessions can perform much better in
> > > > > multi-core environment.
> > > > > * There's no need for IoSessionRecycler on the acceptor-side
> anymore.
> > > > > You have full control over disconnection; probably using
> sessionIdle
> > > > > event in most cases.
> > > > > * Code duplication can be reduced once again, and most part of the
> > > > > existing acceptor code can be extracted into a generic acceptor
> > > > > implementation.
> > > > >
> > > > > The disadvantage is that it forces you to set reuseAddress to
> true,
> > > > > because multiple datagram channels are bound to the same local
> > > > > address.
> > > > >
> > > > > In Linux, connected datagram channels have priority over
> unconnected
> > > > > channels, so most traffic will go directly into
> DatagramConnector's
> > > > > NIOProcessors.  The only exception I've found is broadcast
> packets. It
> > > > > is always received from the unconnected channel in
> DatagramAcceptor.
> > > > > DatagramAcceptor immediately forwards the event to an appropriate
> > > > > session that DatagramConnector is managing, or creates a new
> session
> > > > > using connect().
> > > > >
> > > > > I think this behavior won't have any big differences among
> different
> > > > > platforms (e.g. Windows and SUNOS).  As long as multiple datagram
> > > > > channels can be bound to the same local address, this
> implementation
> > > > > should work fine.  To make this sure, please run the following
> test
> > > > > code in your machine, and let me know what the result is:
> > > > >
> > > > > -------- CODE BEGINS --------
> > > > > package net.gleamynode.tmp;
> > > > >
> > > > > import java.net.InetAddress;
> > > > > import java.net.InetSocketAddress;
> > > > >
> > > > > import org.apache.mina.common.ByteBuffer;
> > > > > import org.apache.mina.common.ConnectFuture;
> > > > > import org.apache.mina.common.IoHandlerAdapter ;
> > > > > import org.apache.mina.common.IoSession;
> > > > > import org.apache.mina.transport.socket.nio.DatagramAcceptor;
> > > > > import org.apache.mina.transport.socket.nio.DatagramConnector;
> > > > >
> > > > > public class Main {
> > > > >
> > > > >     private static final int SERVER_PORT = 1234;
> > > > >     private static final int CLIENT_PORT = 5678;
> > > > >
> > > > >     public static void main(String args[]) throws Exception {
> > > > >         DatagramAcceptor acceptor = new DatagramAcceptor();
> > > > >         acceptor.setLocalAddress (new
> InetSocketAddress(SERVER_PORT));
> > > > >
> > > > >         acceptor.setHandler(new IoHandlerAdapter() {
> > > > >             @Override
> > > > >             public void sessionOpened(IoSession session) {
> > > > >                 System.out.println("Open: " + session);
> > > > >             }
> > > > >
> > > > >             @Override
> > > > >             public void sessionClosed(IoSession session) {
> > > > >                 System.out.println("Closed: " + session);
> > > > >             }
> > > > >
> > > > >             @Override
> > > > >             public void messageReceived(IoSession session, Object
> o) {
> > > > >
> > > > >                 System.out.println("Received: " + session + ", " +
> o);
> > > > >             }
> > > > >         });
> > > > >         acceptor.bind();
> > > > >
> > > > >         DatagramConnector connector = new DatagramConnector();
> > > > >         connector.getSessionConfig().setReuseAddress(true);
> > > > >         connector.setHandler(new IoHandlerAdapter() {
> > > > >             @Override
> > > > >             public void messageReceived(IoSession session, Object
> o) {
> > > > >                 System.out.println("ERR?");
> > > > >             }
> > > > >         });
> > > > >
> > > > >         // Print the local host.
> > > > >         System.out.println("Local host: " +
> InetAddress.getLocalHost
> > > > > ());
> > > > >
> > > > >         // Try point-to-point.
> > > > >         ConnectFuture f1 = connector.connect(
> > > > >                 new InetSocketAddress(
> > > > >                         InetAddress.getLocalHost(), SERVER_PORT),
> > > > >                 new InetSocketAddress(
> > > > >                          InetAddress.getLocalHost(),
> CLIENT_PORT));
> > > > >         f1.await();
> > > > >
> > > > >
> > > > >         f1.getSession().write(ByteBuffer.allocate(1)).await();
> > > > >         f1.getSession().write(ByteBuffer.allocate(1)).await();
> > > > >
> > > > >
> > > > >         // Try broadcast.
> > > > >         ConnectFuture f2 = connector.connect(
> > > > >                 new InetSocketAddress(
> > > > >                         " 255.255.255.255", SERVER_PORT),
> > > > >                 new InetSocketAddress(
> > > > >                         InetAddress.getLocalHost(), CLIENT_PORT));
> > > > >
> > > > >         f2.await();
> > > > >         f2.getSession().write(ByteBuffer.allocate(1)).await();
> > > > >         f2.getSession().write(ByteBuffer.allocate(1)).await();
> > > > >
> > > > >         acceptor.unbind();
> > > > >
> > > > >         System.exit(0);
> > > > >     }
> > > > > }
> > > > > -------- CODE ENDS --------
> > > > >
> > > > > The expected result is:
> > > > >
> > > > > -------- RESULT BEGINS --------
> > > > > Local host: primary/127.0.0.1
> > > > > Open: (datagram, server, /127.0.0.1:5678 => /0:0:0:0:0:0:0:0:1234)
> > > > > Received: (datagram, server, /127.0.0.1:5678 =>
> > > > > /0:0:0:0:0:0:0:0:1234), HeapBuffer[pos=0 lim=1 cap=2048: 00]
> > > > > Received: (datagram, server, /127.0.0.1:5678 =>
> > > > > /0:0:0:0:0:0:0:0:1234), HeapBuffer[pos=0 lim=1 cap=2048: 00]
> > > > > Received: (datagram, server, /127.0.0.1:5678 =>
> > > > > /0:0:0:0:0:0:0:0:1234), HeapBuffer[pos=0 lim=1 cap=2048: 00]
> > > > > Closed: (datagram, server, /127.0.0.1:5678 =>
> /0:0:0:0:0:0:0:0:1234)
> > > > > -------- RESULT ENDS --------
> > > > >
> > > > > If this test fails on any platform that runs Java 5, I am doomed
> to
> > > > > revert my changes. :)
> > > > >
> > > > > Trustin
> > > > > --
> > > > > what we call human nature is actually human habit
> > > > > --
> > > > > http://gleamynode.net/
> > > > > --
> > > > > PGP Key ID: 0x0255ECA6
> > > > >
> > > >
> > > >
> > >
> >
>
>
> --
> what we call human nature is actually human habit
> --
> http://gleamynode.net/
> --
> PGP Key ID: 0x0255ECA6
>

Re: Request for a test on various platforms:

Posted by Maarten Bosteels <mb...@gmail.com>.
On 9/18/07, Trustin Lee <tr...@gmail.com> wrote:
>
> It seems like each broadcast packet is broadcasted as many times as
> the number of network interface cards in Windows and SunOS.  It's
> interesting that Linux doesn't.  Maarten, did I understand correctly?


Yes, that's what I think as well, except that on Windows it's being
broadcasted *twice* per  network interface.
When I disable all interfaces except LAN, I see the broadcast messages
twice.
When I enable LAN + wireless LAN => I see each message 4 times
3 interfaces => each message 6 times
4 interfaces => each message 8 times

When I disable all interfaces, I only see the non-broadcast messages.

I'd like to find a way to suppress the duplicate event emission, but
> don't have any idea yet.


Me neither. Haven't got experience with broadcasting.

Maarten

Thanks,
> Trustin
>
> On 9/18/07, Maarten Bosteels <mb...@gmail.com> wrote:
> > Also tested it on a Solaris box  with just one network interface:
> >
> > [root@mercury tmp]$ ifconfig -a
> > lo0: flags=2001000849<UP,LOOPBACK,RUNNING,MULTICAST,IPv4,VIRTUAL> mtu
> 8232
> > index 1
> >         inet 127.0.0.1 netmask ff000000
> > hme0: flags=1000843<UP,BROADCAST,RUNNING,MULTICAST,IPv4> mtu 1500 index
> 2
> >         inet 172.30.0.139 netmask ffff0000 broadcast 172.30.255.255
> >         ether 8:0:20:e6:85:18
> > [root@mercury tmp]$
> > [root@mercury tmp]$ uname -a
> > SunOS mercury 5.10 Generic_118833-24 sun4u sparc SUNW,Ultra-250
> > [root@mercury tmp]$
> > [root@mercury tmp]$ java -cp mina-core-2.0.0-M1-SNAPSHOT.jar:.
> TestTrustin
> > Local host: mercury/172.30.0.139
> > Open: (datagram, server, /172.30.0.139:5678 => /0.0.0.0:1234)
> > Received: (datagram, server, /172.30.0.139:5678 => /0.0.0.0:1234),
> > HeapBuffer[pos=0 lim=1 cap=2048: 00]
> > Received: (datagram, server, /172.30.0.139:5678 => /0.0.0.0:1234),
> > HeapBuffer[pos=0 lim=2 cap=2048: 00 00]
> > Received: (datagram, server, /172.30.0.139:5678 => /0.0.0.0:1234),
> > HeapBuffer[pos=0 lim=3 cap=2048: 00 00 00]
> > Received: (datagram, server, /172.30.0.139:5678 => /0.0.0.0:1234),
> > HeapBuffer[pos=0 lim=4 cap=2048: 00 00 00 00]
> > unbound
> > Closed: (datagram, server, /172.30.0.139:5678 => /0.0.0.0:1234)
> > [root@mercury tmp]$
> >
> > Maarten
> >
> > On 9/18/07, Maarten Bosteels <mb...@gmail.com> wrote:
> > >
> > > On 9/18/07, Trustin Lee <tr...@gmail.com> wrote:
> > > >
> > > > How many network devices exist in SunOS?
> > >
> > >
> > >
> > > root@mysun # ifconfig -a
> > > lo0: flags=2001000849<UP,LOOPBACK,RUNNING,MULTICAST,IPv4,VIRTUAL> mtu
> 8232
> > > index 1
> > >         inet 127.0.0.1 netmask ff000000
> > > ce0: flags=1000843<UP,BROADCAST,RUNNING,MULTICAST,IPv4> mtu 1500 index
> 2
> > >         inet 192.168.113.8 netmask ffffff00 broadcast 192.168.113.255
> > >         ether 0:14:4f:17:d:de
> > > ce1: flags=1000802<BROADCAST,MULTICAST,IPv4> mtu 1500 index 3
> > >         inet 0.0.0.0 netmask 0
> > >         ether 0:14:4f:17:d:df
> > > ce2: flags=1000802<BROADCAST,MULTICAST,IPv4> mtu 1500 index 4
> > >         inet 0.0.0.0 netmask 0
> > >         ether 0:14:4f:17:d:e0
> > > eri0: flags=1000843<UP,BROADCAST,RUNNING,MULTICAST,IPv4> mtu 1500
> index 5
> > >         inet 10.0.0.120 netmask ffffff00 broadcast 10.0.0.255
> > >         ether 0:3:ba:b0:49:65
> > > eri0:1: flags=1040843<UP,BROADCAST,RUNNING,MULTICAST,DEPRECATED,IPv4>
> mtu
> > > 1500 index 5
> > >         inet 10.0.0.130 netmask ffffff00 broadcast 10.0.0.255
> > >
> > > Maarten
> > >
> > > Thanks!
> > > > Trustin
> > > >
> > > > On 9/18/07, Maarten Bosteels <mb...@gmail.com> wrote:
> > > > > On SunOS 5.10  sun4u sparc SUNW,Sun-Fire-V890
> > > > >
> > > > > java version " 1.5.0_01"
> > > > > Java(TM) 2 Runtime Environment, Standard Edition (build
> 1.5.0_01-b08)
> > > > > Java HotSpot(TM) Server VM (build 1.5.0_01-b08, mixed mode)
> > > > >
> > > > > Open: (datagram, server, /10.0.0.120:5678 => /0.0.0.0:1234)
> > > > > Received: (datagram, server, /10.0.0.120:5678 => /0.0.0.0:1234),
> > > > > HeapBuffer[pos=0 lim=1 cap=2048: 00]
> > > > > Received: (datagram, server, /10.0.0.120:5678 => /0.0.0.0:1234),
> > > > > HeapBuffer[pos=0 lim=2 cap=2048: 00 00]
> > > > > Received: (datagram, server, /10.0.0.120:5678 => /0.0.0.0:1234),
> > > > > HeapBuffer[pos=0 lim=3 cap=2048: 00 00 00]
> > > > > Received: (datagram, server, /10.0.0.120:5678 => /0.0.0.0:1234),
> > > > > HeapBuffer[pos=0 lim=3 cap=2048: 00 00 00]
> > > > > Received: (datagram, server, /10.0.0.120:5678 => /0.0.0.0:1234),
> > > > > HeapBuffer[pos=0 lim=4 cap=2048: 00 00 00 00]
> > > > > Received: (datagram, server, /10.0.0.120:5678 => /0.0.0.0:1234),
> > > > > HeapBuffer[pos=0 lim=4 cap=2048: 00 00 00 00]
> > > > > unbound
> > > > > Closed: (datagram, server, /10.0.0.120:5678 => /0.0.0.0:1234)
> > > > >
> > > > > Maarten
> > > > >
> > > > > On 9/18/07, Maarten Bosteels <mbosteels.dns@gmail.com > wrote:
> > > > > >
> > > > > > On linux 2.6.9, jdk 1.6
> > > > > >
> > > > > > Local host: mortimer/172.30.6.12
> > > > > > Open: (datagram, server, /172.30.6.12:5678 =>
> /0:0:0:0:0:0:0:0:1234)
> > > > > > Received: (datagram, server, /172.30.6.12:5678 =>
> > > > /0:0:0:0:0:0:0:0:1234),
> > > > > > HeapBuffer[pos=0 lim=1 cap=2048: 00]
> > > > > > Received: (datagram, server, /172.30.6.12:5678 =>
> > > > /0:0:0:0:0:0:0:0:1234),
> > > > > > HeapBuffer[pos=0 lim=2 cap=2048: 00 00]
> > > > > > Received: (datagram, server, /172.30.6.12:5678 =>
> > > > /0:0:0:0:0:0:0:0:1234),
> > > > > > HeapBuffer[pos=0 lim=3 cap=2048: 00 00 00]
> > > > > > Received: (datagram, server, /172.30.6.12:5678 =>
> > > > /0:0:0:0:0:0:0:0:1234),
> > > > > > HeapBuffer[pos=0 lim=4 cap=2048: 00 00 00 00]
> > > > > > unbound
> > > > > > Closed: (datagram, server, /172.30.6.12:5678 =>
> > > > /0:0:0:0:0:0:0:0:1234)
> > > > > >
> > > > > > Adding a virtual interface (eth0:0) doesn't make a difference.
> > > > > > Maarten
> > > > > >
> > > > > > On 9/18/07, Maarten Bosteels < mbosteels.dns@gmail.com> wrote:
> > > > > > >
> > > > > > > Hello Trustin,
> > > > > > >
> > > > > > > I ran the code on Windows XP jdk 1.6 , and this is the output
> I
> > > > got:
> > > > > > >
> > > > > > > Local host: kweenie/172.29.100.104
> > > > > > > Open: (datagram, server, /172.29.100.104:5678 =>
> /0.0.0.0:1234)
> > > > > > > Received: (datagram, server, /172.29.100.104:5678 =>
> > > > /0.0.0.0:1234),
> > > > > > > HeapBuffer[pos=0 lim=2 cap=2048: 00 00]
> > > > > > > Received: (datagram, server, /172.29.100.104:5678 =>
> > > > /0.0.0.0:1234),
> > > > > > > HeapBuffer[pos=0 lim=1 cap=2048: 00]
> > > > > > > Received: (datagram, server, /172.29.100.104:5678 =>
> > > > /0.0.0.0:1234),
> > > > > > > HeapBuffer[pos=0 lim=3 cap=2048: 00 00 00]
> > > > > > > Received: (datagram, server, /172.29.100.104:5678 =>
> > > > /0.0.0.0:1234),
> > > > > > > HeapBuffer[pos=0 lim=3 cap=2048: 00 00 00]
> > > > > > > Received: (datagram, server, /172.29.100.104:5678 =>
> > > > /0.0.0.0:1234),
> > > > > > > HeapBuffer[pos=0 lim=3 cap=2048: 00 00 00]
> > > > > > > Received: (datagram, server, /172.29.100.104:5678 =>
> > > > /0.0.0.0:1234),
> > > > > > > HeapBuffer[pos=0 lim=3 cap=2048: 00 00 00]
> > > > > > > Received: (datagram, server, /172.29.100.104:5678 =>
> > > > /0.0.0.0:1234),
> > > > > > > HeapBuffer[pos=0 lim=4 cap=2048: 00 00 00 00]
> > > > > > > Received: (datagram, server, /172.29.100.104:5678 =>
> > > > /0.0.0.0:1234),
> > > > > > > HeapBuffer[pos=0 lim=4 cap=2048: 00 00 00 00]
> > > > > > > Received: (datagram, server, /172.29.100.104:5678 =>
> > > > /0.0.0.0:1234),
> > > > > > > HeapBuffer[pos=0 lim=4 cap=2048: 00 00 00 00]
> > > > > > > Received: (datagram, server, /172.29.100.104:5678 =>
> > > > /0.0.0.0:1234),
> > > > > > > HeapBuffer[pos=0 lim=4 cap=2048: 00 00 00 00]
> > > > > > > Closed: (datagram, server, /172.29.100.104:5678 =>
> /0.0.0.0:1234)
> > > > > > > unbound
> > > > > > >
> > > > > > > I changed the code a little bit, to be able to distinguish the
> > > > messages.
> > > > > > >
> > > > > > > Also added a sleep before the unbind, (I think there's one
> line
> > > > missing
> > > > > > > in your output :-)
> > > > > > >
> > > > > > >        f1.getSession().write(ByteBuffer.allocate (1)).await();
> > > > > > >        f1.getSession().write( ByteBuffer.allocate(2)).await();
> > > > > > >
> > > > > > >        f2.getSession().write(ByteBuffer.allocate(3)).await();
> > > > > > >        f2.getSession ().write(ByteBuffer.allocate(4)).await();
> > > > > > >
> > > > > > >        Thread.sleep(2000);
> > > > > > >        acceptor.unbind();
> > > > > > >        System.out.println ("unbound");
> > > > > > >         System.exit(0);
> > > > > > >
> > > > > > > The messages sent to the broadcast address are received
> multiple
> > > > times:
> > > > > > > twice per enabled network connection.
> > > > > > > When I enable all 4 network interfaces (LAN, wireless LAN and
> two
> > > > > > > virtual ones for VMWare) I receive them 8 times !
> > > > > > >
> > > > > > > Maarten
> > > > > > >
> > > > > > > On 9/17/07, Trustin Lee < trustin@gmail.com > wrote:
> > > > > > > >
> > > > > > > > Hi,
> > > > > > > >
> > > > > > > > I made a lot of changes to the current datagram
> implementation
> > > > in
> > > > > > > > trunk.  DatagramAcceptor now collaborates with
> DatagramConnector
> > > > to
> > > > > > > > create connected datagram socket which listens to the remote
> > > > address
> > > > > > > > of the received packet.  The following is simplified
> description
> > > > of
> > > > > > > > flow:
> > > > > > > >
> > > > > > > > * DatagramAcceptor's underlying DatagramChannel.receive is
> > > > invoked
> > > > > > > > * Once data is received, new connected datagram session is
> > > > created
> > > > > > > > using DatagramConnector.connect (receivedRemoteAddress,
> > > > > > > > acceptor.getLocalAddress()).  If there's already a session
> > > > instance
> > > > > > > > associated with the remote address, it's reused.
> > > > > > > >
> > > > > > > > The advantages of this implementation are:
> > > > > > > >
> > > > > > > > * The acceptor-side datagram sessions can perform much
> better in
> > > > > > > > multi-core environment.
> > > > > > > > * There's no need for IoSessionRecycler on the acceptor-side
> > > > anymore.
> > > > > > > > You have full control over disconnection; probably using
> > > > sessionIdle
> > > > > > > > event in most cases.
> > > > > > > > * Code duplication can be reduced once again, and most part
> of
> > > > the
> > > > > > > > existing acceptor code can be extracted into a generic
> acceptor
> > > > > > > > implementation.
> > > > > > > >
> > > > > > > > The disadvantage is that it forces you to set reuseAddress
> to
> > > > true,
> > > > > > > > because multiple datagram channels are bound to the same
> local
> > > > > > > > address.
> > > > > > > >
> > > > > > > > In Linux, connected datagram channels have priority over
> > > > unconnected
> > > > > > > > channels, so most traffic will go directly into
> > > > DatagramConnector's
> > > > > > > > NIOProcessors.  The only exception I've found is broadcast
> > > > packets. It
> > > > > > > > is always received from the unconnected channel in
> > > > DatagramAcceptor.
> > > > > > > > DatagramAcceptor immediately forwards the event to an
> > > > appropriate
> > > > > > > > session that DatagramConnector is managing, or creates a new
> > > > session
> > > > > > > > using connect().
> > > > > > > >
> > > > > > > > I think this behavior won't have any big differences among
> > > > different
> > > > > > > > platforms (e.g. Windows and SUNOS).  As long as multiple
> > > > datagram
> > > > > > > > channels can be bound to the same local address, this
> > > > implementation
> > > > > > > > should work fine.  To make this sure, please run the
> following
> > > > test
> > > > > > > > code in your machine, and let me know what the result is:
> > > > > > > >
> > > > > > > > -------- CODE BEGINS --------
> > > > > > > > package net.gleamynode.tmp;
> > > > > > > >
> > > > > > > > import java.net.InetAddress;
> > > > > > > > import java.net.InetSocketAddress;
> > > > > > > >
> > > > > > > > import org.apache.mina.common.ByteBuffer;
> > > > > > > > import org.apache.mina.common.ConnectFuture;
> > > > > > > > import org.apache.mina.common.IoHandlerAdapter ;
> > > > > > > > import org.apache.mina.common.IoSession;
> > > > > > > > import org.apache.mina.transport.socket.nio.DatagramAcceptor
> ;
> > > > > > > > import
> org.apache.mina.transport.socket.nio.DatagramConnector ;
> > > > > > > >
> > > > > > > > public class Main {
> > > > > > > >
> > > > > > > >     private static final int SERVER_PORT = 1234;
> > > > > > > >     private static final int CLIENT_PORT = 5678;
> > > > > > > >
> > > > > > > >     public static void main(String args[]) throws Exception
> {
> > > > > > > >         DatagramAcceptor acceptor = new DatagramAcceptor();
> > > > > > > >         acceptor.setLocalAddress (new
> > > > InetSocketAddress(SERVER_PORT));
> > > > > > > >
> > > > > > > >         acceptor.setHandler(new IoHandlerAdapter() {
> > > > > > > >             @Override
> > > > > > > >             public void sessionOpened(IoSession session) {
> > > > > > > >                 System.out.println("Open: " + session);
> > > > > > > >             }
> > > > > > > >
> > > > > > > >             @Override
> > > > > > > >             public void sessionClosed(IoSession session) {
> > > > > > > >                 System.out.println("Closed: " + session);
> > > > > > > >             }
> > > > > > > >
> > > > > > > >             @Override
> > > > > > > >             public void messageReceived(IoSession session,
> > > > Object o) {
> > > > > > > >
> > > > > > > >                 System.out.println("Received: " + session +
> ", "
> > > > + o);
> > > > > > > >             }
> > > > > > > >         });
> > > > > > > >         acceptor.bind();
> > > > > > > >
> > > > > > > >         DatagramConnector connector = new
> DatagramConnector();
> > > > > > > >         connector.getSessionConfig().setReuseAddress(true);
> > > > > > > >         connector.setHandler(new IoHandlerAdapter() {
> > > > > > > >             @Override
> > > > > > > >             public void messageReceived(IoSession session,
> > > > Object o) {
> > > > > > > >                 System.out.println("ERR?");
> > > > > > > >             }
> > > > > > > >         });
> > > > > > > >
> > > > > > > >         // Print the local host.
> > > > > > > >         System.out.println ("Local host: " +
> > > > InetAddress.getLocalHost
> > > > > > > > ());
> > > > > > > >
> > > > > > > >         // Try point-to-point.
> > > > > > > >         ConnectFuture f1 = connector.connect (
> > > > > > > >                 new InetSocketAddress(
> > > > > > > >                         InetAddress.getLocalHost(),
> > > > SERVER_PORT),
> > > > > > > >                 new InetSocketAddress(
> > > > > > > >                           InetAddress.getLocalHost(),
> > > > CLIENT_PORT));
> > > > > > > >         f1.await();
> > > > > > > >
> > > > > > > >
> > > > > > > >         f1.getSession().write(ByteBuffer.allocate
> (1)).await();
> > > > > > > >         f1.getSession().write(ByteBuffer.allocate
> (1)).await();
> > > > > > > >
> > > > > > > >
> > > > > > > >         // Try broadcast.
> > > > > > > >         ConnectFuture f2 = connector.connect(
> > > > > > > >                 new InetSocketAddress(
> > > > > > > >                         " 255.255.255.255", SERVER_PORT),
> > > > > > > >                 new InetSocketAddress(
> > > > > > > >                         InetAddress.getLocalHost(),
> > > > CLIENT_PORT));
> > > > > > > >
> > > > > > > >         f2.await();
> > > > > > > >         f2.getSession().write(ByteBuffer.allocate(1)).await();
> > > > > > > >         f2.getSession().write(ByteBuffer.allocate
> (1)).await();
> > > > > > > >
> > > > > > > >         acceptor.unbind();
> > > > > > > >
> > > > > > > >         System.exit(0);
> > > > > > > >     }
> > > > > > > > }
> > > > > > > > -------- CODE ENDS --------
> > > > > > > >
> > > > > > > > The expected result is:
> > > > > > > >
> > > > > > > > -------- RESULT BEGINS --------
> > > > > > > > Local host: primary/127.0.0.1
> > > > > > > > Open: (datagram, server, /127.0.0.1:5678 =>
> > > > /0:0:0:0:0:0:0:0:1234)
> > > > > > > > Received: (datagram, server, /127.0.0.1:5678 =>
> > > > > > > > /0:0:0:0:0:0:0:0:1234), HeapBuffer[pos=0 lim=1 cap=2048: 00]
> > > > > > > > Received: (datagram, server, /127.0.0.1:5678 =>
> > > > > > > > /0:0:0:0:0:0:0:0:1234), HeapBuffer[pos=0 lim=1 cap=2048: 00]
> > > > > > > > Received: (datagram, server, /127.0.0.1:5678 =>
> > > > > > > > /0:0:0:0:0:0:0:0:1234), HeapBuffer[pos=0 lim=1 cap=2048: 00]
> > > > > > > > Closed: (datagram, server, /127.0.0.1:5678 =>
> > > > /0:0:0:0:0:0:0:0:1234)
> > > > > > > > -------- RESULT ENDS --------
> > > > > > > >
> > > > > > > > If this test fails on any platform that runs Java 5, I am
> doomed
> > > > to
> > > > > > > > revert my changes. :)
> > > > > > > >
> > > > > > > > Trustin
> > > > > > > > --
> > > > > > > > what we call human nature is actually human habit
> > > > > > > > --
> > > > > > > > http://gleamynode.net/
> > > > > > > > --
> > > > > > > > PGP Key ID: 0x0255ECA6
> > > > > > > >
> > > > > > >
> > > > > > >
> > > > > >
> > > > >
> > > >
> > > >
> > > > --
> > > > what we call human nature is actually human habit
> > > > --
> > > > http://gleamynode.net/
> > > > --
> > > > PGP Key ID: 0x0255ECA6
> > > >
> > >
> > >
> >
>
>
> --
> what we call human nature is actually human habit
> --
> http://gleamynode.net/
> --
> PGP Key ID: 0x0255ECA6
>

Re: Request for a test on various platforms:

Posted by Trustin Lee <tr...@gmail.com>.
According to one of my colleagues, it's not broken but the behavior is
just undefined.  So, reverted my work. :-(

Trustin

On 9/19/07, Trustin Lee <tr...@gmail.com> wrote:
> On 9/19/07, Trustin Lee <tr...@gmail.com> wrote:
> > What we've found so far:
> >
> > 1) Non-broadcast packets are working fine.
>
> I found an interesting behavior (probably JVM or Windows bug).  It
> seems like it is who calls receive() or read() first that receives
> non-broadcast packets.  It doesn't mean any socket can receive
> non-broadcast packets but means only the *first* socket who called
> receive() or read() will receive non-broadcast packets.
>
> Therefore, the DatagramAcceptor thread is the only thread that
> receives non-broadcast packets, and this is inefficient, though we can
> live with it.
>
> The worst thing is that we can't receive any packets if someone
> created a connected socket on the same local port with different
> remote port.  Please try the following datagram server:
>
> -------- CODE BEGINS --------
> import java.io.InterruptedIOException;
> import java.net.DatagramPacket;
> import java.net.DatagramSocket;
> import java.net.InetAddress;
> import java.net.InetSocketAddress;
>
> public class DatagramServer {
>     private static final int SERVER_PORT = 1234;
>
>     private static final int CLIENT_PORT = 5678;
>
>     public static void main(String[] args) throws Exception {
>         DatagramSocket cs2 = new DatagramSocket(null);
>         cs2.setReuseAddress(true);
>         cs2.setSoTimeout(100);
>         cs2.bind(new InetSocketAddress(SERVER_PORT));
>         cs2.connect(new InetSocketAddress(InetAddress.getLocalHost(),
>                 CLIENT_PORT + 1));
>
>         DatagramSocket us1 = new DatagramSocket(null);
>         us1.setReuseAddress(true);
>         us1.setSoTimeout(100);
>         us1.bind(new InetSocketAddress(SERVER_PORT));
>
>         DatagramSocket cs1 = new DatagramSocket(null);
>         cs1.setReuseAddress(true);
>         cs1.setSoTimeout(100);
>         cs1.bind(new InetSocketAddress(SERVER_PORT));
>         cs1.connect(new InetSocketAddress(InetAddress.getLocalHost(),
>                 CLIENT_PORT));
>
>         DatagramPacket p = new DatagramPacket(new byte[2048], 2048);
>         for (;;) {
>             try {
>                 cs1.receive(p);
>                 System.out.println("CS1: " + p.getSocketAddress() + ", "
>                         + p.getLength());
>             } catch (InterruptedIOException e) {
>             }
>             try {
>                 cs2.receive(p);
>                 System.out.println("CS2: " + p.getSocketAddress() + ", "
>                         + p.getLength());
>             } catch (InterruptedIOException e) {
>             }
>             try {
>                 us1.receive(p);
>                 System.out.println("US1: " + p.getSocketAddress() + ", "
>                         + p.getLength());
>             } catch (InterruptedIOException e) {
>             }
>         }
>     }
> }
> -------- CODE ENDS --------
>
> As you see, cs2 is created in prior to the other sockets.  The result
> of the test looks like the following:
>
> -------- RESULT BEGINS --------
> US1: /192.168.0.3:5678, 3
>
> CS1: /192.168.0.3:5678, 3
>
> US1: /192.168.0.3:5678, 4
>
> CS1: /192.168.0.3:5678, 4
>
> -------- RESULT ENDS --------
>
> Packet 1 and 2 are missing. :(
>
> I also modified Main.java to send some packets to (CLIENT_PORT + 1) to
> make sure CS2 is swallowing others' packets, and I got the following
> result (Packets are sent 6 times, and packet #5 and 6 are broadcast
> packets):
>
> -------- RESULT BEGINS --------
> CS2: /192.168.0.3:5679, 3
>
> US1: /192.168.0.3:5678, 5
>
> CS1: /192.168.0.3:5678, 5
>
> CS2: /192.168.0.3:5679, 4
>
> US1: /192.168.0.3:5678, 6
>
> CS1: /192.168.0.3:5678, 6
>
> -------- RESULT ENDS --------
>
> In contrast, I got the following in Linux:
>
> -------- RESULT BEGINS --------
> CS1: /127.0.0.1:5678, 1
> CS2: /127.0.0.1:5679, 3
> CS1: /127.0.0.1:5678, 2
> CS2: /127.0.0.1:5679, 4
> US1: /127.0.0.1:5678, 5
> US1: /127.0.0.1:5678, 6
> -------- RESULT ENDS --------
>
> IIUC, the test results we got means that the UDP/IP implementation of
> Windows or Windows JVM is broken.  Did I guess correctly, or am I
> missing something?
>
> Even if it's a bug or not, it seems like the new datagram
> implementation works OK with various operating systems with some
> compromises.  I believe performance will improve definitely in Linux
> and Solaris thanks to multi-thread support.
>
> Trustin
> --
> what we call human nature is actually human habit
> --
> http://gleamynode.net/
> --
> PGP Key ID: 0x0255ECA6
>


-- 
what we call human nature is actually human habit
--
http://gleamynode.net/
--
PGP Key ID: 0x0255ECA6

Re: Request for a test on various platforms:

Posted by Trustin Lee <tr...@gmail.com>.
On 9/19/07, Trustin Lee <tr...@gmail.com> wrote:
> What we've found so far:
>
> 1) Non-broadcast packets are working fine.

I found an interesting behavior (probably JVM or Windows bug).  It
seems like it is who calls receive() or read() first that receives
non-broadcast packets.  It doesn't mean any socket can receive
non-broadcast packets but means only the *first* socket who called
receive() or read() will receive non-broadcast packets.

Therefore, the DatagramAcceptor thread is the only thread that
receives non-broadcast packets, and this is inefficient, though we can
live with it.

The worst thing is that we can't receive any packets if someone
created a connected socket on the same local port with different
remote port.  Please try the following datagram server:

-------- CODE BEGINS --------
import java.io.InterruptedIOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.InetSocketAddress;

public class DatagramServer {
    private static final int SERVER_PORT = 1234;

    private static final int CLIENT_PORT = 5678;

    public static void main(String[] args) throws Exception {
        DatagramSocket cs2 = new DatagramSocket(null);
        cs2.setReuseAddress(true);
        cs2.setSoTimeout(100);
        cs2.bind(new InetSocketAddress(SERVER_PORT));
        cs2.connect(new InetSocketAddress(InetAddress.getLocalHost(),
                CLIENT_PORT + 1));

        DatagramSocket us1 = new DatagramSocket(null);
        us1.setReuseAddress(true);
        us1.setSoTimeout(100);
        us1.bind(new InetSocketAddress(SERVER_PORT));

        DatagramSocket cs1 = new DatagramSocket(null);
        cs1.setReuseAddress(true);
        cs1.setSoTimeout(100);
        cs1.bind(new InetSocketAddress(SERVER_PORT));
        cs1.connect(new InetSocketAddress(InetAddress.getLocalHost(),
                CLIENT_PORT));

        DatagramPacket p = new DatagramPacket(new byte[2048], 2048);
        for (;;) {
            try {
                cs1.receive(p);
                System.out.println("CS1: " + p.getSocketAddress() + ", "
                        + p.getLength());
            } catch (InterruptedIOException e) {
            }
            try {
                cs2.receive(p);
                System.out.println("CS2: " + p.getSocketAddress() + ", "
                        + p.getLength());
            } catch (InterruptedIOException e) {
            }
            try {
                us1.receive(p);
                System.out.println("US1: " + p.getSocketAddress() + ", "
                        + p.getLength());
            } catch (InterruptedIOException e) {
            }
        }
    }
}
-------- CODE ENDS --------

As you see, cs2 is created in prior to the other sockets.  The result
of the test looks like the following:

-------- RESULT BEGINS --------
US1: /192.168.0.3:5678, 3

CS1: /192.168.0.3:5678, 3

US1: /192.168.0.3:5678, 4

CS1: /192.168.0.3:5678, 4

-------- RESULT ENDS --------

Packet 1 and 2 are missing. :(

I also modified Main.java to send some packets to (CLIENT_PORT + 1) to
make sure CS2 is swallowing others' packets, and I got the following
result (Packets are sent 6 times, and packet #5 and 6 are broadcast
packets):

-------- RESULT BEGINS --------
CS2: /192.168.0.3:5679, 3

US1: /192.168.0.3:5678, 5

CS1: /192.168.0.3:5678, 5

CS2: /192.168.0.3:5679, 4

US1: /192.168.0.3:5678, 6

CS1: /192.168.0.3:5678, 6

-------- RESULT ENDS --------

In contrast, I got the following in Linux:

-------- RESULT BEGINS --------
CS1: /127.0.0.1:5678, 1
CS2: /127.0.0.1:5679, 3
CS1: /127.0.0.1:5678, 2
CS2: /127.0.0.1:5679, 4
US1: /127.0.0.1:5678, 5
US1: /127.0.0.1:5678, 6
-------- RESULT ENDS --------

IIUC, the test results we got means that the UDP/IP implementation of
Windows or Windows JVM is broken.  Did I guess correctly, or am I
missing something?

Even if it's a bug or not, it seems like the new datagram
implementation works OK with various operating systems with some
compromises.  I believe performance will improve definitely in Linux
and Solaris thanks to multi-thread support.

Trustin
-- 
what we call human nature is actually human habit
--
http://gleamynode.net/
--
PGP Key ID: 0x0255ECA6

Re: Request for a test on various platforms:

Posted by Trustin Lee <tr...@gmail.com>.
What we've found so far:

1) Non-broadcast packets are working fine.
1) It is a normal behavior that multiple duplicate broadcast packets
are received in a multi-homed system.
2) Windows sends the received broadcast packet to the unconnected
socket, too (i.e.  both to the connected and the unconnected) while
other platforms don't.

I think the case 1 is fine because a network application developer
should consider a multi-homed system, so he or she should program the
application properly (e.g. ignoring the duplicate requests).

The case 2 is suspected to be specific to Windows.  I think it's
probably OK because the user needs to take care of the case 1, but it
would be much better if we can reduce the number of events fired.

WDYT?

Trustin

On 9/19/07, Maarten Bosteels <mb...@gmail.com> wrote:
> On Linux:
> /172.30.6.12:5678, 1
> /172.30.6.12:5678, 2
> /172.30.6.12:5678, 3
> /172.30.6.12:5678, 4
>
> Notice that the linux box has only 1 physical network card (and one virtual
> interface)
>
> eth0      Link encap:Ethernet  HWaddr 00:11:43:2D:3C:29
>           inet addr:172.30.6.12  Bcast:172.30.255.255  Mask:255.255.0.0
>           inet6 addr: fe80::211:43ff:fe2d:3c29/64 Scope:Link
>           UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
>           RX packets:5213648 errors:0 dropped:0 overruns:0 frame:0
>           TX packets:3913571 errors:0 dropped:0 overruns:0 carrier:0
>           collisions:0 txqueuelen:100
>           RX bytes:2836668837 (2.6 GiB)  TX bytes:1058082225 (1009.0 MiB)
>           Base address:0xdcc0 Memory:dfee0000-dff00000
>
> eth0:0    Link encap:Ethernet  HWaddr 00:11:43:2D:3C:29
>           inet addr:172.30.6.16  Bcast:172.30.255.255  Mask:255.255.0.0
>           UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
>           Base address:0xdcc0 Memory:dfee0000-dff00000
>
> lo        Link encap:Local Loopback
>           inet addr:127.0.0.1  Mask:255.0.0.0
>           inet6 addr: ::1/128 Scope:Host
>           UP LOOPBACK RUNNING  MTU:16436  Metric:1
>           RX packets:2849256 errors:0 dropped:0 overruns:0 frame:0
>           TX packets:2849256 errors:0 dropped:0 overruns:0 carrier:0
>           collisions:0 txqueuelen:0
>           RX bytes:645905386 (615.9 MiB)  TX bytes:645905386 (615.9 MiB)
>
>
> On Windows with one network connection enabled:
> /172.30.6.13:5678, 1
> /172.30.6.13:5678, 2
> /172.30.6.13:5678, 3
> /172.30.6.13:5678, 4
>
> On Windows with 2 network connections enabled:  (notice that source ip
> changed: 172.29.100.104 is the WLAN nic)
> /172.29.100.104:5678, 1
> /172.29.100.104:5678, 2
> /172.29.100.104:5678, 3
> /172.29.100.104:5678, 3
> /172.29.100.104:5678, 4
> /172.29.100.104:5678, 4
>
> On Windows with 3 network connections enabled:
>
> /172.29.100.104:5678, 1
> /172.29.100.104:5678, 2
> /172.29.100.104:5678, 3
> /172.29.100.104:5678, 3
> /172.29.100.104:5678, 3
> /172.29.100.104:5678, 4
> /172.29.100.104:5678, 4
> /172.29.100.104:5678, 4
>
> On Windows with 4 network connections enabled:
>
> /172.29.100.104:5678, 1
> /172.29.100.104:5678, 2
> /172.29.100.104:5678, 3
> /172.29.100.104:5678, 3
> /172.29.100.104:5678, 3
> /172.29.100.104:5678, 3
> /172.29.100.104:5678, 4
> /172.29.100.104:5678, 4
> /172.29.100.104:5678, 4
> /172.29.100.104:5678, 4
>
> On Solaris, with one nic:
>
> /172.30.0.139:5678, 1
> /172.30.0.139:5678, 2
> /172.30.0.139:5678, 3
> /172.30.0.139:5678, 4
>
> On the Solaris box with multiple interfaces
>
> /10.0.0.120:56787, 1
> /10.0.0.120:56787, 2
> /10.0.0.120:56787, 3
> /10.0.0.120:56787, 3
> /10.0.0.120:56787, 4
> /10.0.0.120:56787, 4
>
> lo0: flags=2001000849<UP,LOOPBACK,RUNNING,MULTICAST,IPv4,VIRTUAL> mtu 8232
> index 1
>         inet 127.0.0.1 netmask ff000000
> ce0: flags=1000843<UP,BROADCAST,RUNNING,MULTICAST,IPv4> mtu 1500 index 2
>         inet 192.168.113.8 netmask ffffff00 broadcast 192.168.113.255
>         ether 0:14:4f:17:d:de
> ce1: flags=1000802<BROADCAST,MULTICAST,IPv4> mtu 1500 index 3
>         inet 0.0.0.0 netmask 0
>         ether 0:14:4f:17:d:df
> ce2: flags=1000802<BROADCAST,MULTICAST,IPv4> mtu 1500 index 4
>         inet 0.0.0.0 netmask 0
>         ether 0:14:4f:17:d:e0
> eri0: flags=1000843<UP,BROADCAST,RUNNING,MULTICAST,IPv4> mtu 1500 index 5
>         inet 10.0.0.120 netmask ffffff00 broadcast 10.0.0.255
>         ether 0:3:ba:b0:49:65
> eri0:1: flags=1040843<UP,BROADCAST,RUNNING,MULTICAST,DEPRECATED,IPv4> mtu
> 1500 index 5
>         inet 10.0.0.130 netmask ffffff00 broadcast 10.0.0.255
>
> This is what W. Richard Stevens has to say about the "limited boadcast
> address"
> [quote]
> An unanswered question is: if a host is multihomed and a process sends a
> datagram to the limited broadcast address, should the datagram be sent out
> each connected interface that supports broadcasting ?
> If not, an application that wants to broadcast out all interfaces must
> determine all the interfaces on the host that support broadcasting, and send
> a copy out each interface. Most BSD systems treat 255.255.255.255 as an
> alias for the broadcast address of the first interface that was configured,
> and don't provide any way to send a datagram out all attached,
> broadcast-capable interfaces.
> [end of quote]
>
> http://www.goldfish.org/books/TCPIP%20Illustrated%20Vol%201/broadcas.htm
>
> Maarten
>
> On 9/18/07, Trustin Lee <tr...@gmail.com> wrote:
> >
> > I think we also need to check how our previous implementation works
> > with the test code.
> >
> > Maarten, could you run the test again on Windows and SunOS with the
> > plain blocking I/O server instead of DatagramAcceptor?
> >
> > -------- CODE BEGINS --------
> > package net.gleamynode.tmp;
> >
> > import java.net.DatagramPacket;
> > import java.net.DatagramSocket;
> > import java.net.InetSocketAddress;
> >
> > public class DatagramServer {
> >     private static final int SERVER_PORT = 1234;
> >
> >     public static void main(String[] args) throws Exception {
> >         DatagramSocket s = new DatagramSocket(new
> > InetSocketAddress(SERVER_PORT));
> >
> >         DatagramPacket p = new DatagramPacket(new byte[2048], 2048);
> >         for (;;) {
> >             s.receive(p);
> >             System.out.println("" + p.getSocketAddress() + ", " +
> > p.getLength());
> >         }
> >     }
> > }
> > -------- CODE ENDS --------
> >
> > The expected output is:
> >
> > /127.0.0.1:5678, 1
> > /127.0.0.1:5678, 2
> > /127.0.0.1:5678, 3
> > /127.0.0.1:5678, 4
> >
> > You will need to comment out 'acceptor.bind();' to run the test.
> >
> > Thanks in advance,
> > Trustin
> >
> > On 9/18/07, Trustin Lee <tr...@gmail.com> wrote:
> > > It seems like each broadcast packet is broadcasted as many times as
> > > the number of network interface cards in Windows and SunOS.  It's
> > > interesting that Linux doesn't.  Maarten, did I understand correctly?
> > >
> > > I'd like to find a way to suppress the duplicate event emission, but
> > > don't have any idea yet.
> > >
> > > Thanks,
> > > Trustin
> > >
> > > On 9/18/07, Maarten Bosteels <mb...@gmail.com> wrote:
> > > > Also tested it on a Solaris box  with just one network interface:
> > > >
> > > > [root@mercury tmp]$ ifconfig -a
> > > > lo0: flags=2001000849<UP,LOOPBACK,RUNNING,MULTICAST,IPv4,VIRTUAL> mtu
> > 8232
> > > > index 1
> > > >         inet 127.0.0.1 netmask ff000000
> > > > hme0: flags=1000843<UP,BROADCAST,RUNNING,MULTICAST,IPv4> mtu 1500
> > index 2
> > > >         inet 172.30.0.139 netmask ffff0000 broadcast 172.30.255.255
> > > >         ether 8:0:20:e6:85:18
> > > > [root@mercury tmp]$
> > > > [root@mercury tmp]$ uname -a
> > > > SunOS mercury 5.10 Generic_118833-24 sun4u sparc SUNW,Ultra-250
> > > > [root@mercury tmp]$
> > > > [root@mercury tmp]$ java -cp mina-core-2.0.0-M1-SNAPSHOT.jar:.
> > TestTrustin
> > > > Local host: mercury/172.30.0.139
> > > > Open: (datagram, server, /172.30.0.139:5678 => /0.0.0.0:1234)
> > > > Received: (datagram, server, /172.30.0.139:5678 => /0.0.0.0:1234),
> > > > HeapBuffer[pos=0 lim=1 cap=2048: 00]
> > > > Received: (datagram, server, /172.30.0.139:5678 => /0.0.0.0:1234),
> > > > HeapBuffer[pos=0 lim=2 cap=2048: 00 00]
> > > > Received: (datagram, server, /172.30.0.139:5678 => /0.0.0.0:1234),
> > > > HeapBuffer[pos=0 lim=3 cap=2048: 00 00 00]
> > > > Received: (datagram, server, /172.30.0.139:5678 => /0.0.0.0:1234),
> > > > HeapBuffer[pos=0 lim=4 cap=2048: 00 00 00 00]
> > > > unbound
> > > > Closed: (datagram, server, /172.30.0.139:5678 => /0.0.0.0:1234)
> > > > [root@mercury tmp]$
> > > >
> > > > Maarten
> > > >
> > > > On 9/18/07, Maarten Bosteels <mb...@gmail.com> wrote:
> > > > >
> > > > > On 9/18/07, Trustin Lee < trustin@gmail.com> wrote:
> > > > > >
> > > > > > How many network devices exist in SunOS?
> > > > >
> > > > >
> > > > >
> > > > > root@mysun # ifconfig -a
> > > > > lo0: flags=2001000849<UP,LOOPBACK,RUNNING,MULTICAST,IPv4,VIRTUAL>
> > mtu 8232
> > > > > index 1
> > > > >         inet 127.0.0.1 netmask ff000000
> > > > > ce0: flags=1000843<UP,BROADCAST,RUNNING,MULTICAST,IPv4> mtu 1500
> > index 2
> > > > >         inet 192.168.113.8 netmask ffffff00 broadcast
> > 192.168.113.255
> > > > >         ether 0:14:4f:17:d:de
> > > > > ce1: flags=1000802<BROADCAST,MULTICAST,IPv4> mtu 1500 index 3
> > > > >         inet 0.0.0.0 netmask 0
> > > > >         ether 0:14:4f:17:d:df
> > > > > ce2: flags=1000802<BROADCAST,MULTICAST,IPv4> mtu 1500 index 4
> > > > >         inet 0.0.0.0 netmask 0
> > > > >         ether 0:14:4f:17:d:e0
> > > > > eri0: flags=1000843<UP,BROADCAST,RUNNING,MULTICAST,IPv4> mtu 1500
> > index 5
> > > > >         inet 10.0.0.120 netmask ffffff00 broadcast 10.0.0.255
> > > > >         ether 0:3:ba:b0:49:65
> > > > > eri0:1:
> > flags=1040843<UP,BROADCAST,RUNNING,MULTICAST,DEPRECATED,IPv4> mtu
> > > > > 1500 index 5
> > > > >         inet 10.0.0.130 netmask ffffff00 broadcast 10.0.0.255
> > > > >
> > > > > Maarten
> > > > >
> > > > > Thanks!
> > > > > > Trustin
> > > > > >
> > > > > > On 9/18/07, Maarten Bosteels < mbosteels.dns@gmail.com> wrote:
> > > > > > > On SunOS 5.10  sun4u sparc SUNW,Sun-Fire-V890
> > > > > > >
> > > > > > > java version " 1.5.0_01"
> > > > > > > Java(TM) 2 Runtime Environment, Standard Edition (build
> > 1.5.0_01-b08)
> > > > > > > Java HotSpot(TM) Server VM (build 1.5.0_01-b08, mixed mode)
> > > > > > >
> > > > > > > Open: (datagram, server, /10.0.0.120:5678 => /0.0.0.0:1234)
> > > > > > > Received: (datagram, server, /10.0.0.120:5678 => /0.0.0.0:1234),
> > > > > > > HeapBuffer[pos=0 lim=1 cap=2048: 00]
> > > > > > > Received: (datagram, server, /10.0.0.120:5678 => /0.0.0.0:1234),
> >
> > > > > > > HeapBuffer[pos=0 lim=2 cap=2048: 00 00]
> > > > > > > Received: (datagram, server, /10.0.0.120:5678 => /0.0.0.0:1234),
> > > > > > > HeapBuffer[pos=0 lim=3 cap=2048: 00 00 00]
> > > > > > > Received: (datagram, server, /10.0.0.120:5678 => /0.0.0.0:1234),
> > > > > > > HeapBuffer[pos=0 lim=3 cap=2048: 00 00 00]
> > > > > > > Received: (datagram, server, /10.0.0.120:5678 => /0.0.0.0:1234),
> >
> > > > > > > HeapBuffer[pos=0 lim=4 cap=2048: 00 00 00 00]
> > > > > > > Received: (datagram, server, /10.0.0.120:5678 => /0.0.0.0:1234),
> > > > > > > HeapBuffer[pos=0 lim=4 cap=2048: 00 00 00 00]
> > > > > > > unbound
> > > > > > > Closed: (datagram, server, /10.0.0.120:5678 => /0.0.0.0:1234)
> > > > > > >
> > > > > > > Maarten
> > > > > > >
> > > > > > > On 9/18/07, Maarten Bosteels <mbosteels.dns@gmail.com > wrote:
> > > > > > > >
> > > > > > > > On linux 2.6.9 , jdk 1.6
> > > > > > > >
> > > > > > > > Local host: mortimer/172.30.6.12
> > > > > > > > Open: (datagram, server, /172.30.6.12:5678 =>
> > /0:0:0:0:0:0:0:0:1234)
> > > > > > > > Received: (datagram, server, /172.30.6.12:5678 =>
> > > > > > /0:0:0:0:0:0:0:0:1234),
> > > > > > > > HeapBuffer[pos=0 lim=1 cap=2048: 00]
> > > > > > > > Received: (datagram, server, /172.30.6.12:5678 =>
> > > > > > /0:0:0:0:0:0:0:0:1234),
> > > > > > > > HeapBuffer[pos=0 lim=2 cap=2048: 00 00]
> > > > > > > > Received: (datagram, server, /172.30.6.12:5678 =>
> > > > > > /0:0:0:0:0:0:0:0:1234),
> > > > > > > > HeapBuffer[pos=0 lim=3 cap=2048: 00 00 00]
> > > > > > > > Received: (datagram, server, /172.30.6.12:5678 =>
> > > > > > /0:0:0:0:0:0:0:0:1234),
> > > > > > > > HeapBuffer[pos=0 lim=4 cap=2048: 00 00 00 00]
> > > > > > > > unbound
> > > > > > > > Closed: (datagram, server, /172.30.6.12:5678 =>
> > > > > > /0:0:0:0:0:0:0:0:1234)
> > > > > > > >
> > > > > > > > Adding a virtual interface (eth0:0) doesn't make a difference.
> >
> > > > > > > > Maarten
> > > > > > > >
> > > > > > > > On 9/18/07, Maarten Bosteels < mbosteels.dns@gmail.com> wrote:
> >
> > > > > > > > >
> > > > > > > > > Hello Trustin,
> > > > > > > > >
> > > > > > > > > I ran the code on Windows XP jdk 1.6 , and this is the
> > output I
> > > > > > got:
> > > > > > > > >
> > > > > > > > > Local host: kweenie/172.29.100.104
> > > > > > > > > Open: (datagram, server, /172.29.100.104:5678 =>
> > /0.0.0.0:1234)
> > > > > > > > > Received: (datagram, server, /172.29.100.104:5678 =>
> > > > > > /0.0.0.0:1234),
> > > > > > > > > HeapBuffer[pos=0 lim=2 cap=2048: 00 00]
> > > > > > > > > Received: (datagram, server, /172.29.100.104:5678 =>
> > > > > > /0.0.0.0:1234),
> > > > > > > > > HeapBuffer[pos=0 lim=1 cap=2048: 00]
> > > > > > > > > Received: (datagram, server, /172.29.100.104:5678 =>
> > > > > > /0.0.0.0:1234),
> > > > > > > > > HeapBuffer[pos=0 lim=3 cap=2048: 00 00 00]
> > > > > > > > > Received: (datagram, server, /172.29.100.104:5678 =>
> > > > > > /0.0.0.0:1234),
> > > > > > > > > HeapBuffer[pos=0 lim=3 cap=2048: 00 00 00]
> > > > > > > > > Received: (datagram, server, /172.29.100.104:5678 =>
> > > > > > /0.0.0.0:1234),
> > > > > > > > > HeapBuffer[pos=0 lim=3 cap=2048: 00 00 00]
> > > > > > > > > Received: (datagram, server, /172.29.100.104:5678 =>
> > > > > > /0.0.0.0:1234),
> > > > > > > > > HeapBuffer[pos=0 lim=3 cap=2048: 00 00 00]
> > > > > > > > > Received: (datagram, server, /172.29.100.104:5678 =>
> > > > > > /0.0.0.0:1234),
> > > > > > > > > HeapBuffer[pos=0 lim=4 cap=2048: 00 00 00 00]
> > > > > > > > > Received: (datagram, server, /172.29.100.104:5678 =>
> > > > > > /0.0.0.0:1234),
> > > > > > > > > HeapBuffer[pos=0 lim=4 cap=2048: 00 00 00 00]
> > > > > > > > > Received: (datagram, server, /172.29.100.104:5678 =>
> > > > > > /0.0.0.0:1234),
> > > > > > > > > HeapBuffer[pos=0 lim=4 cap=2048: 00 00 00 00]
> > > > > > > > > Received: (datagram, server, /172.29.100.104:5678 =>
> > > > > > /0.0.0.0:1234),
> > > > > > > > > HeapBuffer[pos=0 lim=4 cap=2048: 00 00 00 00]
> > > > > > > > > Closed: (datagram, server, /172.29.100.104:5678 =>
> > /0.0.0.0:1234)
> > > > > > > > > unbound
> > > > > > > > >
> > > > > > > > > I changed the code a little bit, to be able to distinguish
> > the
> > > > > > messages.
> > > > > > > > >
> > > > > > > > > Also added a sleep before the unbind, (I think there's one
> > line
> > > > > > missing
> > > > > > > > > in your output :-)
> > > > > > > > >
> > > > > > > > >        f1.getSession().write(ByteBuffer.allocate(1)).await();
> > > > > > > > >        f1.getSession().write( ByteBuffer.allocate(2)).await();
> > > > > > > > >
> > > > > > > > >        f2.getSession().write(ByteBuffer.allocate
> > (3)).await();
> > > > > > > > >        f2.getSession ().write( ByteBuffer.allocate(4)).await();
> > > > > > > > >
> > > > > > > > >        Thread.sleep(2000);
> > > > > > > > >        acceptor.unbind();
> > > > > > > > >         System.out.println ("unbound");
> > > > > > > > >         System.exit(0);
> > > > > > > > >
> > > > > > > > > The messages sent to the broadcast address are received
> > multiple
> > > > > > times:
> > > > > > > > > twice per enabled network connection.
> > > > > > > > > When I enable all 4 network interfaces (LAN, wireless LAN
> > and two
> > > > > > > > > virtual ones for VMWare) I receive them 8 times !
> > > > > > > > >
> > > > > > > > > Maarten
> > > > > > > > >
> > > > > > > > > On 9/17/07, Trustin Lee < trustin@gmail.com > wrote:
> > > > > > > > > >
> > > > > > > > > > Hi,
> > > > > > > > > >
> > > > > > > > > > I made a lot of changes to the current datagram
> > implementation
> > > > > > in
> > > > > > > > > > trunk.  DatagramAcceptor now collaborates with
> > DatagramConnector
> > > > > > to
> > > > > > > > > > create connected datagram socket which listens to the
> > remote
> > > > > > address
> > > > > > > > > > of the received packet.  The following is simplified
> > description
> > > > > > of
> > > > > > > > > > flow:
> > > > > > > > > >
> > > > > > > > > > * DatagramAcceptor's underlying DatagramChannel.receive is
> > > > > > invoked
> > > > > > > > > > * Once data is received, new connected datagram session is
> >
> > > > > > created
> > > > > > > > > > using DatagramConnector.connect (receivedRemoteAddress,
> > > > > > > > > > acceptor.getLocalAddress()).  If there's already a session
> >
> > > > > > instance
> > > > > > > > > > associated with the remote address, it's reused.
> > > > > > > > > >
> > > > > > > > > > The advantages of this implementation are:
> > > > > > > > > >
> > > > > > > > > > * The acceptor-side datagram sessions can perform much
> > better in
> > > > > > > > > > multi-core environment.
> > > > > > > > > > * There's no need for IoSessionRecycler on the
> > acceptor-side
> > > > > > anymore.
> > > > > > > > > > You have full control over disconnection; probably using
> > > > > > sessionIdle
> > > > > > > > > > event in most cases.
> > > > > > > > > > * Code duplication can be reduced once again, and most
> > part of
> > > > > > the
> > > > > > > > > > existing acceptor code can be extracted into a generic
> > acceptor
> > > > > > > > > > implementation.
> > > > > > > > > >
> > > > > > > > > > The disadvantage is that it forces you to set reuseAddress
> > to
> > > > > > true,
> > > > > > > > > > because multiple datagram channels are bound to the same
> > local
> > > > > > > > > > address.
> > > > > > > > > >
> > > > > > > > > > In Linux, connected datagram channels have priority over
> > > > > > unconnected
> > > > > > > > > > channels, so most traffic will go directly into
> > > > > > DatagramConnector's
> > > > > > > > > > NIOProcessors.  The only exception I've found is broadcast
> > > > > > packets. It
> > > > > > > > > > is always received from the unconnected channel in
> > > > > > DatagramAcceptor.
> > > > > > > > > > DatagramAcceptor immediately forwards the event to an
> > > > > > appropriate
> > > > > > > > > > session that DatagramConnector is managing, or creates a
> > new
> > > > > > session
> > > > > > > > > > using connect().
> > > > > > > > > >
> > > > > > > > > > I think this behavior won't have any big differences among
> >
> > > > > > different
> > > > > > > > > > platforms (e.g. Windows and SUNOS).  As long as multiple
> > > > > > datagram
> > > > > > > > > > channels can be bound to the same local address, this
> > > > > > implementation
> > > > > > > > > > should work fine.  To make this sure, please run the
> > following
> > > > > > test
> > > > > > > > > > code in your machine, and let me know what the result is:
> > > > > > > > > >
> > > > > > > > > > -------- CODE BEGINS --------
> > > > > > > > > > package net.gleamynode.tmp;
> > > > > > > > > >
> > > > > > > > > > import java.net.InetAddress;
> > > > > > > > > > import java.net.InetSocketAddress;
> > > > > > > > > >
> > > > > > > > > > import org.apache.mina.common.ByteBuffer;
> > > > > > > > > > import org.apache.mina.common.ConnectFuture;
> > > > > > > > > > import org.apache.mina.common.IoHandlerAdapter ;
> > > > > > > > > > import org.apache.mina.common.IoSession;
> > > > > > > > > > import
> > org.apache.mina.transport.socket.nio.DatagramAcceptor;
> > > > > > > > > > import
> > org.apache.mina.transport.socket.nio.DatagramConnector ;
> > > > > > > > > >
> > > > > > > > > > public class Main {
> > > > > > > > > >
> > > > > > > > > >     private static final int SERVER_PORT = 1234;
> > > > > > > > > >     private static final int CLIENT_PORT = 5678;
> > > > > > > > > >
> > > > > > > > > >     public static void main(String args[]) throws
> > Exception {
> > > > > > > > > >         DatagramAcceptor acceptor = new
> > DatagramAcceptor();
> > > > > > > > > >         acceptor.setLocalAddress (new
> > > > > > InetSocketAddress(SERVER_PORT));
> > > > > > > > > >
> > > > > > > > > >         acceptor.setHandler(new IoHandlerAdapter() {
> > > > > > > > > >             @Override
> > > > > > > > > >             public void sessionOpened(IoSession session) {
> >
> > > > > > > > > >                 System.out.println("Open: " + session);
> > > > > > > > > >             }
> > > > > > > > > >
> > > > > > > > > >             @Override
> > > > > > > > > >             public void sessionClosed(IoSession session) {
> > > > > > > > > >                 System.out.println("Closed: " + session);
> > > > > > > > > >             }
> > > > > > > > > >
> > > > > > > > > >             @Override
> > > > > > > > > >             public void messageReceived(IoSession session,
> > > > > > Object o) {
> > > > > > > > > >
> > > > > > > > > >                 System.out.println("Received: " + session
> > + ", "
> > > > > > + o);
> > > > > > > > > >             }
> > > > > > > > > >         });
> > > > > > > > > >         acceptor.bind();
> > > > > > > > > >
> > > > > > > > > >         DatagramConnector connector = new
> > DatagramConnector();
> > > > > > > > > >         connector.getSessionConfig
> > ().setReuseAddress(true);
> > > > > > > > > >         connector.setHandler(new IoHandlerAdapter() {
> > > > > > > > > >             @Override
> > > > > > > > > >             public void messageReceived(IoSession session,
> > > > > > Object o) {
> > > > > > > > > >                 System.out.println("ERR?");
> > > > > > > > > >             }
> > > > > > > > > >         });
> > > > > > > > > >
> > > > > > > > > >         // Print the local host.
> > > > > > > > > >         System.out.println ("Local host: " +
> > > > > > InetAddress.getLocalHost
> > > > > > > > > > ());
> > > > > > > > > >
> > > > > > > > > >         // Try point-to-point.
> > > > > > > > > >         ConnectFuture f1 = connector.connect (
> > > > > > > > > >                 new InetSocketAddress(
> > > > > > > > > >                         InetAddress.getLocalHost(),
> > > > > > SERVER_PORT),
> > > > > > > > > >                 new InetSocketAddress(
> > > > > > > > > >                           InetAddress.getLocalHost(),
> > > > > > CLIENT_PORT));
> > > > > > > > > >         f1.await();
> > > > > > > > > >
> > > > > > > > > >
> > > > > > > > > >         f1.getSession().write(ByteBuffer.allocate
> > (1)).await();
> > > > > > > > > >         f1.getSession().write(ByteBuffer.allocate
> > (1)).await();
> > > > > > > > > >
> > > > > > > > > >
> > > > > > > > > >         // Try broadcast.
> > > > > > > > > >         ConnectFuture f2 = connector.connect(
> > > > > > > > > >                 new InetSocketAddress(
> > > > > > > > > >                         " 255.255.255.255", SERVER_PORT),
> > > > > > > > > >                 new InetSocketAddress(
> > > > > > > > > >                         InetAddress.getLocalHost(),
> > > > > > CLIENT_PORT));
> > > > > > > > > >
> > > > > > > > > >         f2.await();
> > > > > > > > > >         f2.getSession().write(ByteBuffer.allocate(1)).await();
> > > > > > > > > >         f2.getSession().write(ByteBuffer.allocate(1)).await();
> >
> > > > > > > > > >
> > > > > > > > > >         acceptor.unbind();
> > > > > > > > > >
> > > > > > > > > >         System.exit(0);
> > > > > > > > > >     }
> > > > > > > > > > }
> > > > > > > > > > -------- CODE ENDS --------
> > > > > > > > > >
> > > > > > > > > > The expected result is:
> > > > > > > > > >
> > > > > > > > > > -------- RESULT BEGINS --------
> > > > > > > > > > Local host: primary/127.0.0.1
> > > > > > > > > > Open: (datagram, server, /127.0.0.1:5678 =>
> > > > > > /0:0:0:0:0:0:0:0:1234)
> > > > > > > > > > Received: (datagram, server, /127.0.0.1:5678 =>
> > > > > > > > > > /0:0:0:0:0:0:0:0:1234), HeapBuffer[pos=0 lim=1 cap=2048:
> > 00]
> > > > > > > > > > Received: (datagram, server, /127.0.0.1:5678 =>
> > > > > > > > > > /0:0:0:0:0:0:0:0:1234), HeapBuffer[pos=0 lim=1 cap=2048:
> > 00]
> > > > > > > > > > Received: (datagram, server, /127.0.0.1:5678 =>
> > > > > > > > > > /0:0:0:0:0:0:0:0:1234), HeapBuffer[pos=0 lim=1 cap=2048:
> > 00]
> > > > > > > > > > Closed: (datagram, server, /127.0.0.1:5678 =>
> > > > > > /0:0:0:0:0:0:0:0:1234)
> > > > > > > > > > -------- RESULT ENDS --------
> > > > > > > > > >
> > > > > > > > > > If this test fails on any platform that runs Java 5, I am
> > doomed
> > > > > > to
> > > > > > > > > > revert my changes. :)
> > > > > > > > > >
> > > > > > > > > > Trustin
> > > > > > > > > > --
> > > > > > > > > > what we call human nature is actually human habit
> > > > > > > > > > --
> > > > > > > > > > http://gleamynode.net/
> > > > > > > > > > --
> > > > > > > > > > PGP Key ID: 0x0255ECA6
> > > > > > > > > >
> > > > > > > > >
> > > > > > > > >
> > > > > > > >
> > > > > > >
> > > > > >
> > > > > >
> > > > > > --
> > > > > > what we call human nature is actually human habit
> > > > > > --
> > > > > > http://gleamynode.net/
> > > > > > --
> > > > > > PGP Key ID: 0x0255ECA6
> > > > > >
> > > > >
> > > > >
> > > >
> > >
> > >
> > > --
> > > what we call human nature is actually human habit
> > > --
> > > http://gleamynode.net/
> > > --
> > > PGP Key ID: 0x0255ECA6
> > >
> >
> >
> > --
> > what we call human nature is actually human habit
> > --
> > http://gleamynode.net/
> > --
> > PGP Key ID: 0x0255ECA6
> >
>


-- 
what we call human nature is actually human habit
--
http://gleamynode.net/
--
PGP Key ID: 0x0255ECA6

Re: Request for a test on various platforms:

Posted by Maarten Bosteels <mb...@gmail.com>.
On Linux:
/172.30.6.12:5678, 1
/172.30.6.12:5678, 2
/172.30.6.12:5678, 3
/172.30.6.12:5678, 4

Notice that the linux box has only 1 physical network card (and one virtual
interface)

eth0      Link encap:Ethernet  HWaddr 00:11:43:2D:3C:29
          inet addr:172.30.6.12  Bcast:172.30.255.255  Mask:255.255.0.0
          inet6 addr: fe80::211:43ff:fe2d:3c29/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:5213648 errors:0 dropped:0 overruns:0 frame:0
          TX packets:3913571 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:100
          RX bytes:2836668837 (2.6 GiB)  TX bytes:1058082225 (1009.0 MiB)
          Base address:0xdcc0 Memory:dfee0000-dff00000

eth0:0    Link encap:Ethernet  HWaddr 00:11:43:2D:3C:29
          inet addr:172.30.6.16  Bcast:172.30.255.255  Mask:255.255.0.0
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          Base address:0xdcc0 Memory:dfee0000-dff00000

lo        Link encap:Local Loopback
          inet addr:127.0.0.1  Mask:255.0.0.0
          inet6 addr: ::1/128 Scope:Host
          UP LOOPBACK RUNNING  MTU:16436  Metric:1
          RX packets:2849256 errors:0 dropped:0 overruns:0 frame:0
          TX packets:2849256 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0
          RX bytes:645905386 (615.9 MiB)  TX bytes:645905386 (615.9 MiB)


On Windows with one network connection enabled:
/172.30.6.13:5678, 1
/172.30.6.13:5678, 2
/172.30.6.13:5678, 3
/172.30.6.13:5678, 4

On Windows with 2 network connections enabled:  (notice that source ip
changed: 172.29.100.104 is the WLAN nic)
/172.29.100.104:5678, 1
/172.29.100.104:5678, 2
/172.29.100.104:5678, 3
/172.29.100.104:5678, 3
/172.29.100.104:5678, 4
/172.29.100.104:5678, 4

On Windows with 3 network connections enabled:

/172.29.100.104:5678, 1
/172.29.100.104:5678, 2
/172.29.100.104:5678, 3
/172.29.100.104:5678, 3
/172.29.100.104:5678, 3
/172.29.100.104:5678, 4
/172.29.100.104:5678, 4
/172.29.100.104:5678, 4

On Windows with 4 network connections enabled:

/172.29.100.104:5678, 1
/172.29.100.104:5678, 2
/172.29.100.104:5678, 3
/172.29.100.104:5678, 3
/172.29.100.104:5678, 3
/172.29.100.104:5678, 3
/172.29.100.104:5678, 4
/172.29.100.104:5678, 4
/172.29.100.104:5678, 4
/172.29.100.104:5678, 4

On Solaris, with one nic:

/172.30.0.139:5678, 1
/172.30.0.139:5678, 2
/172.30.0.139:5678, 3
/172.30.0.139:5678, 4

On the Solaris box with multiple interfaces

/10.0.0.120:56787, 1
/10.0.0.120:56787, 2
/10.0.0.120:56787, 3
/10.0.0.120:56787, 3
/10.0.0.120:56787, 4
/10.0.0.120:56787, 4

lo0: flags=2001000849<UP,LOOPBACK,RUNNING,MULTICAST,IPv4,VIRTUAL> mtu 8232
index 1
        inet 127.0.0.1 netmask ff000000
ce0: flags=1000843<UP,BROADCAST,RUNNING,MULTICAST,IPv4> mtu 1500 index 2
        inet 192.168.113.8 netmask ffffff00 broadcast 192.168.113.255
        ether 0:14:4f:17:d:de
ce1: flags=1000802<BROADCAST,MULTICAST,IPv4> mtu 1500 index 3
        inet 0.0.0.0 netmask 0
        ether 0:14:4f:17:d:df
ce2: flags=1000802<BROADCAST,MULTICAST,IPv4> mtu 1500 index 4
        inet 0.0.0.0 netmask 0
        ether 0:14:4f:17:d:e0
eri0: flags=1000843<UP,BROADCAST,RUNNING,MULTICAST,IPv4> mtu 1500 index 5
        inet 10.0.0.120 netmask ffffff00 broadcast 10.0.0.255
        ether 0:3:ba:b0:49:65
eri0:1: flags=1040843<UP,BROADCAST,RUNNING,MULTICAST,DEPRECATED,IPv4> mtu
1500 index 5
        inet 10.0.0.130 netmask ffffff00 broadcast 10.0.0.255

This is what W. Richard Stevens has to say about the "limited boadcast
address"
[quote]
An unanswered question is: if a host is multihomed and a process sends a
datagram to the limited broadcast address, should the datagram be sent out
each connected interface that supports broadcasting ?
If not, an application that wants to broadcast out all interfaces must
determine all the interfaces on the host that support broadcasting, and send
a copy out each interface. Most BSD systems treat 255.255.255.255 as an
alias for the broadcast address of the first interface that was configured,
and don't provide any way to send a datagram out all attached,
broadcast-capable interfaces.
[end of quote]

http://www.goldfish.org/books/TCPIP%20Illustrated%20Vol%201/broadcas.htm

Maarten

On 9/18/07, Trustin Lee <tr...@gmail.com> wrote:
>
> I think we also need to check how our previous implementation works
> with the test code.
>
> Maarten, could you run the test again on Windows and SunOS with the
> plain blocking I/O server instead of DatagramAcceptor?
>
> -------- CODE BEGINS --------
> package net.gleamynode.tmp;
>
> import java.net.DatagramPacket;
> import java.net.DatagramSocket;
> import java.net.InetSocketAddress;
>
> public class DatagramServer {
>     private static final int SERVER_PORT = 1234;
>
>     public static void main(String[] args) throws Exception {
>         DatagramSocket s = new DatagramSocket(new
> InetSocketAddress(SERVER_PORT));
>
>         DatagramPacket p = new DatagramPacket(new byte[2048], 2048);
>         for (;;) {
>             s.receive(p);
>             System.out.println("" + p.getSocketAddress() + ", " +
> p.getLength());
>         }
>     }
> }
> -------- CODE ENDS --------
>
> The expected output is:
>
> /127.0.0.1:5678, 1
> /127.0.0.1:5678, 2
> /127.0.0.1:5678, 3
> /127.0.0.1:5678, 4
>
> You will need to comment out 'acceptor.bind();' to run the test.
>
> Thanks in advance,
> Trustin
>
> On 9/18/07, Trustin Lee <tr...@gmail.com> wrote:
> > It seems like each broadcast packet is broadcasted as many times as
> > the number of network interface cards in Windows and SunOS.  It's
> > interesting that Linux doesn't.  Maarten, did I understand correctly?
> >
> > I'd like to find a way to suppress the duplicate event emission, but
> > don't have any idea yet.
> >
> > Thanks,
> > Trustin
> >
> > On 9/18/07, Maarten Bosteels <mb...@gmail.com> wrote:
> > > Also tested it on a Solaris box  with just one network interface:
> > >
> > > [root@mercury tmp]$ ifconfig -a
> > > lo0: flags=2001000849<UP,LOOPBACK,RUNNING,MULTICAST,IPv4,VIRTUAL> mtu
> 8232
> > > index 1
> > >         inet 127.0.0.1 netmask ff000000
> > > hme0: flags=1000843<UP,BROADCAST,RUNNING,MULTICAST,IPv4> mtu 1500
> index 2
> > >         inet 172.30.0.139 netmask ffff0000 broadcast 172.30.255.255
> > >         ether 8:0:20:e6:85:18
> > > [root@mercury tmp]$
> > > [root@mercury tmp]$ uname -a
> > > SunOS mercury 5.10 Generic_118833-24 sun4u sparc SUNW,Ultra-250
> > > [root@mercury tmp]$
> > > [root@mercury tmp]$ java -cp mina-core-2.0.0-M1-SNAPSHOT.jar:.
> TestTrustin
> > > Local host: mercury/172.30.0.139
> > > Open: (datagram, server, /172.30.0.139:5678 => /0.0.0.0:1234)
> > > Received: (datagram, server, /172.30.0.139:5678 => /0.0.0.0:1234),
> > > HeapBuffer[pos=0 lim=1 cap=2048: 00]
> > > Received: (datagram, server, /172.30.0.139:5678 => /0.0.0.0:1234),
> > > HeapBuffer[pos=0 lim=2 cap=2048: 00 00]
> > > Received: (datagram, server, /172.30.0.139:5678 => /0.0.0.0:1234),
> > > HeapBuffer[pos=0 lim=3 cap=2048: 00 00 00]
> > > Received: (datagram, server, /172.30.0.139:5678 => /0.0.0.0:1234),
> > > HeapBuffer[pos=0 lim=4 cap=2048: 00 00 00 00]
> > > unbound
> > > Closed: (datagram, server, /172.30.0.139:5678 => /0.0.0.0:1234)
> > > [root@mercury tmp]$
> > >
> > > Maarten
> > >
> > > On 9/18/07, Maarten Bosteels <mb...@gmail.com> wrote:
> > > >
> > > > On 9/18/07, Trustin Lee < trustin@gmail.com> wrote:
> > > > >
> > > > > How many network devices exist in SunOS?
> > > >
> > > >
> > > >
> > > > root@mysun # ifconfig -a
> > > > lo0: flags=2001000849<UP,LOOPBACK,RUNNING,MULTICAST,IPv4,VIRTUAL>
> mtu 8232
> > > > index 1
> > > >         inet 127.0.0.1 netmask ff000000
> > > > ce0: flags=1000843<UP,BROADCAST,RUNNING,MULTICAST,IPv4> mtu 1500
> index 2
> > > >         inet 192.168.113.8 netmask ffffff00 broadcast
> 192.168.113.255
> > > >         ether 0:14:4f:17:d:de
> > > > ce1: flags=1000802<BROADCAST,MULTICAST,IPv4> mtu 1500 index 3
> > > >         inet 0.0.0.0 netmask 0
> > > >         ether 0:14:4f:17:d:df
> > > > ce2: flags=1000802<BROADCAST,MULTICAST,IPv4> mtu 1500 index 4
> > > >         inet 0.0.0.0 netmask 0
> > > >         ether 0:14:4f:17:d:e0
> > > > eri0: flags=1000843<UP,BROADCAST,RUNNING,MULTICAST,IPv4> mtu 1500
> index 5
> > > >         inet 10.0.0.120 netmask ffffff00 broadcast 10.0.0.255
> > > >         ether 0:3:ba:b0:49:65
> > > > eri0:1:
> flags=1040843<UP,BROADCAST,RUNNING,MULTICAST,DEPRECATED,IPv4> mtu
> > > > 1500 index 5
> > > >         inet 10.0.0.130 netmask ffffff00 broadcast 10.0.0.255
> > > >
> > > > Maarten
> > > >
> > > > Thanks!
> > > > > Trustin
> > > > >
> > > > > On 9/18/07, Maarten Bosteels < mbosteels.dns@gmail.com> wrote:
> > > > > > On SunOS 5.10  sun4u sparc SUNW,Sun-Fire-V890
> > > > > >
> > > > > > java version " 1.5.0_01"
> > > > > > Java(TM) 2 Runtime Environment, Standard Edition (build
> 1.5.0_01-b08)
> > > > > > Java HotSpot(TM) Server VM (build 1.5.0_01-b08, mixed mode)
> > > > > >
> > > > > > Open: (datagram, server, /10.0.0.120:5678 => /0.0.0.0:1234)
> > > > > > Received: (datagram, server, /10.0.0.120:5678 => /0.0.0.0:1234),
> > > > > > HeapBuffer[pos=0 lim=1 cap=2048: 00]
> > > > > > Received: (datagram, server, /10.0.0.120:5678 => /0.0.0.0:1234),
>
> > > > > > HeapBuffer[pos=0 lim=2 cap=2048: 00 00]
> > > > > > Received: (datagram, server, /10.0.0.120:5678 => /0.0.0.0:1234),
> > > > > > HeapBuffer[pos=0 lim=3 cap=2048: 00 00 00]
> > > > > > Received: (datagram, server, /10.0.0.120:5678 => /0.0.0.0:1234),
> > > > > > HeapBuffer[pos=0 lim=3 cap=2048: 00 00 00]
> > > > > > Received: (datagram, server, /10.0.0.120:5678 => /0.0.0.0:1234),
>
> > > > > > HeapBuffer[pos=0 lim=4 cap=2048: 00 00 00 00]
> > > > > > Received: (datagram, server, /10.0.0.120:5678 => /0.0.0.0:1234),
> > > > > > HeapBuffer[pos=0 lim=4 cap=2048: 00 00 00 00]
> > > > > > unbound
> > > > > > Closed: (datagram, server, /10.0.0.120:5678 => /0.0.0.0:1234)
> > > > > >
> > > > > > Maarten
> > > > > >
> > > > > > On 9/18/07, Maarten Bosteels <mbosteels.dns@gmail.com > wrote:
> > > > > > >
> > > > > > > On linux 2.6.9 , jdk 1.6
> > > > > > >
> > > > > > > Local host: mortimer/172.30.6.12
> > > > > > > Open: (datagram, server, /172.30.6.12:5678 =>
> /0:0:0:0:0:0:0:0:1234)
> > > > > > > Received: (datagram, server, /172.30.6.12:5678 =>
> > > > > /0:0:0:0:0:0:0:0:1234),
> > > > > > > HeapBuffer[pos=0 lim=1 cap=2048: 00]
> > > > > > > Received: (datagram, server, /172.30.6.12:5678 =>
> > > > > /0:0:0:0:0:0:0:0:1234),
> > > > > > > HeapBuffer[pos=0 lim=2 cap=2048: 00 00]
> > > > > > > Received: (datagram, server, /172.30.6.12:5678 =>
> > > > > /0:0:0:0:0:0:0:0:1234),
> > > > > > > HeapBuffer[pos=0 lim=3 cap=2048: 00 00 00]
> > > > > > > Received: (datagram, server, /172.30.6.12:5678 =>
> > > > > /0:0:0:0:0:0:0:0:1234),
> > > > > > > HeapBuffer[pos=0 lim=4 cap=2048: 00 00 00 00]
> > > > > > > unbound
> > > > > > > Closed: (datagram, server, /172.30.6.12:5678 =>
> > > > > /0:0:0:0:0:0:0:0:1234)
> > > > > > >
> > > > > > > Adding a virtual interface (eth0:0) doesn't make a difference.
>
> > > > > > > Maarten
> > > > > > >
> > > > > > > On 9/18/07, Maarten Bosteels < mbosteels.dns@gmail.com> wrote:
>
> > > > > > > >
> > > > > > > > Hello Trustin,
> > > > > > > >
> > > > > > > > I ran the code on Windows XP jdk 1.6 , and this is the
> output I
> > > > > got:
> > > > > > > >
> > > > > > > > Local host: kweenie/172.29.100.104
> > > > > > > > Open: (datagram, server, /172.29.100.104:5678 =>
> /0.0.0.0:1234)
> > > > > > > > Received: (datagram, server, /172.29.100.104:5678 =>
> > > > > /0.0.0.0:1234),
> > > > > > > > HeapBuffer[pos=0 lim=2 cap=2048: 00 00]
> > > > > > > > Received: (datagram, server, /172.29.100.104:5678 =>
> > > > > /0.0.0.0:1234),
> > > > > > > > HeapBuffer[pos=0 lim=1 cap=2048: 00]
> > > > > > > > Received: (datagram, server, /172.29.100.104:5678 =>
> > > > > /0.0.0.0:1234),
> > > > > > > > HeapBuffer[pos=0 lim=3 cap=2048: 00 00 00]
> > > > > > > > Received: (datagram, server, /172.29.100.104:5678 =>
> > > > > /0.0.0.0:1234),
> > > > > > > > HeapBuffer[pos=0 lim=3 cap=2048: 00 00 00]
> > > > > > > > Received: (datagram, server, /172.29.100.104:5678 =>
> > > > > /0.0.0.0:1234),
> > > > > > > > HeapBuffer[pos=0 lim=3 cap=2048: 00 00 00]
> > > > > > > > Received: (datagram, server, /172.29.100.104:5678 =>
> > > > > /0.0.0.0:1234),
> > > > > > > > HeapBuffer[pos=0 lim=3 cap=2048: 00 00 00]
> > > > > > > > Received: (datagram, server, /172.29.100.104:5678 =>
> > > > > /0.0.0.0:1234),
> > > > > > > > HeapBuffer[pos=0 lim=4 cap=2048: 00 00 00 00]
> > > > > > > > Received: (datagram, server, /172.29.100.104:5678 =>
> > > > > /0.0.0.0:1234),
> > > > > > > > HeapBuffer[pos=0 lim=4 cap=2048: 00 00 00 00]
> > > > > > > > Received: (datagram, server, /172.29.100.104:5678 =>
> > > > > /0.0.0.0:1234),
> > > > > > > > HeapBuffer[pos=0 lim=4 cap=2048: 00 00 00 00]
> > > > > > > > Received: (datagram, server, /172.29.100.104:5678 =>
> > > > > /0.0.0.0:1234),
> > > > > > > > HeapBuffer[pos=0 lim=4 cap=2048: 00 00 00 00]
> > > > > > > > Closed: (datagram, server, /172.29.100.104:5678 =>
> /0.0.0.0:1234)
> > > > > > > > unbound
> > > > > > > >
> > > > > > > > I changed the code a little bit, to be able to distinguish
> the
> > > > > messages.
> > > > > > > >
> > > > > > > > Also added a sleep before the unbind, (I think there's one
> line
> > > > > missing
> > > > > > > > in your output :-)
> > > > > > > >
> > > > > > > >        f1.getSession().write(ByteBuffer.allocate(1)).await();
> > > > > > > >        f1.getSession().write( ByteBuffer.allocate(2)).await();
> > > > > > > >
> > > > > > > >        f2.getSession().write(ByteBuffer.allocate
> (3)).await();
> > > > > > > >        f2.getSession ().write( ByteBuffer.allocate(4)).await();
> > > > > > > >
> > > > > > > >        Thread.sleep(2000);
> > > > > > > >        acceptor.unbind();
> > > > > > > >         System.out.println ("unbound");
> > > > > > > >         System.exit(0);
> > > > > > > >
> > > > > > > > The messages sent to the broadcast address are received
> multiple
> > > > > times:
> > > > > > > > twice per enabled network connection.
> > > > > > > > When I enable all 4 network interfaces (LAN, wireless LAN
> and two
> > > > > > > > virtual ones for VMWare) I receive them 8 times !
> > > > > > > >
> > > > > > > > Maarten
> > > > > > > >
> > > > > > > > On 9/17/07, Trustin Lee < trustin@gmail.com > wrote:
> > > > > > > > >
> > > > > > > > > Hi,
> > > > > > > > >
> > > > > > > > > I made a lot of changes to the current datagram
> implementation
> > > > > in
> > > > > > > > > trunk.  DatagramAcceptor now collaborates with
> DatagramConnector
> > > > > to
> > > > > > > > > create connected datagram socket which listens to the
> remote
> > > > > address
> > > > > > > > > of the received packet.  The following is simplified
> description
> > > > > of
> > > > > > > > > flow:
> > > > > > > > >
> > > > > > > > > * DatagramAcceptor's underlying DatagramChannel.receive is
> > > > > invoked
> > > > > > > > > * Once data is received, new connected datagram session is
>
> > > > > created
> > > > > > > > > using DatagramConnector.connect (receivedRemoteAddress,
> > > > > > > > > acceptor.getLocalAddress()).  If there's already a session
>
> > > > > instance
> > > > > > > > > associated with the remote address, it's reused.
> > > > > > > > >
> > > > > > > > > The advantages of this implementation are:
> > > > > > > > >
> > > > > > > > > * The acceptor-side datagram sessions can perform much
> better in
> > > > > > > > > multi-core environment.
> > > > > > > > > * There's no need for IoSessionRecycler on the
> acceptor-side
> > > > > anymore.
> > > > > > > > > You have full control over disconnection; probably using
> > > > > sessionIdle
> > > > > > > > > event in most cases.
> > > > > > > > > * Code duplication can be reduced once again, and most
> part of
> > > > > the
> > > > > > > > > existing acceptor code can be extracted into a generic
> acceptor
> > > > > > > > > implementation.
> > > > > > > > >
> > > > > > > > > The disadvantage is that it forces you to set reuseAddress
> to
> > > > > true,
> > > > > > > > > because multiple datagram channels are bound to the same
> local
> > > > > > > > > address.
> > > > > > > > >
> > > > > > > > > In Linux, connected datagram channels have priority over
> > > > > unconnected
> > > > > > > > > channels, so most traffic will go directly into
> > > > > DatagramConnector's
> > > > > > > > > NIOProcessors.  The only exception I've found is broadcast
> > > > > packets. It
> > > > > > > > > is always received from the unconnected channel in
> > > > > DatagramAcceptor.
> > > > > > > > > DatagramAcceptor immediately forwards the event to an
> > > > > appropriate
> > > > > > > > > session that DatagramConnector is managing, or creates a
> new
> > > > > session
> > > > > > > > > using connect().
> > > > > > > > >
> > > > > > > > > I think this behavior won't have any big differences among
>
> > > > > different
> > > > > > > > > platforms (e.g. Windows and SUNOS).  As long as multiple
> > > > > datagram
> > > > > > > > > channels can be bound to the same local address, this
> > > > > implementation
> > > > > > > > > should work fine.  To make this sure, please run the
> following
> > > > > test
> > > > > > > > > code in your machine, and let me know what the result is:
> > > > > > > > >
> > > > > > > > > -------- CODE BEGINS --------
> > > > > > > > > package net.gleamynode.tmp;
> > > > > > > > >
> > > > > > > > > import java.net.InetAddress;
> > > > > > > > > import java.net.InetSocketAddress;
> > > > > > > > >
> > > > > > > > > import org.apache.mina.common.ByteBuffer;
> > > > > > > > > import org.apache.mina.common.ConnectFuture;
> > > > > > > > > import org.apache.mina.common.IoHandlerAdapter ;
> > > > > > > > > import org.apache.mina.common.IoSession;
> > > > > > > > > import
> org.apache.mina.transport.socket.nio.DatagramAcceptor;
> > > > > > > > > import
> org.apache.mina.transport.socket.nio.DatagramConnector ;
> > > > > > > > >
> > > > > > > > > public class Main {
> > > > > > > > >
> > > > > > > > >     private static final int SERVER_PORT = 1234;
> > > > > > > > >     private static final int CLIENT_PORT = 5678;
> > > > > > > > >
> > > > > > > > >     public static void main(String args[]) throws
> Exception {
> > > > > > > > >         DatagramAcceptor acceptor = new
> DatagramAcceptor();
> > > > > > > > >         acceptor.setLocalAddress (new
> > > > > InetSocketAddress(SERVER_PORT));
> > > > > > > > >
> > > > > > > > >         acceptor.setHandler(new IoHandlerAdapter() {
> > > > > > > > >             @Override
> > > > > > > > >             public void sessionOpened(IoSession session) {
>
> > > > > > > > >                 System.out.println("Open: " + session);
> > > > > > > > >             }
> > > > > > > > >
> > > > > > > > >             @Override
> > > > > > > > >             public void sessionClosed(IoSession session) {
> > > > > > > > >                 System.out.println("Closed: " + session);
> > > > > > > > >             }
> > > > > > > > >
> > > > > > > > >             @Override
> > > > > > > > >             public void messageReceived(IoSession session,
> > > > > Object o) {
> > > > > > > > >
> > > > > > > > >                 System.out.println("Received: " + session
> + ", "
> > > > > + o);
> > > > > > > > >             }
> > > > > > > > >         });
> > > > > > > > >         acceptor.bind();
> > > > > > > > >
> > > > > > > > >         DatagramConnector connector = new
> DatagramConnector();
> > > > > > > > >         connector.getSessionConfig
> ().setReuseAddress(true);
> > > > > > > > >         connector.setHandler(new IoHandlerAdapter() {
> > > > > > > > >             @Override
> > > > > > > > >             public void messageReceived(IoSession session,
> > > > > Object o) {
> > > > > > > > >                 System.out.println("ERR?");
> > > > > > > > >             }
> > > > > > > > >         });
> > > > > > > > >
> > > > > > > > >         // Print the local host.
> > > > > > > > >         System.out.println ("Local host: " +
> > > > > InetAddress.getLocalHost
> > > > > > > > > ());
> > > > > > > > >
> > > > > > > > >         // Try point-to-point.
> > > > > > > > >         ConnectFuture f1 = connector.connect (
> > > > > > > > >                 new InetSocketAddress(
> > > > > > > > >                         InetAddress.getLocalHost(),
> > > > > SERVER_PORT),
> > > > > > > > >                 new InetSocketAddress(
> > > > > > > > >                           InetAddress.getLocalHost(),
> > > > > CLIENT_PORT));
> > > > > > > > >         f1.await();
> > > > > > > > >
> > > > > > > > >
> > > > > > > > >         f1.getSession().write(ByteBuffer.allocate
> (1)).await();
> > > > > > > > >         f1.getSession().write(ByteBuffer.allocate
> (1)).await();
> > > > > > > > >
> > > > > > > > >
> > > > > > > > >         // Try broadcast.
> > > > > > > > >         ConnectFuture f2 = connector.connect(
> > > > > > > > >                 new InetSocketAddress(
> > > > > > > > >                         " 255.255.255.255", SERVER_PORT),
> > > > > > > > >                 new InetSocketAddress(
> > > > > > > > >                         InetAddress.getLocalHost(),
> > > > > CLIENT_PORT));
> > > > > > > > >
> > > > > > > > >         f2.await();
> > > > > > > > >         f2.getSession().write(ByteBuffer.allocate(1)).await();
> > > > > > > > >         f2.getSession().write(ByteBuffer.allocate(1)).await();
>
> > > > > > > > >
> > > > > > > > >         acceptor.unbind();
> > > > > > > > >
> > > > > > > > >         System.exit(0);
> > > > > > > > >     }
> > > > > > > > > }
> > > > > > > > > -------- CODE ENDS --------
> > > > > > > > >
> > > > > > > > > The expected result is:
> > > > > > > > >
> > > > > > > > > -------- RESULT BEGINS --------
> > > > > > > > > Local host: primary/127.0.0.1
> > > > > > > > > Open: (datagram, server, /127.0.0.1:5678 =>
> > > > > /0:0:0:0:0:0:0:0:1234)
> > > > > > > > > Received: (datagram, server, /127.0.0.1:5678 =>
> > > > > > > > > /0:0:0:0:0:0:0:0:1234), HeapBuffer[pos=0 lim=1 cap=2048:
> 00]
> > > > > > > > > Received: (datagram, server, /127.0.0.1:5678 =>
> > > > > > > > > /0:0:0:0:0:0:0:0:1234), HeapBuffer[pos=0 lim=1 cap=2048:
> 00]
> > > > > > > > > Received: (datagram, server, /127.0.0.1:5678 =>
> > > > > > > > > /0:0:0:0:0:0:0:0:1234), HeapBuffer[pos=0 lim=1 cap=2048:
> 00]
> > > > > > > > > Closed: (datagram, server, /127.0.0.1:5678 =>
> > > > > /0:0:0:0:0:0:0:0:1234)
> > > > > > > > > -------- RESULT ENDS --------
> > > > > > > > >
> > > > > > > > > If this test fails on any platform that runs Java 5, I am
> doomed
> > > > > to
> > > > > > > > > revert my changes. :)
> > > > > > > > >
> > > > > > > > > Trustin
> > > > > > > > > --
> > > > > > > > > what we call human nature is actually human habit
> > > > > > > > > --
> > > > > > > > > http://gleamynode.net/
> > > > > > > > > --
> > > > > > > > > PGP Key ID: 0x0255ECA6
> > > > > > > > >
> > > > > > > >
> > > > > > > >
> > > > > > >
> > > > > >
> > > > >
> > > > >
> > > > > --
> > > > > what we call human nature is actually human habit
> > > > > --
> > > > > http://gleamynode.net/
> > > > > --
> > > > > PGP Key ID: 0x0255ECA6
> > > > >
> > > >
> > > >
> > >
> >
> >
> > --
> > what we call human nature is actually human habit
> > --
> > http://gleamynode.net/
> > --
> > PGP Key ID: 0x0255ECA6
> >
>
>
> --
> what we call human nature is actually human habit
> --
> http://gleamynode.net/
> --
> PGP Key ID: 0x0255ECA6
>

Re: Request for a test on various platforms:

Posted by Trustin Lee <tr...@gmail.com>.
I think we also need to check how our previous implementation works
with the test code.

Maarten, could you run the test again on Windows and SunOS with the
plain blocking I/O server instead of DatagramAcceptor?

-------- CODE BEGINS --------
package net.gleamynode.tmp;

import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetSocketAddress;

public class DatagramServer {
    private static final int SERVER_PORT = 1234;

    public static void main(String[] args) throws Exception {
        DatagramSocket s = new DatagramSocket(new
InetSocketAddress(SERVER_PORT));

        DatagramPacket p = new DatagramPacket(new byte[2048], 2048);
        for (;;) {
            s.receive(p);
            System.out.println("" + p.getSocketAddress() + ", " +
p.getLength());
        }
    }
}
-------- CODE ENDS --------

The expected output is:

/127.0.0.1:5678, 1
/127.0.0.1:5678, 2
/127.0.0.1:5678, 3
/127.0.0.1:5678, 4

You will need to comment out 'acceptor.bind();' to run the test.

Thanks in advance,
Trustin

On 9/18/07, Trustin Lee <tr...@gmail.com> wrote:
> It seems like each broadcast packet is broadcasted as many times as
> the number of network interface cards in Windows and SunOS.  It's
> interesting that Linux doesn't.  Maarten, did I understand correctly?
>
> I'd like to find a way to suppress the duplicate event emission, but
> don't have any idea yet.
>
> Thanks,
> Trustin
>
> On 9/18/07, Maarten Bosteels <mb...@gmail.com> wrote:
> > Also tested it on a Solaris box  with just one network interface:
> >
> > [root@mercury tmp]$ ifconfig -a
> > lo0: flags=2001000849<UP,LOOPBACK,RUNNING,MULTICAST,IPv4,VIRTUAL> mtu 8232
> > index 1
> >         inet 127.0.0.1 netmask ff000000
> > hme0: flags=1000843<UP,BROADCAST,RUNNING,MULTICAST,IPv4> mtu 1500 index 2
> >         inet 172.30.0.139 netmask ffff0000 broadcast 172.30.255.255
> >         ether 8:0:20:e6:85:18
> > [root@mercury tmp]$
> > [root@mercury tmp]$ uname -a
> > SunOS mercury 5.10 Generic_118833-24 sun4u sparc SUNW,Ultra-250
> > [root@mercury tmp]$
> > [root@mercury tmp]$ java -cp mina-core-2.0.0-M1-SNAPSHOT.jar:. TestTrustin
> > Local host: mercury/172.30.0.139
> > Open: (datagram, server, /172.30.0.139:5678 => /0.0.0.0:1234)
> > Received: (datagram, server, /172.30.0.139:5678 => /0.0.0.0:1234),
> > HeapBuffer[pos=0 lim=1 cap=2048: 00]
> > Received: (datagram, server, /172.30.0.139:5678 => /0.0.0.0:1234),
> > HeapBuffer[pos=0 lim=2 cap=2048: 00 00]
> > Received: (datagram, server, /172.30.0.139:5678 => /0.0.0.0:1234),
> > HeapBuffer[pos=0 lim=3 cap=2048: 00 00 00]
> > Received: (datagram, server, /172.30.0.139:5678 => /0.0.0.0:1234),
> > HeapBuffer[pos=0 lim=4 cap=2048: 00 00 00 00]
> > unbound
> > Closed: (datagram, server, /172.30.0.139:5678 => /0.0.0.0:1234)
> > [root@mercury tmp]$
> >
> > Maarten
> >
> > On 9/18/07, Maarten Bosteels <mb...@gmail.com> wrote:
> > >
> > > On 9/18/07, Trustin Lee <tr...@gmail.com> wrote:
> > > >
> > > > How many network devices exist in SunOS?
> > >
> > >
> > >
> > > root@mysun # ifconfig -a
> > > lo0: flags=2001000849<UP,LOOPBACK,RUNNING,MULTICAST,IPv4,VIRTUAL> mtu 8232
> > > index 1
> > >         inet 127.0.0.1 netmask ff000000
> > > ce0: flags=1000843<UP,BROADCAST,RUNNING,MULTICAST,IPv4> mtu 1500 index 2
> > >         inet 192.168.113.8 netmask ffffff00 broadcast 192.168.113.255
> > >         ether 0:14:4f:17:d:de
> > > ce1: flags=1000802<BROADCAST,MULTICAST,IPv4> mtu 1500 index 3
> > >         inet 0.0.0.0 netmask 0
> > >         ether 0:14:4f:17:d:df
> > > ce2: flags=1000802<BROADCAST,MULTICAST,IPv4> mtu 1500 index 4
> > >         inet 0.0.0.0 netmask 0
> > >         ether 0:14:4f:17:d:e0
> > > eri0: flags=1000843<UP,BROADCAST,RUNNING,MULTICAST,IPv4> mtu 1500 index 5
> > >         inet 10.0.0.120 netmask ffffff00 broadcast 10.0.0.255
> > >         ether 0:3:ba:b0:49:65
> > > eri0:1: flags=1040843<UP,BROADCAST,RUNNING,MULTICAST,DEPRECATED,IPv4> mtu
> > > 1500 index 5
> > >         inet 10.0.0.130 netmask ffffff00 broadcast 10.0.0.255
> > >
> > > Maarten
> > >
> > > Thanks!
> > > > Trustin
> > > >
> > > > On 9/18/07, Maarten Bosteels <mb...@gmail.com> wrote:
> > > > > On SunOS 5.10  sun4u sparc SUNW,Sun-Fire-V890
> > > > >
> > > > > java version " 1.5.0_01"
> > > > > Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0_01-b08)
> > > > > Java HotSpot(TM) Server VM (build 1.5.0_01-b08, mixed mode)
> > > > >
> > > > > Open: (datagram, server, /10.0.0.120:5678 => /0.0.0.0:1234)
> > > > > Received: (datagram, server, /10.0.0.120:5678 => /0.0.0.0:1234),
> > > > > HeapBuffer[pos=0 lim=1 cap=2048: 00]
> > > > > Received: (datagram, server, /10.0.0.120:5678 => /0.0.0.0:1234),
> > > > > HeapBuffer[pos=0 lim=2 cap=2048: 00 00]
> > > > > Received: (datagram, server, /10.0.0.120:5678 => /0.0.0.0:1234),
> > > > > HeapBuffer[pos=0 lim=3 cap=2048: 00 00 00]
> > > > > Received: (datagram, server, /10.0.0.120:5678 => /0.0.0.0:1234),
> > > > > HeapBuffer[pos=0 lim=3 cap=2048: 00 00 00]
> > > > > Received: (datagram, server, /10.0.0.120:5678 => /0.0.0.0:1234),
> > > > > HeapBuffer[pos=0 lim=4 cap=2048: 00 00 00 00]
> > > > > Received: (datagram, server, /10.0.0.120:5678 => /0.0.0.0:1234),
> > > > > HeapBuffer[pos=0 lim=4 cap=2048: 00 00 00 00]
> > > > > unbound
> > > > > Closed: (datagram, server, /10.0.0.120:5678 => /0.0.0.0:1234)
> > > > >
> > > > > Maarten
> > > > >
> > > > > On 9/18/07, Maarten Bosteels <mbosteels.dns@gmail.com > wrote:
> > > > > >
> > > > > > On linux 2.6.9, jdk 1.6
> > > > > >
> > > > > > Local host: mortimer/172.30.6.12
> > > > > > Open: (datagram, server, /172.30.6.12:5678 => /0:0:0:0:0:0:0:0:1234)
> > > > > > Received: (datagram, server, /172.30.6.12:5678 =>
> > > > /0:0:0:0:0:0:0:0:1234),
> > > > > > HeapBuffer[pos=0 lim=1 cap=2048: 00]
> > > > > > Received: (datagram, server, /172.30.6.12:5678 =>
> > > > /0:0:0:0:0:0:0:0:1234),
> > > > > > HeapBuffer[pos=0 lim=2 cap=2048: 00 00]
> > > > > > Received: (datagram, server, /172.30.6.12:5678 =>
> > > > /0:0:0:0:0:0:0:0:1234),
> > > > > > HeapBuffer[pos=0 lim=3 cap=2048: 00 00 00]
> > > > > > Received: (datagram, server, /172.30.6.12:5678 =>
> > > > /0:0:0:0:0:0:0:0:1234),
> > > > > > HeapBuffer[pos=0 lim=4 cap=2048: 00 00 00 00]
> > > > > > unbound
> > > > > > Closed: (datagram, server, /172.30.6.12:5678 =>
> > > > /0:0:0:0:0:0:0:0:1234)
> > > > > >
> > > > > > Adding a virtual interface (eth0:0) doesn't make a difference.
> > > > > > Maarten
> > > > > >
> > > > > > On 9/18/07, Maarten Bosteels < mbosteels.dns@gmail.com> wrote:
> > > > > > >
> > > > > > > Hello Trustin,
> > > > > > >
> > > > > > > I ran the code on Windows XP jdk 1.6 , and this is the output I
> > > > got:
> > > > > > >
> > > > > > > Local host: kweenie/172.29.100.104
> > > > > > > Open: (datagram, server, /172.29.100.104:5678 => /0.0.0.0:1234)
> > > > > > > Received: (datagram, server, /172.29.100.104:5678 =>
> > > > /0.0.0.0:1234),
> > > > > > > HeapBuffer[pos=0 lim=2 cap=2048: 00 00]
> > > > > > > Received: (datagram, server, /172.29.100.104:5678 =>
> > > > /0.0.0.0:1234),
> > > > > > > HeapBuffer[pos=0 lim=1 cap=2048: 00]
> > > > > > > Received: (datagram, server, /172.29.100.104:5678 =>
> > > > /0.0.0.0:1234),
> > > > > > > HeapBuffer[pos=0 lim=3 cap=2048: 00 00 00]
> > > > > > > Received: (datagram, server, /172.29.100.104:5678 =>
> > > > /0.0.0.0:1234),
> > > > > > > HeapBuffer[pos=0 lim=3 cap=2048: 00 00 00]
> > > > > > > Received: (datagram, server, /172.29.100.104:5678 =>
> > > > /0.0.0.0:1234),
> > > > > > > HeapBuffer[pos=0 lim=3 cap=2048: 00 00 00]
> > > > > > > Received: (datagram, server, /172.29.100.104:5678 =>
> > > > /0.0.0.0:1234),
> > > > > > > HeapBuffer[pos=0 lim=3 cap=2048: 00 00 00]
> > > > > > > Received: (datagram, server, /172.29.100.104:5678 =>
> > > > /0.0.0.0:1234),
> > > > > > > HeapBuffer[pos=0 lim=4 cap=2048: 00 00 00 00]
> > > > > > > Received: (datagram, server, /172.29.100.104:5678 =>
> > > > /0.0.0.0:1234),
> > > > > > > HeapBuffer[pos=0 lim=4 cap=2048: 00 00 00 00]
> > > > > > > Received: (datagram, server, /172.29.100.104:5678 =>
> > > > /0.0.0.0:1234),
> > > > > > > HeapBuffer[pos=0 lim=4 cap=2048: 00 00 00 00]
> > > > > > > Received: (datagram, server, /172.29.100.104:5678 =>
> > > > /0.0.0.0:1234),
> > > > > > > HeapBuffer[pos=0 lim=4 cap=2048: 00 00 00 00]
> > > > > > > Closed: (datagram, server, /172.29.100.104:5678 => /0.0.0.0:1234)
> > > > > > > unbound
> > > > > > >
> > > > > > > I changed the code a little bit, to be able to distinguish the
> > > > messages.
> > > > > > >
> > > > > > > Also added a sleep before the unbind, (I think there's one line
> > > > missing
> > > > > > > in your output :-)
> > > > > > >
> > > > > > >        f1.getSession().write(ByteBuffer.allocate (1)).await();
> > > > > > >        f1.getSession().write( ByteBuffer.allocate(2)).await();
> > > > > > >
> > > > > > >        f2.getSession().write(ByteBuffer.allocate(3)).await();
> > > > > > >        f2.getSession ().write(ByteBuffer.allocate(4)).await();
> > > > > > >
> > > > > > >        Thread.sleep(2000);
> > > > > > >        acceptor.unbind();
> > > > > > >        System.out.println ("unbound");
> > > > > > >         System.exit(0);
> > > > > > >
> > > > > > > The messages sent to the broadcast address are received multiple
> > > > times:
> > > > > > > twice per enabled network connection.
> > > > > > > When I enable all 4 network interfaces (LAN, wireless LAN and two
> > > > > > > virtual ones for VMWare) I receive them 8 times !
> > > > > > >
> > > > > > > Maarten
> > > > > > >
> > > > > > > On 9/17/07, Trustin Lee < trustin@gmail.com > wrote:
> > > > > > > >
> > > > > > > > Hi,
> > > > > > > >
> > > > > > > > I made a lot of changes to the current datagram implementation
> > > > in
> > > > > > > > trunk.  DatagramAcceptor now collaborates with DatagramConnector
> > > > to
> > > > > > > > create connected datagram socket which listens to the remote
> > > > address
> > > > > > > > of the received packet.  The following is simplified description
> > > > of
> > > > > > > > flow:
> > > > > > > >
> > > > > > > > * DatagramAcceptor's underlying DatagramChannel.receive is
> > > > invoked
> > > > > > > > * Once data is received, new connected datagram session is
> > > > created
> > > > > > > > using DatagramConnector.connect (receivedRemoteAddress,
> > > > > > > > acceptor.getLocalAddress()).  If there's already a session
> > > > instance
> > > > > > > > associated with the remote address, it's reused.
> > > > > > > >
> > > > > > > > The advantages of this implementation are:
> > > > > > > >
> > > > > > > > * The acceptor-side datagram sessions can perform much better in
> > > > > > > > multi-core environment.
> > > > > > > > * There's no need for IoSessionRecycler on the acceptor-side
> > > > anymore.
> > > > > > > > You have full control over disconnection; probably using
> > > > sessionIdle
> > > > > > > > event in most cases.
> > > > > > > > * Code duplication can be reduced once again, and most part of
> > > > the
> > > > > > > > existing acceptor code can be extracted into a generic acceptor
> > > > > > > > implementation.
> > > > > > > >
> > > > > > > > The disadvantage is that it forces you to set reuseAddress to
> > > > true,
> > > > > > > > because multiple datagram channels are bound to the same local
> > > > > > > > address.
> > > > > > > >
> > > > > > > > In Linux, connected datagram channels have priority over
> > > > unconnected
> > > > > > > > channels, so most traffic will go directly into
> > > > DatagramConnector's
> > > > > > > > NIOProcessors.  The only exception I've found is broadcast
> > > > packets. It
> > > > > > > > is always received from the unconnected channel in
> > > > DatagramAcceptor.
> > > > > > > > DatagramAcceptor immediately forwards the event to an
> > > > appropriate
> > > > > > > > session that DatagramConnector is managing, or creates a new
> > > > session
> > > > > > > > using connect().
> > > > > > > >
> > > > > > > > I think this behavior won't have any big differences among
> > > > different
> > > > > > > > platforms (e.g. Windows and SUNOS).  As long as multiple
> > > > datagram
> > > > > > > > channels can be bound to the same local address, this
> > > > implementation
> > > > > > > > should work fine.  To make this sure, please run the following
> > > > test
> > > > > > > > code in your machine, and let me know what the result is:
> > > > > > > >
> > > > > > > > -------- CODE BEGINS --------
> > > > > > > > package net.gleamynode.tmp;
> > > > > > > >
> > > > > > > > import java.net.InetAddress;
> > > > > > > > import java.net.InetSocketAddress;
> > > > > > > >
> > > > > > > > import org.apache.mina.common.ByteBuffer;
> > > > > > > > import org.apache.mina.common.ConnectFuture;
> > > > > > > > import org.apache.mina.common.IoHandlerAdapter ;
> > > > > > > > import org.apache.mina.common.IoSession;
> > > > > > > > import org.apache.mina.transport.socket.nio.DatagramAcceptor;
> > > > > > > > import org.apache.mina.transport.socket.nio.DatagramConnector ;
> > > > > > > >
> > > > > > > > public class Main {
> > > > > > > >
> > > > > > > >     private static final int SERVER_PORT = 1234;
> > > > > > > >     private static final int CLIENT_PORT = 5678;
> > > > > > > >
> > > > > > > >     public static void main(String args[]) throws Exception {
> > > > > > > >         DatagramAcceptor acceptor = new DatagramAcceptor();
> > > > > > > >         acceptor.setLocalAddress (new
> > > > InetSocketAddress(SERVER_PORT));
> > > > > > > >
> > > > > > > >         acceptor.setHandler(new IoHandlerAdapter() {
> > > > > > > >             @Override
> > > > > > > >             public void sessionOpened(IoSession session) {
> > > > > > > >                 System.out.println("Open: " + session);
> > > > > > > >             }
> > > > > > > >
> > > > > > > >             @Override
> > > > > > > >             public void sessionClosed(IoSession session) {
> > > > > > > >                 System.out.println("Closed: " + session);
> > > > > > > >             }
> > > > > > > >
> > > > > > > >             @Override
> > > > > > > >             public void messageReceived(IoSession session,
> > > > Object o) {
> > > > > > > >
> > > > > > > >                 System.out.println("Received: " + session + ", "
> > > > + o);
> > > > > > > >             }
> > > > > > > >         });
> > > > > > > >         acceptor.bind();
> > > > > > > >
> > > > > > > >         DatagramConnector connector = new DatagramConnector();
> > > > > > > >         connector.getSessionConfig().setReuseAddress(true);
> > > > > > > >         connector.setHandler(new IoHandlerAdapter() {
> > > > > > > >             @Override
> > > > > > > >             public void messageReceived(IoSession session,
> > > > Object o) {
> > > > > > > >                 System.out.println("ERR?");
> > > > > > > >             }
> > > > > > > >         });
> > > > > > > >
> > > > > > > >         // Print the local host.
> > > > > > > >         System.out.println ("Local host: " +
> > > > InetAddress.getLocalHost
> > > > > > > > ());
> > > > > > > >
> > > > > > > >         // Try point-to-point.
> > > > > > > >         ConnectFuture f1 = connector.connect (
> > > > > > > >                 new InetSocketAddress(
> > > > > > > >                         InetAddress.getLocalHost(),
> > > > SERVER_PORT),
> > > > > > > >                 new InetSocketAddress(
> > > > > > > >                           InetAddress.getLocalHost(),
> > > > CLIENT_PORT));
> > > > > > > >         f1.await();
> > > > > > > >
> > > > > > > >
> > > > > > > >         f1.getSession().write(ByteBuffer.allocate(1)).await();
> > > > > > > >         f1.getSession().write(ByteBuffer.allocate(1)).await();
> > > > > > > >
> > > > > > > >
> > > > > > > >         // Try broadcast.
> > > > > > > >         ConnectFuture f2 = connector.connect(
> > > > > > > >                 new InetSocketAddress(
> > > > > > > >                         " 255.255.255.255", SERVER_PORT),
> > > > > > > >                 new InetSocketAddress(
> > > > > > > >                         InetAddress.getLocalHost(),
> > > > CLIENT_PORT));
> > > > > > > >
> > > > > > > >         f2.await();
> > > > > > > >         f2.getSession().write(ByteBuffer.allocate (1)).await();
> > > > > > > >         f2.getSession().write(ByteBuffer.allocate(1)).await();
> > > > > > > >
> > > > > > > >         acceptor.unbind();
> > > > > > > >
> > > > > > > >         System.exit(0);
> > > > > > > >     }
> > > > > > > > }
> > > > > > > > -------- CODE ENDS --------
> > > > > > > >
> > > > > > > > The expected result is:
> > > > > > > >
> > > > > > > > -------- RESULT BEGINS --------
> > > > > > > > Local host: primary/127.0.0.1
> > > > > > > > Open: (datagram, server, /127.0.0.1:5678 =>
> > > > /0:0:0:0:0:0:0:0:1234)
> > > > > > > > Received: (datagram, server, /127.0.0.1:5678 =>
> > > > > > > > /0:0:0:0:0:0:0:0:1234), HeapBuffer[pos=0 lim=1 cap=2048: 00]
> > > > > > > > Received: (datagram, server, /127.0.0.1:5678 =>
> > > > > > > > /0:0:0:0:0:0:0:0:1234), HeapBuffer[pos=0 lim=1 cap=2048: 00]
> > > > > > > > Received: (datagram, server, /127.0.0.1:5678 =>
> > > > > > > > /0:0:0:0:0:0:0:0:1234), HeapBuffer[pos=0 lim=1 cap=2048: 00]
> > > > > > > > Closed: (datagram, server, /127.0.0.1:5678 =>
> > > > /0:0:0:0:0:0:0:0:1234)
> > > > > > > > -------- RESULT ENDS --------
> > > > > > > >
> > > > > > > > If this test fails on any platform that runs Java 5, I am doomed
> > > > to
> > > > > > > > revert my changes. :)
> > > > > > > >
> > > > > > > > Trustin
> > > > > > > > --
> > > > > > > > what we call human nature is actually human habit
> > > > > > > > --
> > > > > > > > http://gleamynode.net/
> > > > > > > > --
> > > > > > > > PGP Key ID: 0x0255ECA6
> > > > > > > >
> > > > > > >
> > > > > > >
> > > > > >
> > > > >
> > > >
> > > >
> > > > --
> > > > what we call human nature is actually human habit
> > > > --
> > > > http://gleamynode.net/
> > > > --
> > > > PGP Key ID: 0x0255ECA6
> > > >
> > >
> > >
> >
>
>
> --
> what we call human nature is actually human habit
> --
> http://gleamynode.net/
> --
> PGP Key ID: 0x0255ECA6
>


-- 
what we call human nature is actually human habit
--
http://gleamynode.net/
--
PGP Key ID: 0x0255ECA6

Re: Request for a test on various platforms:

Posted by Trustin Lee <tr...@gmail.com>.
It seems like each broadcast packet is broadcasted as many times as
the number of network interface cards in Windows and SunOS.  It's
interesting that Linux doesn't.  Maarten, did I understand correctly?

I'd like to find a way to suppress the duplicate event emission, but
don't have any idea yet.

Thanks,
Trustin

On 9/18/07, Maarten Bosteels <mb...@gmail.com> wrote:
> Also tested it on a Solaris box  with just one network interface:
>
> [root@mercury tmp]$ ifconfig -a
> lo0: flags=2001000849<UP,LOOPBACK,RUNNING,MULTICAST,IPv4,VIRTUAL> mtu 8232
> index 1
>         inet 127.0.0.1 netmask ff000000
> hme0: flags=1000843<UP,BROADCAST,RUNNING,MULTICAST,IPv4> mtu 1500 index 2
>         inet 172.30.0.139 netmask ffff0000 broadcast 172.30.255.255
>         ether 8:0:20:e6:85:18
> [root@mercury tmp]$
> [root@mercury tmp]$ uname -a
> SunOS mercury 5.10 Generic_118833-24 sun4u sparc SUNW,Ultra-250
> [root@mercury tmp]$
> [root@mercury tmp]$ java -cp mina-core-2.0.0-M1-SNAPSHOT.jar:. TestTrustin
> Local host: mercury/172.30.0.139
> Open: (datagram, server, /172.30.0.139:5678 => /0.0.0.0:1234)
> Received: (datagram, server, /172.30.0.139:5678 => /0.0.0.0:1234),
> HeapBuffer[pos=0 lim=1 cap=2048: 00]
> Received: (datagram, server, /172.30.0.139:5678 => /0.0.0.0:1234),
> HeapBuffer[pos=0 lim=2 cap=2048: 00 00]
> Received: (datagram, server, /172.30.0.139:5678 => /0.0.0.0:1234),
> HeapBuffer[pos=0 lim=3 cap=2048: 00 00 00]
> Received: (datagram, server, /172.30.0.139:5678 => /0.0.0.0:1234),
> HeapBuffer[pos=0 lim=4 cap=2048: 00 00 00 00]
> unbound
> Closed: (datagram, server, /172.30.0.139:5678 => /0.0.0.0:1234)
> [root@mercury tmp]$
>
> Maarten
>
> On 9/18/07, Maarten Bosteels <mb...@gmail.com> wrote:
> >
> > On 9/18/07, Trustin Lee <tr...@gmail.com> wrote:
> > >
> > > How many network devices exist in SunOS?
> >
> >
> >
> > root@mysun # ifconfig -a
> > lo0: flags=2001000849<UP,LOOPBACK,RUNNING,MULTICAST,IPv4,VIRTUAL> mtu 8232
> > index 1
> >         inet 127.0.0.1 netmask ff000000
> > ce0: flags=1000843<UP,BROADCAST,RUNNING,MULTICAST,IPv4> mtu 1500 index 2
> >         inet 192.168.113.8 netmask ffffff00 broadcast 192.168.113.255
> >         ether 0:14:4f:17:d:de
> > ce1: flags=1000802<BROADCAST,MULTICAST,IPv4> mtu 1500 index 3
> >         inet 0.0.0.0 netmask 0
> >         ether 0:14:4f:17:d:df
> > ce2: flags=1000802<BROADCAST,MULTICAST,IPv4> mtu 1500 index 4
> >         inet 0.0.0.0 netmask 0
> >         ether 0:14:4f:17:d:e0
> > eri0: flags=1000843<UP,BROADCAST,RUNNING,MULTICAST,IPv4> mtu 1500 index 5
> >         inet 10.0.0.120 netmask ffffff00 broadcast 10.0.0.255
> >         ether 0:3:ba:b0:49:65
> > eri0:1: flags=1040843<UP,BROADCAST,RUNNING,MULTICAST,DEPRECATED,IPv4> mtu
> > 1500 index 5
> >         inet 10.0.0.130 netmask ffffff00 broadcast 10.0.0.255
> >
> > Maarten
> >
> > Thanks!
> > > Trustin
> > >
> > > On 9/18/07, Maarten Bosteels <mb...@gmail.com> wrote:
> > > > On SunOS 5.10  sun4u sparc SUNW,Sun-Fire-V890
> > > >
> > > > java version " 1.5.0_01"
> > > > Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0_01-b08)
> > > > Java HotSpot(TM) Server VM (build 1.5.0_01-b08, mixed mode)
> > > >
> > > > Open: (datagram, server, /10.0.0.120:5678 => /0.0.0.0:1234)
> > > > Received: (datagram, server, /10.0.0.120:5678 => /0.0.0.0:1234),
> > > > HeapBuffer[pos=0 lim=1 cap=2048: 00]
> > > > Received: (datagram, server, /10.0.0.120:5678 => /0.0.0.0:1234),
> > > > HeapBuffer[pos=0 lim=2 cap=2048: 00 00]
> > > > Received: (datagram, server, /10.0.0.120:5678 => /0.0.0.0:1234),
> > > > HeapBuffer[pos=0 lim=3 cap=2048: 00 00 00]
> > > > Received: (datagram, server, /10.0.0.120:5678 => /0.0.0.0:1234),
> > > > HeapBuffer[pos=0 lim=3 cap=2048: 00 00 00]
> > > > Received: (datagram, server, /10.0.0.120:5678 => /0.0.0.0:1234),
> > > > HeapBuffer[pos=0 lim=4 cap=2048: 00 00 00 00]
> > > > Received: (datagram, server, /10.0.0.120:5678 => /0.0.0.0:1234),
> > > > HeapBuffer[pos=0 lim=4 cap=2048: 00 00 00 00]
> > > > unbound
> > > > Closed: (datagram, server, /10.0.0.120:5678 => /0.0.0.0:1234)
> > > >
> > > > Maarten
> > > >
> > > > On 9/18/07, Maarten Bosteels <mbosteels.dns@gmail.com > wrote:
> > > > >
> > > > > On linux 2.6.9, jdk 1.6
> > > > >
> > > > > Local host: mortimer/172.30.6.12
> > > > > Open: (datagram, server, /172.30.6.12:5678 => /0:0:0:0:0:0:0:0:1234)
> > > > > Received: (datagram, server, /172.30.6.12:5678 =>
> > > /0:0:0:0:0:0:0:0:1234),
> > > > > HeapBuffer[pos=0 lim=1 cap=2048: 00]
> > > > > Received: (datagram, server, /172.30.6.12:5678 =>
> > > /0:0:0:0:0:0:0:0:1234),
> > > > > HeapBuffer[pos=0 lim=2 cap=2048: 00 00]
> > > > > Received: (datagram, server, /172.30.6.12:5678 =>
> > > /0:0:0:0:0:0:0:0:1234),
> > > > > HeapBuffer[pos=0 lim=3 cap=2048: 00 00 00]
> > > > > Received: (datagram, server, /172.30.6.12:5678 =>
> > > /0:0:0:0:0:0:0:0:1234),
> > > > > HeapBuffer[pos=0 lim=4 cap=2048: 00 00 00 00]
> > > > > unbound
> > > > > Closed: (datagram, server, /172.30.6.12:5678 =>
> > > /0:0:0:0:0:0:0:0:1234)
> > > > >
> > > > > Adding a virtual interface (eth0:0) doesn't make a difference.
> > > > > Maarten
> > > > >
> > > > > On 9/18/07, Maarten Bosteels < mbosteels.dns@gmail.com> wrote:
> > > > > >
> > > > > > Hello Trustin,
> > > > > >
> > > > > > I ran the code on Windows XP jdk 1.6 , and this is the output I
> > > got:
> > > > > >
> > > > > > Local host: kweenie/172.29.100.104
> > > > > > Open: (datagram, server, /172.29.100.104:5678 => /0.0.0.0:1234)
> > > > > > Received: (datagram, server, /172.29.100.104:5678 =>
> > > /0.0.0.0:1234),
> > > > > > HeapBuffer[pos=0 lim=2 cap=2048: 00 00]
> > > > > > Received: (datagram, server, /172.29.100.104:5678 =>
> > > /0.0.0.0:1234),
> > > > > > HeapBuffer[pos=0 lim=1 cap=2048: 00]
> > > > > > Received: (datagram, server, /172.29.100.104:5678 =>
> > > /0.0.0.0:1234),
> > > > > > HeapBuffer[pos=0 lim=3 cap=2048: 00 00 00]
> > > > > > Received: (datagram, server, /172.29.100.104:5678 =>
> > > /0.0.0.0:1234),
> > > > > > HeapBuffer[pos=0 lim=3 cap=2048: 00 00 00]
> > > > > > Received: (datagram, server, /172.29.100.104:5678 =>
> > > /0.0.0.0:1234),
> > > > > > HeapBuffer[pos=0 lim=3 cap=2048: 00 00 00]
> > > > > > Received: (datagram, server, /172.29.100.104:5678 =>
> > > /0.0.0.0:1234),
> > > > > > HeapBuffer[pos=0 lim=3 cap=2048: 00 00 00]
> > > > > > Received: (datagram, server, /172.29.100.104:5678 =>
> > > /0.0.0.0:1234),
> > > > > > HeapBuffer[pos=0 lim=4 cap=2048: 00 00 00 00]
> > > > > > Received: (datagram, server, /172.29.100.104:5678 =>
> > > /0.0.0.0:1234),
> > > > > > HeapBuffer[pos=0 lim=4 cap=2048: 00 00 00 00]
> > > > > > Received: (datagram, server, /172.29.100.104:5678 =>
> > > /0.0.0.0:1234),
> > > > > > HeapBuffer[pos=0 lim=4 cap=2048: 00 00 00 00]
> > > > > > Received: (datagram, server, /172.29.100.104:5678 =>
> > > /0.0.0.0:1234),
> > > > > > HeapBuffer[pos=0 lim=4 cap=2048: 00 00 00 00]
> > > > > > Closed: (datagram, server, /172.29.100.104:5678 => /0.0.0.0:1234)
> > > > > > unbound
> > > > > >
> > > > > > I changed the code a little bit, to be able to distinguish the
> > > messages.
> > > > > >
> > > > > > Also added a sleep before the unbind, (I think there's one line
> > > missing
> > > > > > in your output :-)
> > > > > >
> > > > > >        f1.getSession().write(ByteBuffer.allocate (1)).await();
> > > > > >        f1.getSession().write( ByteBuffer.allocate(2)).await();
> > > > > >
> > > > > >        f2.getSession().write(ByteBuffer.allocate(3)).await();
> > > > > >        f2.getSession ().write(ByteBuffer.allocate(4)).await();
> > > > > >
> > > > > >        Thread.sleep(2000);
> > > > > >        acceptor.unbind();
> > > > > >        System.out.println ("unbound");
> > > > > >         System.exit(0);
> > > > > >
> > > > > > The messages sent to the broadcast address are received multiple
> > > times:
> > > > > > twice per enabled network connection.
> > > > > > When I enable all 4 network interfaces (LAN, wireless LAN and two
> > > > > > virtual ones for VMWare) I receive them 8 times !
> > > > > >
> > > > > > Maarten
> > > > > >
> > > > > > On 9/17/07, Trustin Lee < trustin@gmail.com > wrote:
> > > > > > >
> > > > > > > Hi,
> > > > > > >
> > > > > > > I made a lot of changes to the current datagram implementation
> > > in
> > > > > > > trunk.  DatagramAcceptor now collaborates with DatagramConnector
> > > to
> > > > > > > create connected datagram socket which listens to the remote
> > > address
> > > > > > > of the received packet.  The following is simplified description
> > > of
> > > > > > > flow:
> > > > > > >
> > > > > > > * DatagramAcceptor's underlying DatagramChannel.receive is
> > > invoked
> > > > > > > * Once data is received, new connected datagram session is
> > > created
> > > > > > > using DatagramConnector.connect (receivedRemoteAddress,
> > > > > > > acceptor.getLocalAddress()).  If there's already a session
> > > instance
> > > > > > > associated with the remote address, it's reused.
> > > > > > >
> > > > > > > The advantages of this implementation are:
> > > > > > >
> > > > > > > * The acceptor-side datagram sessions can perform much better in
> > > > > > > multi-core environment.
> > > > > > > * There's no need for IoSessionRecycler on the acceptor-side
> > > anymore.
> > > > > > > You have full control over disconnection; probably using
> > > sessionIdle
> > > > > > > event in most cases.
> > > > > > > * Code duplication can be reduced once again, and most part of
> > > the
> > > > > > > existing acceptor code can be extracted into a generic acceptor
> > > > > > > implementation.
> > > > > > >
> > > > > > > The disadvantage is that it forces you to set reuseAddress to
> > > true,
> > > > > > > because multiple datagram channels are bound to the same local
> > > > > > > address.
> > > > > > >
> > > > > > > In Linux, connected datagram channels have priority over
> > > unconnected
> > > > > > > channels, so most traffic will go directly into
> > > DatagramConnector's
> > > > > > > NIOProcessors.  The only exception I've found is broadcast
> > > packets. It
> > > > > > > is always received from the unconnected channel in
> > > DatagramAcceptor.
> > > > > > > DatagramAcceptor immediately forwards the event to an
> > > appropriate
> > > > > > > session that DatagramConnector is managing, or creates a new
> > > session
> > > > > > > using connect().
> > > > > > >
> > > > > > > I think this behavior won't have any big differences among
> > > different
> > > > > > > platforms (e.g. Windows and SUNOS).  As long as multiple
> > > datagram
> > > > > > > channels can be bound to the same local address, this
> > > implementation
> > > > > > > should work fine.  To make this sure, please run the following
> > > test
> > > > > > > code in your machine, and let me know what the result is:
> > > > > > >
> > > > > > > -------- CODE BEGINS --------
> > > > > > > package net.gleamynode.tmp;
> > > > > > >
> > > > > > > import java.net.InetAddress;
> > > > > > > import java.net.InetSocketAddress;
> > > > > > >
> > > > > > > import org.apache.mina.common.ByteBuffer;
> > > > > > > import org.apache.mina.common.ConnectFuture;
> > > > > > > import org.apache.mina.common.IoHandlerAdapter ;
> > > > > > > import org.apache.mina.common.IoSession;
> > > > > > > import org.apache.mina.transport.socket.nio.DatagramAcceptor;
> > > > > > > import org.apache.mina.transport.socket.nio.DatagramConnector ;
> > > > > > >
> > > > > > > public class Main {
> > > > > > >
> > > > > > >     private static final int SERVER_PORT = 1234;
> > > > > > >     private static final int CLIENT_PORT = 5678;
> > > > > > >
> > > > > > >     public static void main(String args[]) throws Exception {
> > > > > > >         DatagramAcceptor acceptor = new DatagramAcceptor();
> > > > > > >         acceptor.setLocalAddress (new
> > > InetSocketAddress(SERVER_PORT));
> > > > > > >
> > > > > > >         acceptor.setHandler(new IoHandlerAdapter() {
> > > > > > >             @Override
> > > > > > >             public void sessionOpened(IoSession session) {
> > > > > > >                 System.out.println("Open: " + session);
> > > > > > >             }
> > > > > > >
> > > > > > >             @Override
> > > > > > >             public void sessionClosed(IoSession session) {
> > > > > > >                 System.out.println("Closed: " + session);
> > > > > > >             }
> > > > > > >
> > > > > > >             @Override
> > > > > > >             public void messageReceived(IoSession session,
> > > Object o) {
> > > > > > >
> > > > > > >                 System.out.println("Received: " + session + ", "
> > > + o);
> > > > > > >             }
> > > > > > >         });
> > > > > > >         acceptor.bind();
> > > > > > >
> > > > > > >         DatagramConnector connector = new DatagramConnector();
> > > > > > >         connector.getSessionConfig().setReuseAddress(true);
> > > > > > >         connector.setHandler(new IoHandlerAdapter() {
> > > > > > >             @Override
> > > > > > >             public void messageReceived(IoSession session,
> > > Object o) {
> > > > > > >                 System.out.println("ERR?");
> > > > > > >             }
> > > > > > >         });
> > > > > > >
> > > > > > >         // Print the local host.
> > > > > > >         System.out.println ("Local host: " +
> > > InetAddress.getLocalHost
> > > > > > > ());
> > > > > > >
> > > > > > >         // Try point-to-point.
> > > > > > >         ConnectFuture f1 = connector.connect (
> > > > > > >                 new InetSocketAddress(
> > > > > > >                         InetAddress.getLocalHost(),
> > > SERVER_PORT),
> > > > > > >                 new InetSocketAddress(
> > > > > > >                           InetAddress.getLocalHost(),
> > > CLIENT_PORT));
> > > > > > >         f1.await();
> > > > > > >
> > > > > > >
> > > > > > >         f1.getSession().write(ByteBuffer.allocate(1)).await();
> > > > > > >         f1.getSession().write(ByteBuffer.allocate(1)).await();
> > > > > > >
> > > > > > >
> > > > > > >         // Try broadcast.
> > > > > > >         ConnectFuture f2 = connector.connect(
> > > > > > >                 new InetSocketAddress(
> > > > > > >                         " 255.255.255.255", SERVER_PORT),
> > > > > > >                 new InetSocketAddress(
> > > > > > >                         InetAddress.getLocalHost(),
> > > CLIENT_PORT));
> > > > > > >
> > > > > > >         f2.await();
> > > > > > >         f2.getSession().write(ByteBuffer.allocate (1)).await();
> > > > > > >         f2.getSession().write(ByteBuffer.allocate(1)).await();
> > > > > > >
> > > > > > >         acceptor.unbind();
> > > > > > >
> > > > > > >         System.exit(0);
> > > > > > >     }
> > > > > > > }
> > > > > > > -------- CODE ENDS --------
> > > > > > >
> > > > > > > The expected result is:
> > > > > > >
> > > > > > > -------- RESULT BEGINS --------
> > > > > > > Local host: primary/127.0.0.1
> > > > > > > Open: (datagram, server, /127.0.0.1:5678 =>
> > > /0:0:0:0:0:0:0:0:1234)
> > > > > > > Received: (datagram, server, /127.0.0.1:5678 =>
> > > > > > > /0:0:0:0:0:0:0:0:1234), HeapBuffer[pos=0 lim=1 cap=2048: 00]
> > > > > > > Received: (datagram, server, /127.0.0.1:5678 =>
> > > > > > > /0:0:0:0:0:0:0:0:1234), HeapBuffer[pos=0 lim=1 cap=2048: 00]
> > > > > > > Received: (datagram, server, /127.0.0.1:5678 =>
> > > > > > > /0:0:0:0:0:0:0:0:1234), HeapBuffer[pos=0 lim=1 cap=2048: 00]
> > > > > > > Closed: (datagram, server, /127.0.0.1:5678 =>
> > > /0:0:0:0:0:0:0:0:1234)
> > > > > > > -------- RESULT ENDS --------
> > > > > > >
> > > > > > > If this test fails on any platform that runs Java 5, I am doomed
> > > to
> > > > > > > revert my changes. :)
> > > > > > >
> > > > > > > Trustin
> > > > > > > --
> > > > > > > what we call human nature is actually human habit
> > > > > > > --
> > > > > > > http://gleamynode.net/
> > > > > > > --
> > > > > > > PGP Key ID: 0x0255ECA6
> > > > > > >
> > > > > >
> > > > > >
> > > > >
> > > >
> > >
> > >
> > > --
> > > what we call human nature is actually human habit
> > > --
> > > http://gleamynode.net/
> > > --
> > > PGP Key ID: 0x0255ECA6
> > >
> >
> >
>


-- 
what we call human nature is actually human habit
--
http://gleamynode.net/
--
PGP Key ID: 0x0255ECA6

Re: Request for a test on various platforms:

Posted by Maarten Bosteels <mb...@gmail.com>.
Also tested it on a Solaris box  with just one network interface:

[root@mercury tmp]$ ifconfig -a
lo0: flags=2001000849<UP,LOOPBACK,RUNNING,MULTICAST,IPv4,VIRTUAL> mtu 8232
index 1
        inet 127.0.0.1 netmask ff000000
hme0: flags=1000843<UP,BROADCAST,RUNNING,MULTICAST,IPv4> mtu 1500 index 2
        inet 172.30.0.139 netmask ffff0000 broadcast 172.30.255.255
        ether 8:0:20:e6:85:18
[root@mercury tmp]$
[root@mercury tmp]$ uname -a
SunOS mercury 5.10 Generic_118833-24 sun4u sparc SUNW,Ultra-250
[root@mercury tmp]$
[root@mercury tmp]$ java -cp mina-core-2.0.0-M1-SNAPSHOT.jar:. TestTrustin
Local host: mercury/172.30.0.139
Open: (datagram, server, /172.30.0.139:5678 => /0.0.0.0:1234)
Received: (datagram, server, /172.30.0.139:5678 => /0.0.0.0:1234),
HeapBuffer[pos=0 lim=1 cap=2048: 00]
Received: (datagram, server, /172.30.0.139:5678 => /0.0.0.0:1234),
HeapBuffer[pos=0 lim=2 cap=2048: 00 00]
Received: (datagram, server, /172.30.0.139:5678 => /0.0.0.0:1234),
HeapBuffer[pos=0 lim=3 cap=2048: 00 00 00]
Received: (datagram, server, /172.30.0.139:5678 => /0.0.0.0:1234),
HeapBuffer[pos=0 lim=4 cap=2048: 00 00 00 00]
unbound
Closed: (datagram, server, /172.30.0.139:5678 => /0.0.0.0:1234)
[root@mercury tmp]$

Maarten

On 9/18/07, Maarten Bosteels <mb...@gmail.com> wrote:
>
> On 9/18/07, Trustin Lee <tr...@gmail.com> wrote:
> >
> > How many network devices exist in SunOS?
>
>
>
> root@mysun # ifconfig -a
> lo0: flags=2001000849<UP,LOOPBACK,RUNNING,MULTICAST,IPv4,VIRTUAL> mtu 8232
> index 1
>         inet 127.0.0.1 netmask ff000000
> ce0: flags=1000843<UP,BROADCAST,RUNNING,MULTICAST,IPv4> mtu 1500 index 2
>         inet 192.168.113.8 netmask ffffff00 broadcast 192.168.113.255
>         ether 0:14:4f:17:d:de
> ce1: flags=1000802<BROADCAST,MULTICAST,IPv4> mtu 1500 index 3
>         inet 0.0.0.0 netmask 0
>         ether 0:14:4f:17:d:df
> ce2: flags=1000802<BROADCAST,MULTICAST,IPv4> mtu 1500 index 4
>         inet 0.0.0.0 netmask 0
>         ether 0:14:4f:17:d:e0
> eri0: flags=1000843<UP,BROADCAST,RUNNING,MULTICAST,IPv4> mtu 1500 index 5
>         inet 10.0.0.120 netmask ffffff00 broadcast 10.0.0.255
>         ether 0:3:ba:b0:49:65
> eri0:1: flags=1040843<UP,BROADCAST,RUNNING,MULTICAST,DEPRECATED,IPv4> mtu
> 1500 index 5
>         inet 10.0.0.130 netmask ffffff00 broadcast 10.0.0.255
>
> Maarten
>
> Thanks!
> > Trustin
> >
> > On 9/18/07, Maarten Bosteels <mb...@gmail.com> wrote:
> > > On SunOS 5.10  sun4u sparc SUNW,Sun-Fire-V890
> > >
> > > java version " 1.5.0_01"
> > > Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0_01-b08)
> > > Java HotSpot(TM) Server VM (build 1.5.0_01-b08, mixed mode)
> > >
> > > Open: (datagram, server, /10.0.0.120:5678 => /0.0.0.0:1234)
> > > Received: (datagram, server, /10.0.0.120:5678 => /0.0.0.0:1234),
> > > HeapBuffer[pos=0 lim=1 cap=2048: 00]
> > > Received: (datagram, server, /10.0.0.120:5678 => /0.0.0.0:1234),
> > > HeapBuffer[pos=0 lim=2 cap=2048: 00 00]
> > > Received: (datagram, server, /10.0.0.120:5678 => /0.0.0.0:1234),
> > > HeapBuffer[pos=0 lim=3 cap=2048: 00 00 00]
> > > Received: (datagram, server, /10.0.0.120:5678 => /0.0.0.0:1234),
> > > HeapBuffer[pos=0 lim=3 cap=2048: 00 00 00]
> > > Received: (datagram, server, /10.0.0.120:5678 => /0.0.0.0:1234),
> > > HeapBuffer[pos=0 lim=4 cap=2048: 00 00 00 00]
> > > Received: (datagram, server, /10.0.0.120:5678 => /0.0.0.0:1234),
> > > HeapBuffer[pos=0 lim=4 cap=2048: 00 00 00 00]
> > > unbound
> > > Closed: (datagram, server, /10.0.0.120:5678 => /0.0.0.0:1234)
> > >
> > > Maarten
> > >
> > > On 9/18/07, Maarten Bosteels <mbosteels.dns@gmail.com > wrote:
> > > >
> > > > On linux 2.6.9, jdk 1.6
> > > >
> > > > Local host: mortimer/172.30.6.12
> > > > Open: (datagram, server, /172.30.6.12:5678 => /0:0:0:0:0:0:0:0:1234)
> > > > Received: (datagram, server, /172.30.6.12:5678 =>
> > /0:0:0:0:0:0:0:0:1234),
> > > > HeapBuffer[pos=0 lim=1 cap=2048: 00]
> > > > Received: (datagram, server, /172.30.6.12:5678 =>
> > /0:0:0:0:0:0:0:0:1234),
> > > > HeapBuffer[pos=0 lim=2 cap=2048: 00 00]
> > > > Received: (datagram, server, /172.30.6.12:5678 =>
> > /0:0:0:0:0:0:0:0:1234),
> > > > HeapBuffer[pos=0 lim=3 cap=2048: 00 00 00]
> > > > Received: (datagram, server, /172.30.6.12:5678 =>
> > /0:0:0:0:0:0:0:0:1234),
> > > > HeapBuffer[pos=0 lim=4 cap=2048: 00 00 00 00]
> > > > unbound
> > > > Closed: (datagram, server, /172.30.6.12:5678 =>
> > /0:0:0:0:0:0:0:0:1234)
> > > >
> > > > Adding a virtual interface (eth0:0) doesn't make a difference.
> > > > Maarten
> > > >
> > > > On 9/18/07, Maarten Bosteels < mbosteels.dns@gmail.com> wrote:
> > > > >
> > > > > Hello Trustin,
> > > > >
> > > > > I ran the code on Windows XP jdk 1.6 , and this is the output I
> > got:
> > > > >
> > > > > Local host: kweenie/172.29.100.104
> > > > > Open: (datagram, server, /172.29.100.104:5678 => /0.0.0.0:1234)
> > > > > Received: (datagram, server, /172.29.100.104:5678 =>
> > /0.0.0.0:1234),
> > > > > HeapBuffer[pos=0 lim=2 cap=2048: 00 00]
> > > > > Received: (datagram, server, /172.29.100.104:5678 =>
> > /0.0.0.0:1234),
> > > > > HeapBuffer[pos=0 lim=1 cap=2048: 00]
> > > > > Received: (datagram, server, /172.29.100.104:5678 =>
> > /0.0.0.0:1234),
> > > > > HeapBuffer[pos=0 lim=3 cap=2048: 00 00 00]
> > > > > Received: (datagram, server, /172.29.100.104:5678 =>
> > /0.0.0.0:1234),
> > > > > HeapBuffer[pos=0 lim=3 cap=2048: 00 00 00]
> > > > > Received: (datagram, server, /172.29.100.104:5678 =>
> > /0.0.0.0:1234),
> > > > > HeapBuffer[pos=0 lim=3 cap=2048: 00 00 00]
> > > > > Received: (datagram, server, /172.29.100.104:5678 =>
> > /0.0.0.0:1234),
> > > > > HeapBuffer[pos=0 lim=3 cap=2048: 00 00 00]
> > > > > Received: (datagram, server, /172.29.100.104:5678 =>
> > /0.0.0.0:1234),
> > > > > HeapBuffer[pos=0 lim=4 cap=2048: 00 00 00 00]
> > > > > Received: (datagram, server, /172.29.100.104:5678 =>
> > /0.0.0.0:1234),
> > > > > HeapBuffer[pos=0 lim=4 cap=2048: 00 00 00 00]
> > > > > Received: (datagram, server, /172.29.100.104:5678 =>
> > /0.0.0.0:1234),
> > > > > HeapBuffer[pos=0 lim=4 cap=2048: 00 00 00 00]
> > > > > Received: (datagram, server, /172.29.100.104:5678 =>
> > /0.0.0.0:1234),
> > > > > HeapBuffer[pos=0 lim=4 cap=2048: 00 00 00 00]
> > > > > Closed: (datagram, server, /172.29.100.104:5678 => /0.0.0.0:1234)
> > > > > unbound
> > > > >
> > > > > I changed the code a little bit, to be able to distinguish the
> > messages.
> > > > >
> > > > > Also added a sleep before the unbind, (I think there's one line
> > missing
> > > > > in your output :-)
> > > > >
> > > > >        f1.getSession().write(ByteBuffer.allocate (1)).await();
> > > > >        f1.getSession().write( ByteBuffer.allocate(2)).await();
> > > > >
> > > > >        f2.getSession().write(ByteBuffer.allocate(3)).await();
> > > > >        f2.getSession ().write(ByteBuffer.allocate(4)).await();
> > > > >
> > > > >        Thread.sleep(2000);
> > > > >        acceptor.unbind();
> > > > >        System.out.println ("unbound");
> > > > >         System.exit(0);
> > > > >
> > > > > The messages sent to the broadcast address are received multiple
> > times:
> > > > > twice per enabled network connection.
> > > > > When I enable all 4 network interfaces (LAN, wireless LAN and two
> > > > > virtual ones for VMWare) I receive them 8 times !
> > > > >
> > > > > Maarten
> > > > >
> > > > > On 9/17/07, Trustin Lee < trustin@gmail.com > wrote:
> > > > > >
> > > > > > Hi,
> > > > > >
> > > > > > I made a lot of changes to the current datagram implementation
> > in
> > > > > > trunk.  DatagramAcceptor now collaborates with DatagramConnector
> > to
> > > > > > create connected datagram socket which listens to the remote
> > address
> > > > > > of the received packet.  The following is simplified description
> > of
> > > > > > flow:
> > > > > >
> > > > > > * DatagramAcceptor's underlying DatagramChannel.receive is
> > invoked
> > > > > > * Once data is received, new connected datagram session is
> > created
> > > > > > using DatagramConnector.connect (receivedRemoteAddress,
> > > > > > acceptor.getLocalAddress()).  If there's already a session
> > instance
> > > > > > associated with the remote address, it's reused.
> > > > > >
> > > > > > The advantages of this implementation are:
> > > > > >
> > > > > > * The acceptor-side datagram sessions can perform much better in
> > > > > > multi-core environment.
> > > > > > * There's no need for IoSessionRecycler on the acceptor-side
> > anymore.
> > > > > > You have full control over disconnection; probably using
> > sessionIdle
> > > > > > event in most cases.
> > > > > > * Code duplication can be reduced once again, and most part of
> > the
> > > > > > existing acceptor code can be extracted into a generic acceptor
> > > > > > implementation.
> > > > > >
> > > > > > The disadvantage is that it forces you to set reuseAddress to
> > true,
> > > > > > because multiple datagram channels are bound to the same local
> > > > > > address.
> > > > > >
> > > > > > In Linux, connected datagram channels have priority over
> > unconnected
> > > > > > channels, so most traffic will go directly into
> > DatagramConnector's
> > > > > > NIOProcessors.  The only exception I've found is broadcast
> > packets. It
> > > > > > is always received from the unconnected channel in
> > DatagramAcceptor.
> > > > > > DatagramAcceptor immediately forwards the event to an
> > appropriate
> > > > > > session that DatagramConnector is managing, or creates a new
> > session
> > > > > > using connect().
> > > > > >
> > > > > > I think this behavior won't have any big differences among
> > different
> > > > > > platforms (e.g. Windows and SUNOS).  As long as multiple
> > datagram
> > > > > > channels can be bound to the same local address, this
> > implementation
> > > > > > should work fine.  To make this sure, please run the following
> > test
> > > > > > code in your machine, and let me know what the result is:
> > > > > >
> > > > > > -------- CODE BEGINS --------
> > > > > > package net.gleamynode.tmp;
> > > > > >
> > > > > > import java.net.InetAddress;
> > > > > > import java.net.InetSocketAddress;
> > > > > >
> > > > > > import org.apache.mina.common.ByteBuffer;
> > > > > > import org.apache.mina.common.ConnectFuture;
> > > > > > import org.apache.mina.common.IoHandlerAdapter ;
> > > > > > import org.apache.mina.common.IoSession;
> > > > > > import org.apache.mina.transport.socket.nio.DatagramAcceptor;
> > > > > > import org.apache.mina.transport.socket.nio.DatagramConnector ;
> > > > > >
> > > > > > public class Main {
> > > > > >
> > > > > >     private static final int SERVER_PORT = 1234;
> > > > > >     private static final int CLIENT_PORT = 5678;
> > > > > >
> > > > > >     public static void main(String args[]) throws Exception {
> > > > > >         DatagramAcceptor acceptor = new DatagramAcceptor();
> > > > > >         acceptor.setLocalAddress (new
> > InetSocketAddress(SERVER_PORT));
> > > > > >
> > > > > >         acceptor.setHandler(new IoHandlerAdapter() {
> > > > > >             @Override
> > > > > >             public void sessionOpened(IoSession session) {
> > > > > >                 System.out.println("Open: " + session);
> > > > > >             }
> > > > > >
> > > > > >             @Override
> > > > > >             public void sessionClosed(IoSession session) {
> > > > > >                 System.out.println("Closed: " + session);
> > > > > >             }
> > > > > >
> > > > > >             @Override
> > > > > >             public void messageReceived(IoSession session,
> > Object o) {
> > > > > >
> > > > > >                 System.out.println("Received: " + session + ", "
> > + o);
> > > > > >             }
> > > > > >         });
> > > > > >         acceptor.bind();
> > > > > >
> > > > > >         DatagramConnector connector = new DatagramConnector();
> > > > > >         connector.getSessionConfig().setReuseAddress(true);
> > > > > >         connector.setHandler(new IoHandlerAdapter() {
> > > > > >             @Override
> > > > > >             public void messageReceived(IoSession session,
> > Object o) {
> > > > > >                 System.out.println("ERR?");
> > > > > >             }
> > > > > >         });
> > > > > >
> > > > > >         // Print the local host.
> > > > > >         System.out.println ("Local host: " +
> > InetAddress.getLocalHost
> > > > > > ());
> > > > > >
> > > > > >         // Try point-to-point.
> > > > > >         ConnectFuture f1 = connector.connect (
> > > > > >                 new InetSocketAddress(
> > > > > >                         InetAddress.getLocalHost(),
> > SERVER_PORT),
> > > > > >                 new InetSocketAddress(
> > > > > >                           InetAddress.getLocalHost(),
> > CLIENT_PORT));
> > > > > >         f1.await();
> > > > > >
> > > > > >
> > > > > >         f1.getSession().write(ByteBuffer.allocate(1)).await();
> > > > > >         f1.getSession().write(ByteBuffer.allocate(1)).await();
> > > > > >
> > > > > >
> > > > > >         // Try broadcast.
> > > > > >         ConnectFuture f2 = connector.connect(
> > > > > >                 new InetSocketAddress(
> > > > > >                         " 255.255.255.255", SERVER_PORT),
> > > > > >                 new InetSocketAddress(
> > > > > >                         InetAddress.getLocalHost(),
> > CLIENT_PORT));
> > > > > >
> > > > > >         f2.await();
> > > > > >         f2.getSession().write(ByteBuffer.allocate (1)).await();
> > > > > >         f2.getSession().write(ByteBuffer.allocate(1)).await();
> > > > > >
> > > > > >         acceptor.unbind();
> > > > > >
> > > > > >         System.exit(0);
> > > > > >     }
> > > > > > }
> > > > > > -------- CODE ENDS --------
> > > > > >
> > > > > > The expected result is:
> > > > > >
> > > > > > -------- RESULT BEGINS --------
> > > > > > Local host: primary/127.0.0.1
> > > > > > Open: (datagram, server, /127.0.0.1:5678 =>
> > /0:0:0:0:0:0:0:0:1234)
> > > > > > Received: (datagram, server, /127.0.0.1:5678 =>
> > > > > > /0:0:0:0:0:0:0:0:1234), HeapBuffer[pos=0 lim=1 cap=2048: 00]
> > > > > > Received: (datagram, server, /127.0.0.1:5678 =>
> > > > > > /0:0:0:0:0:0:0:0:1234), HeapBuffer[pos=0 lim=1 cap=2048: 00]
> > > > > > Received: (datagram, server, /127.0.0.1:5678 =>
> > > > > > /0:0:0:0:0:0:0:0:1234), HeapBuffer[pos=0 lim=1 cap=2048: 00]
> > > > > > Closed: (datagram, server, /127.0.0.1:5678 =>
> > /0:0:0:0:0:0:0:0:1234)
> > > > > > -------- RESULT ENDS --------
> > > > > >
> > > > > > If this test fails on any platform that runs Java 5, I am doomed
> > to
> > > > > > revert my changes. :)
> > > > > >
> > > > > > Trustin
> > > > > > --
> > > > > > what we call human nature is actually human habit
> > > > > > --
> > > > > > http://gleamynode.net/
> > > > > > --
> > > > > > PGP Key ID: 0x0255ECA6
> > > > > >
> > > > >
> > > > >
> > > >
> > >
> >
> >
> > --
> > what we call human nature is actually human habit
> > --
> > http://gleamynode.net/
> > --
> > PGP Key ID: 0x0255ECA6
> >
>
>

Re: Request for a test on various platforms:

Posted by Maarten Bosteels <mb...@gmail.com>.
On 9/18/07, Trustin Lee <tr...@gmail.com> wrote:
>
> How many network devices exist in SunOS?



root@mysun # ifconfig -a
lo0: flags=2001000849<UP,LOOPBACK,RUNNING,MULTICAST,IPv4,VIRTUAL> mtu 8232
index 1
        inet 127.0.0.1 netmask ff000000
ce0: flags=1000843<UP,BROADCAST,RUNNING,MULTICAST,IPv4> mtu 1500 index 2
        inet 192.168.113.8 netmask ffffff00 broadcast 192.168.113.255
        ether 0:14:4f:17:d:de
ce1: flags=1000802<BROADCAST,MULTICAST,IPv4> mtu 1500 index 3
        inet 0.0.0.0 netmask 0
        ether 0:14:4f:17:d:df
ce2: flags=1000802<BROADCAST,MULTICAST,IPv4> mtu 1500 index 4
        inet 0.0.0.0 netmask 0
        ether 0:14:4f:17:d:e0
eri0: flags=1000843<UP,BROADCAST,RUNNING,MULTICAST,IPv4> mtu 1500 index 5
        inet 10.0.0.120 netmask ffffff00 broadcast 10.0.0.255
        ether 0:3:ba:b0:49:65
eri0:1: flags=1040843<UP,BROADCAST,RUNNING,MULTICAST,DEPRECATED,IPv4> mtu
1500 index 5
        inet 10.0.0.130 netmask ffffff00 broadcast 10.0.0.255

Maarten

Thanks!
> Trustin
>
> On 9/18/07, Maarten Bosteels <mb...@gmail.com> wrote:
> > On SunOS 5.10  sun4u sparc SUNW,Sun-Fire-V890
> >
> > java version "1.5.0_01"
> > Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0_01-b08)
> > Java HotSpot(TM) Server VM (build 1.5.0_01-b08, mixed mode)
> >
> > Open: (datagram, server, /10.0.0.120:5678 => /0.0.0.0:1234)
> > Received: (datagram, server, /10.0.0.120:5678 => /0.0.0.0:1234),
> > HeapBuffer[pos=0 lim=1 cap=2048: 00]
> > Received: (datagram, server, /10.0.0.120:5678 => /0.0.0.0:1234),
> > HeapBuffer[pos=0 lim=2 cap=2048: 00 00]
> > Received: (datagram, server, /10.0.0.120:5678 => /0.0.0.0:1234),
> > HeapBuffer[pos=0 lim=3 cap=2048: 00 00 00]
> > Received: (datagram, server, /10.0.0.120:5678 => /0.0.0.0:1234),
> > HeapBuffer[pos=0 lim=3 cap=2048: 00 00 00]
> > Received: (datagram, server, /10.0.0.120:5678 => /0.0.0.0:1234),
> > HeapBuffer[pos=0 lim=4 cap=2048: 00 00 00 00]
> > Received: (datagram, server, /10.0.0.120:5678 => /0.0.0.0:1234),
> > HeapBuffer[pos=0 lim=4 cap=2048: 00 00 00 00]
> > unbound
> > Closed: (datagram, server, /10.0.0.120:5678 => /0.0.0.0:1234)
> >
> > Maarten
> >
> > On 9/18/07, Maarten Bosteels <mb...@gmail.com> wrote:
> > >
> > > On linux 2.6.9, jdk 1.6
> > >
> > > Local host: mortimer/172.30.6.12
> > > Open: (datagram, server, /172.30.6.12:5678 => /0:0:0:0:0:0:0:0:1234)
> > > Received: (datagram, server, /172.30.6.12:5678 =>
> /0:0:0:0:0:0:0:0:1234),
> > > HeapBuffer[pos=0 lim=1 cap=2048: 00]
> > > Received: (datagram, server, /172.30.6.12:5678 =>
> /0:0:0:0:0:0:0:0:1234),
> > > HeapBuffer[pos=0 lim=2 cap=2048: 00 00]
> > > Received: (datagram, server, /172.30.6.12:5678 =>
> /0:0:0:0:0:0:0:0:1234),
> > > HeapBuffer[pos=0 lim=3 cap=2048: 00 00 00]
> > > Received: (datagram, server, /172.30.6.12:5678 =>
> /0:0:0:0:0:0:0:0:1234),
> > > HeapBuffer[pos=0 lim=4 cap=2048: 00 00 00 00]
> > > unbound
> > > Closed: (datagram, server, /172.30.6.12:5678 => /0:0:0:0:0:0:0:0:1234)
> > >
> > > Adding a virtual interface (eth0:0) doesn't make a difference.
> > > Maarten
> > >
> > > On 9/18/07, Maarten Bosteels < mbosteels.dns@gmail.com> wrote:
> > > >
> > > > Hello Trustin,
> > > >
> > > > I ran the code on Windows XP jdk 1.6 , and this is the output I got:
> > > >
> > > > Local host: kweenie/172.29.100.104
> > > > Open: (datagram, server, /172.29.100.104:5678 => /0.0.0.0:1234)
> > > > Received: (datagram, server, /172.29.100.104:5678 => /0.0.0.0:1234),
> > > > HeapBuffer[pos=0 lim=2 cap=2048: 00 00]
> > > > Received: (datagram, server, /172.29.100.104:5678 => /0.0.0.0:1234),
> > > > HeapBuffer[pos=0 lim=1 cap=2048: 00]
> > > > Received: (datagram, server, /172.29.100.104:5678 => /0.0.0.0:1234),
> > > > HeapBuffer[pos=0 lim=3 cap=2048: 00 00 00]
> > > > Received: (datagram, server, /172.29.100.104:5678 => /0.0.0.0:1234),
> > > > HeapBuffer[pos=0 lim=3 cap=2048: 00 00 00]
> > > > Received: (datagram, server, /172.29.100.104:5678 => /0.0.0.0:1234),
> > > > HeapBuffer[pos=0 lim=3 cap=2048: 00 00 00]
> > > > Received: (datagram, server, /172.29.100.104:5678 => /0.0.0.0:1234),
> > > > HeapBuffer[pos=0 lim=3 cap=2048: 00 00 00]
> > > > Received: (datagram, server, /172.29.100.104:5678 => /0.0.0.0:1234),
> > > > HeapBuffer[pos=0 lim=4 cap=2048: 00 00 00 00]
> > > > Received: (datagram, server, /172.29.100.104:5678 => /0.0.0.0:1234),
> > > > HeapBuffer[pos=0 lim=4 cap=2048: 00 00 00 00]
> > > > Received: (datagram, server, /172.29.100.104:5678 => /0.0.0.0:1234),
> > > > HeapBuffer[pos=0 lim=4 cap=2048: 00 00 00 00]
> > > > Received: (datagram, server, /172.29.100.104:5678 => /0.0.0.0:1234),
> > > > HeapBuffer[pos=0 lim=4 cap=2048: 00 00 00 00]
> > > > Closed: (datagram, server, /172.29.100.104:5678 => /0.0.0.0:1234)
> > > > unbound
> > > >
> > > > I changed the code a little bit, to be able to distinguish the
> messages.
> > > >
> > > > Also added a sleep before the unbind, (I think there's one line
> missing
> > > > in your output :-)
> > > >
> > > >        f1.getSession().write(ByteBuffer.allocate(1)).await();
> > > >        f1.getSession().write( ByteBuffer.allocate(2)).await();
> > > >
> > > >        f2.getSession().write(ByteBuffer.allocate(3)).await();
> > > >        f2.getSession().write(ByteBuffer.allocate(4)).await();
> > > >
> > > >        Thread.sleep(2000);
> > > >        acceptor.unbind();
> > > >        System.out.println ("unbound");
> > > >        System.exit(0);
> > > >
> > > > The messages sent to the broadcast address are received multiple
> times:
> > > > twice per enabled network connection.
> > > > When I enable all 4 network interfaces (LAN, wireless LAN and two
> > > > virtual ones for VMWare) I receive them 8 times !
> > > >
> > > > Maarten
> > > >
> > > > On 9/17/07, Trustin Lee < trustin@gmail.com> wrote:
> > > > >
> > > > > Hi,
> > > > >
> > > > > I made a lot of changes to the current datagram implementation in
> > > > > trunk.  DatagramAcceptor now collaborates with DatagramConnector
> to
> > > > > create connected datagram socket which listens to the remote
> address
> > > > > of the received packet.  The following is simplified description
> of
> > > > > flow:
> > > > >
> > > > > * DatagramAcceptor's underlying DatagramChannel.receive is invoked
> > > > > * Once data is received, new connected datagram session is created
> > > > > using DatagramConnector.connect(receivedRemoteAddress,
> > > > > acceptor.getLocalAddress()).  If there's already a session
> instance
> > > > > associated with the remote address, it's reused.
> > > > >
> > > > > The advantages of this implementation are:
> > > > >
> > > > > * The acceptor-side datagram sessions can perform much better in
> > > > > multi-core environment.
> > > > > * There's no need for IoSessionRecycler on the acceptor-side
> anymore.
> > > > > You have full control over disconnection; probably using
> sessionIdle
> > > > > event in most cases.
> > > > > * Code duplication can be reduced once again, and most part of the
> > > > > existing acceptor code can be extracted into a generic acceptor
> > > > > implementation.
> > > > >
> > > > > The disadvantage is that it forces you to set reuseAddress to
> true,
> > > > > because multiple datagram channels are bound to the same local
> > > > > address.
> > > > >
> > > > > In Linux, connected datagram channels have priority over
> unconnected
> > > > > channels, so most traffic will go directly into
> DatagramConnector's
> > > > > NIOProcessors.  The only exception I've found is broadcast
> packets. It
> > > > > is always received from the unconnected channel in
> DatagramAcceptor.
> > > > > DatagramAcceptor immediately forwards the event to an appropriate
> > > > > session that DatagramConnector is managing, or creates a new
> session
> > > > > using connect().
> > > > >
> > > > > I think this behavior won't have any big differences among
> different
> > > > > platforms (e.g. Windows and SUNOS).  As long as multiple datagram
> > > > > channels can be bound to the same local address, this
> implementation
> > > > > should work fine.  To make this sure, please run the following
> test
> > > > > code in your machine, and let me know what the result is:
> > > > >
> > > > > -------- CODE BEGINS --------
> > > > > package net.gleamynode.tmp;
> > > > >
> > > > > import java.net.InetAddress;
> > > > > import java.net.InetSocketAddress;
> > > > >
> > > > > import org.apache.mina.common.ByteBuffer;
> > > > > import org.apache.mina.common.ConnectFuture;
> > > > > import org.apache.mina.common.IoHandlerAdapter ;
> > > > > import org.apache.mina.common.IoSession;
> > > > > import org.apache.mina.transport.socket.nio.DatagramAcceptor;
> > > > > import org.apache.mina.transport.socket.nio.DatagramConnector;
> > > > >
> > > > > public class Main {
> > > > >
> > > > >     private static final int SERVER_PORT = 1234;
> > > > >     private static final int CLIENT_PORT = 5678;
> > > > >
> > > > >     public static void main(String args[]) throws Exception {
> > > > >         DatagramAcceptor acceptor = new DatagramAcceptor();
> > > > >         acceptor.setLocalAddress (new
> InetSocketAddress(SERVER_PORT));
> > > > >
> > > > >         acceptor.setHandler(new IoHandlerAdapter() {
> > > > >             @Override
> > > > >             public void sessionOpened(IoSession session) {
> > > > >                 System.out.println("Open: " + session);
> > > > >             }
> > > > >
> > > > >             @Override
> > > > >             public void sessionClosed(IoSession session) {
> > > > >                 System.out.println("Closed: " + session);
> > > > >             }
> > > > >
> > > > >             @Override
> > > > >             public void messageReceived(IoSession session, Object
> o) {
> > > > >
> > > > >                 System.out.println("Received: " + session + ", " +
> o);
> > > > >             }
> > > > >         });
> > > > >         acceptor.bind();
> > > > >
> > > > >         DatagramConnector connector = new DatagramConnector();
> > > > >         connector.getSessionConfig().setReuseAddress(true);
> > > > >         connector.setHandler(new IoHandlerAdapter() {
> > > > >             @Override
> > > > >             public void messageReceived(IoSession session, Object
> o) {
> > > > >                 System.out.println("ERR?");
> > > > >             }
> > > > >         });
> > > > >
> > > > >         // Print the local host.
> > > > >         System.out.println("Local host: " +
> InetAddress.getLocalHost
> > > > > ());
> > > > >
> > > > >         // Try point-to-point.
> > > > >         ConnectFuture f1 = connector.connect(
> > > > >                 new InetSocketAddress(
> > > > >                         InetAddress.getLocalHost(), SERVER_PORT),
> > > > >                 new InetSocketAddress(
> > > > >                          InetAddress.getLocalHost(),
> CLIENT_PORT));
> > > > >         f1.await();
> > > > >
> > > > >
> > > > >         f1.getSession().write(ByteBuffer.allocate(1)).await();
> > > > >         f1.getSession().write(ByteBuffer.allocate(1)).await();
> > > > >
> > > > >
> > > > >         // Try broadcast.
> > > > >         ConnectFuture f2 = connector.connect(
> > > > >                 new InetSocketAddress(
> > > > >                         " 255.255.255.255", SERVER_PORT),
> > > > >                 new InetSocketAddress(
> > > > >                         InetAddress.getLocalHost(), CLIENT_PORT));
> > > > >
> > > > >         f2.await();
> > > > >         f2.getSession().write(ByteBuffer.allocate(1)).await();
> > > > >         f2.getSession().write(ByteBuffer.allocate(1)).await();
> > > > >
> > > > >         acceptor.unbind();
> > > > >
> > > > >         System.exit(0);
> > > > >     }
> > > > > }
> > > > > -------- CODE ENDS --------
> > > > >
> > > > > The expected result is:
> > > > >
> > > > > -------- RESULT BEGINS --------
> > > > > Local host: primary/127.0.0.1
> > > > > Open: (datagram, server, /127.0.0.1:5678 => /0:0:0:0:0:0:0:0:1234)
> > > > > Received: (datagram, server, /127.0.0.1:5678 =>
> > > > > /0:0:0:0:0:0:0:0:1234), HeapBuffer[pos=0 lim=1 cap=2048: 00]
> > > > > Received: (datagram, server, /127.0.0.1:5678 =>
> > > > > /0:0:0:0:0:0:0:0:1234), HeapBuffer[pos=0 lim=1 cap=2048: 00]
> > > > > Received: (datagram, server, /127.0.0.1:5678 =>
> > > > > /0:0:0:0:0:0:0:0:1234), HeapBuffer[pos=0 lim=1 cap=2048: 00]
> > > > > Closed: (datagram, server, /127.0.0.1:5678 =>
> /0:0:0:0:0:0:0:0:1234)
> > > > > -------- RESULT ENDS --------
> > > > >
> > > > > If this test fails on any platform that runs Java 5, I am doomed
> to
> > > > > revert my changes. :)
> > > > >
> > > > > Trustin
> > > > > --
> > > > > what we call human nature is actually human habit
> > > > > --
> > > > > http://gleamynode.net/
> > > > > --
> > > > > PGP Key ID: 0x0255ECA6
> > > > >
> > > >
> > > >
> > >
> >
>
>
> --
> what we call human nature is actually human habit
> --
> http://gleamynode.net/
> --
> PGP Key ID: 0x0255ECA6
>

Re: Request for a test on various platforms:

Posted by Trustin Lee <tr...@gmail.com>.
How many network devices exist in SunOS?

Thanks!
Trustin

On 9/18/07, Maarten Bosteels <mb...@gmail.com> wrote:
> On SunOS 5.10  sun4u sparc SUNW,Sun-Fire-V890
>
> java version "1.5.0_01"
> Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0_01-b08)
> Java HotSpot(TM) Server VM (build 1.5.0_01-b08, mixed mode)
>
> Open: (datagram, server, /10.0.0.120:5678 => /0.0.0.0:1234)
> Received: (datagram, server, /10.0.0.120:5678 => /0.0.0.0:1234),
> HeapBuffer[pos=0 lim=1 cap=2048: 00]
> Received: (datagram, server, /10.0.0.120:5678 => /0.0.0.0:1234),
> HeapBuffer[pos=0 lim=2 cap=2048: 00 00]
> Received: (datagram, server, /10.0.0.120:5678 => /0.0.0.0:1234),
> HeapBuffer[pos=0 lim=3 cap=2048: 00 00 00]
> Received: (datagram, server, /10.0.0.120:5678 => /0.0.0.0:1234),
> HeapBuffer[pos=0 lim=3 cap=2048: 00 00 00]
> Received: (datagram, server, /10.0.0.120:5678 => /0.0.0.0:1234),
> HeapBuffer[pos=0 lim=4 cap=2048: 00 00 00 00]
> Received: (datagram, server, /10.0.0.120:5678 => /0.0.0.0:1234),
> HeapBuffer[pos=0 lim=4 cap=2048: 00 00 00 00]
> unbound
> Closed: (datagram, server, /10.0.0.120:5678 => /0.0.0.0:1234)
>
> Maarten
>
> On 9/18/07, Maarten Bosteels <mb...@gmail.com> wrote:
> >
> > On linux 2.6.9, jdk 1.6
> >
> > Local host: mortimer/172.30.6.12
> > Open: (datagram, server, /172.30.6.12:5678 => /0:0:0:0:0:0:0:0:1234)
> > Received: (datagram, server, /172.30.6.12:5678 => /0:0:0:0:0:0:0:0:1234),
> > HeapBuffer[pos=0 lim=1 cap=2048: 00]
> > Received: (datagram, server, /172.30.6.12:5678 => /0:0:0:0:0:0:0:0:1234),
> > HeapBuffer[pos=0 lim=2 cap=2048: 00 00]
> > Received: (datagram, server, /172.30.6.12:5678 => /0:0:0:0:0:0:0:0:1234),
> > HeapBuffer[pos=0 lim=3 cap=2048: 00 00 00]
> > Received: (datagram, server, /172.30.6.12:5678 => /0:0:0:0:0:0:0:0:1234),
> > HeapBuffer[pos=0 lim=4 cap=2048: 00 00 00 00]
> > unbound
> > Closed: (datagram, server, /172.30.6.12:5678 => /0:0:0:0:0:0:0:0:1234)
> >
> > Adding a virtual interface (eth0:0) doesn't make a difference.
> > Maarten
> >
> > On 9/18/07, Maarten Bosteels < mbosteels.dns@gmail.com> wrote:
> > >
> > > Hello Trustin,
> > >
> > > I ran the code on Windows XP jdk 1.6 , and this is the output I got:
> > >
> > > Local host: kweenie/172.29.100.104
> > > Open: (datagram, server, /172.29.100.104:5678 => /0.0.0.0:1234)
> > > Received: (datagram, server, /172.29.100.104:5678 => /0.0.0.0:1234),
> > > HeapBuffer[pos=0 lim=2 cap=2048: 00 00]
> > > Received: (datagram, server, /172.29.100.104:5678 => /0.0.0.0:1234),
> > > HeapBuffer[pos=0 lim=1 cap=2048: 00]
> > > Received: (datagram, server, /172.29.100.104:5678 => /0.0.0.0:1234),
> > > HeapBuffer[pos=0 lim=3 cap=2048: 00 00 00]
> > > Received: (datagram, server, /172.29.100.104:5678 => /0.0.0.0:1234),
> > > HeapBuffer[pos=0 lim=3 cap=2048: 00 00 00]
> > > Received: (datagram, server, /172.29.100.104:5678 => /0.0.0.0:1234),
> > > HeapBuffer[pos=0 lim=3 cap=2048: 00 00 00]
> > > Received: (datagram, server, /172.29.100.104:5678 => /0.0.0.0:1234),
> > > HeapBuffer[pos=0 lim=3 cap=2048: 00 00 00]
> > > Received: (datagram, server, /172.29.100.104:5678 => /0.0.0.0:1234),
> > > HeapBuffer[pos=0 lim=4 cap=2048: 00 00 00 00]
> > > Received: (datagram, server, /172.29.100.104:5678 => /0.0.0.0:1234),
> > > HeapBuffer[pos=0 lim=4 cap=2048: 00 00 00 00]
> > > Received: (datagram, server, /172.29.100.104:5678 => /0.0.0.0:1234),
> > > HeapBuffer[pos=0 lim=4 cap=2048: 00 00 00 00]
> > > Received: (datagram, server, /172.29.100.104:5678 => /0.0.0.0:1234),
> > > HeapBuffer[pos=0 lim=4 cap=2048: 00 00 00 00]
> > > Closed: (datagram, server, /172.29.100.104:5678 => /0.0.0.0:1234)
> > > unbound
> > >
> > > I changed the code a little bit, to be able to distinguish the messages.
> > >
> > > Also added a sleep before the unbind, (I think there's one line missing
> > > in your output :-)
> > >
> > >        f1.getSession().write(ByteBuffer.allocate(1)).await();
> > >        f1.getSession().write( ByteBuffer.allocate(2)).await();
> > >
> > >        f2.getSession().write(ByteBuffer.allocate(3)).await();
> > >        f2.getSession().write(ByteBuffer.allocate(4)).await();
> > >
> > >        Thread.sleep(2000);
> > >        acceptor.unbind();
> > >        System.out.println ("unbound");
> > >        System.exit(0);
> > >
> > > The messages sent to the broadcast address are received multiple times:
> > > twice per enabled network connection.
> > > When I enable all 4 network interfaces (LAN, wireless LAN and two
> > > virtual ones for VMWare) I receive them 8 times !
> > >
> > > Maarten
> > >
> > > On 9/17/07, Trustin Lee < trustin@gmail.com> wrote:
> > > >
> > > > Hi,
> > > >
> > > > I made a lot of changes to the current datagram implementation in
> > > > trunk.  DatagramAcceptor now collaborates with DatagramConnector to
> > > > create connected datagram socket which listens to the remote address
> > > > of the received packet.  The following is simplified description of
> > > > flow:
> > > >
> > > > * DatagramAcceptor's underlying DatagramChannel.receive is invoked
> > > > * Once data is received, new connected datagram session is created
> > > > using DatagramConnector.connect(receivedRemoteAddress,
> > > > acceptor.getLocalAddress()).  If there's already a session instance
> > > > associated with the remote address, it's reused.
> > > >
> > > > The advantages of this implementation are:
> > > >
> > > > * The acceptor-side datagram sessions can perform much better in
> > > > multi-core environment.
> > > > * There's no need for IoSessionRecycler on the acceptor-side anymore.
> > > > You have full control over disconnection; probably using sessionIdle
> > > > event in most cases.
> > > > * Code duplication can be reduced once again, and most part of the
> > > > existing acceptor code can be extracted into a generic acceptor
> > > > implementation.
> > > >
> > > > The disadvantage is that it forces you to set reuseAddress to true,
> > > > because multiple datagram channels are bound to the same local
> > > > address.
> > > >
> > > > In Linux, connected datagram channels have priority over unconnected
> > > > channels, so most traffic will go directly into DatagramConnector's
> > > > NIOProcessors.  The only exception I've found is broadcast packets. It
> > > > is always received from the unconnected channel in DatagramAcceptor.
> > > > DatagramAcceptor immediately forwards the event to an appropriate
> > > > session that DatagramConnector is managing, or creates a new session
> > > > using connect().
> > > >
> > > > I think this behavior won't have any big differences among different
> > > > platforms (e.g. Windows and SUNOS).  As long as multiple datagram
> > > > channels can be bound to the same local address, this implementation
> > > > should work fine.  To make this sure, please run the following test
> > > > code in your machine, and let me know what the result is:
> > > >
> > > > -------- CODE BEGINS --------
> > > > package net.gleamynode.tmp;
> > > >
> > > > import java.net.InetAddress;
> > > > import java.net.InetSocketAddress;
> > > >
> > > > import org.apache.mina.common.ByteBuffer;
> > > > import org.apache.mina.common.ConnectFuture;
> > > > import org.apache.mina.common.IoHandlerAdapter ;
> > > > import org.apache.mina.common.IoSession;
> > > > import org.apache.mina.transport.socket.nio.DatagramAcceptor;
> > > > import org.apache.mina.transport.socket.nio.DatagramConnector;
> > > >
> > > > public class Main {
> > > >
> > > >     private static final int SERVER_PORT = 1234;
> > > >     private static final int CLIENT_PORT = 5678;
> > > >
> > > >     public static void main(String args[]) throws Exception {
> > > >         DatagramAcceptor acceptor = new DatagramAcceptor();
> > > >         acceptor.setLocalAddress (new InetSocketAddress(SERVER_PORT));
> > > >
> > > >         acceptor.setHandler(new IoHandlerAdapter() {
> > > >             @Override
> > > >             public void sessionOpened(IoSession session) {
> > > >                 System.out.println("Open: " + session);
> > > >             }
> > > >
> > > >             @Override
> > > >             public void sessionClosed(IoSession session) {
> > > >                 System.out.println("Closed: " + session);
> > > >             }
> > > >
> > > >             @Override
> > > >             public void messageReceived(IoSession session, Object o) {
> > > >
> > > >                 System.out.println("Received: " + session + ", " + o);
> > > >             }
> > > >         });
> > > >         acceptor.bind();
> > > >
> > > >         DatagramConnector connector = new DatagramConnector();
> > > >         connector.getSessionConfig().setReuseAddress(true);
> > > >         connector.setHandler(new IoHandlerAdapter() {
> > > >             @Override
> > > >             public void messageReceived(IoSession session, Object o) {
> > > >                 System.out.println("ERR?");
> > > >             }
> > > >         });
> > > >
> > > >         // Print the local host.
> > > >         System.out.println("Local host: " + InetAddress.getLocalHost
> > > > ());
> > > >
> > > >         // Try point-to-point.
> > > >         ConnectFuture f1 = connector.connect(
> > > >                 new InetSocketAddress(
> > > >                         InetAddress.getLocalHost(), SERVER_PORT),
> > > >                 new InetSocketAddress(
> > > >                          InetAddress.getLocalHost(), CLIENT_PORT));
> > > >         f1.await();
> > > >
> > > >
> > > >         f1.getSession().write(ByteBuffer.allocate(1)).await();
> > > >         f1.getSession().write(ByteBuffer.allocate(1)).await();
> > > >
> > > >
> > > >         // Try broadcast.
> > > >         ConnectFuture f2 = connector.connect(
> > > >                 new InetSocketAddress(
> > > >                         " 255.255.255.255", SERVER_PORT),
> > > >                 new InetSocketAddress(
> > > >                         InetAddress.getLocalHost(), CLIENT_PORT));
> > > >
> > > >         f2.await();
> > > >         f2.getSession().write(ByteBuffer.allocate(1)).await();
> > > >         f2.getSession().write(ByteBuffer.allocate(1)).await();
> > > >
> > > >         acceptor.unbind();
> > > >
> > > >         System.exit(0);
> > > >     }
> > > > }
> > > > -------- CODE ENDS --------
> > > >
> > > > The expected result is:
> > > >
> > > > -------- RESULT BEGINS --------
> > > > Local host: primary/127.0.0.1
> > > > Open: (datagram, server, /127.0.0.1:5678 => /0:0:0:0:0:0:0:0:1234)
> > > > Received: (datagram, server, /127.0.0.1:5678 =>
> > > > /0:0:0:0:0:0:0:0:1234), HeapBuffer[pos=0 lim=1 cap=2048: 00]
> > > > Received: (datagram, server, /127.0.0.1:5678 =>
> > > > /0:0:0:0:0:0:0:0:1234), HeapBuffer[pos=0 lim=1 cap=2048: 00]
> > > > Received: (datagram, server, /127.0.0.1:5678 =>
> > > > /0:0:0:0:0:0:0:0:1234), HeapBuffer[pos=0 lim=1 cap=2048: 00]
> > > > Closed: (datagram, server, /127.0.0.1:5678 => /0:0:0:0:0:0:0:0:1234)
> > > > -------- RESULT ENDS --------
> > > >
> > > > If this test fails on any platform that runs Java 5, I am doomed to
> > > > revert my changes. :)
> > > >
> > > > Trustin
> > > > --
> > > > what we call human nature is actually human habit
> > > > --
> > > > http://gleamynode.net/
> > > > --
> > > > PGP Key ID: 0x0255ECA6
> > > >
> > >
> > >
> >
>


-- 
what we call human nature is actually human habit
--
http://gleamynode.net/
--
PGP Key ID: 0x0255ECA6

Re: Request for a test on various platforms:

Posted by Maarten Bosteels <mb...@gmail.com>.
On SunOS 5.10  sun4u sparc SUNW,Sun-Fire-V890

java version "1.5.0_01"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0_01-b08)
Java HotSpot(TM) Server VM (build 1.5.0_01-b08, mixed mode)

Open: (datagram, server, /10.0.0.120:5678 => /0.0.0.0:1234)
Received: (datagram, server, /10.0.0.120:5678 => /0.0.0.0:1234),
HeapBuffer[pos=0 lim=1 cap=2048: 00]
Received: (datagram, server, /10.0.0.120:5678 => /0.0.0.0:1234),
HeapBuffer[pos=0 lim=2 cap=2048: 00 00]
Received: (datagram, server, /10.0.0.120:5678 => /0.0.0.0:1234),
HeapBuffer[pos=0 lim=3 cap=2048: 00 00 00]
Received: (datagram, server, /10.0.0.120:5678 => /0.0.0.0:1234),
HeapBuffer[pos=0 lim=3 cap=2048: 00 00 00]
Received: (datagram, server, /10.0.0.120:5678 => /0.0.0.0:1234),
HeapBuffer[pos=0 lim=4 cap=2048: 00 00 00 00]
Received: (datagram, server, /10.0.0.120:5678 => /0.0.0.0:1234),
HeapBuffer[pos=0 lim=4 cap=2048: 00 00 00 00]
unbound
Closed: (datagram, server, /10.0.0.120:5678 => /0.0.0.0:1234)

Maarten

On 9/18/07, Maarten Bosteels <mb...@gmail.com> wrote:
>
> On linux 2.6.9, jdk 1.6
>
> Local host: mortimer/172.30.6.12
> Open: (datagram, server, /172.30.6.12:5678 => /0:0:0:0:0:0:0:0:1234)
> Received: (datagram, server, /172.30.6.12:5678 => /0:0:0:0:0:0:0:0:1234),
> HeapBuffer[pos=0 lim=1 cap=2048: 00]
> Received: (datagram, server, /172.30.6.12:5678 => /0:0:0:0:0:0:0:0:1234),
> HeapBuffer[pos=0 lim=2 cap=2048: 00 00]
> Received: (datagram, server, /172.30.6.12:5678 => /0:0:0:0:0:0:0:0:1234),
> HeapBuffer[pos=0 lim=3 cap=2048: 00 00 00]
> Received: (datagram, server, /172.30.6.12:5678 => /0:0:0:0:0:0:0:0:1234),
> HeapBuffer[pos=0 lim=4 cap=2048: 00 00 00 00]
> unbound
> Closed: (datagram, server, /172.30.6.12:5678 => /0:0:0:0:0:0:0:0:1234)
>
> Adding a virtual interface (eth0:0) doesn't make a difference.
> Maarten
>
> On 9/18/07, Maarten Bosteels < mbosteels.dns@gmail.com> wrote:
> >
> > Hello Trustin,
> >
> > I ran the code on Windows XP jdk 1.6 , and this is the output I got:
> >
> > Local host: kweenie/172.29.100.104
> > Open: (datagram, server, /172.29.100.104:5678 => /0.0.0.0:1234)
> > Received: (datagram, server, /172.29.100.104:5678 => /0.0.0.0:1234),
> > HeapBuffer[pos=0 lim=2 cap=2048: 00 00]
> > Received: (datagram, server, /172.29.100.104:5678 => /0.0.0.0:1234),
> > HeapBuffer[pos=0 lim=1 cap=2048: 00]
> > Received: (datagram, server, /172.29.100.104:5678 => /0.0.0.0:1234),
> > HeapBuffer[pos=0 lim=3 cap=2048: 00 00 00]
> > Received: (datagram, server, /172.29.100.104:5678 => /0.0.0.0:1234),
> > HeapBuffer[pos=0 lim=3 cap=2048: 00 00 00]
> > Received: (datagram, server, /172.29.100.104:5678 => /0.0.0.0:1234),
> > HeapBuffer[pos=0 lim=3 cap=2048: 00 00 00]
> > Received: (datagram, server, /172.29.100.104:5678 => /0.0.0.0:1234),
> > HeapBuffer[pos=0 lim=3 cap=2048: 00 00 00]
> > Received: (datagram, server, /172.29.100.104:5678 => /0.0.0.0:1234),
> > HeapBuffer[pos=0 lim=4 cap=2048: 00 00 00 00]
> > Received: (datagram, server, /172.29.100.104:5678 => /0.0.0.0:1234),
> > HeapBuffer[pos=0 lim=4 cap=2048: 00 00 00 00]
> > Received: (datagram, server, /172.29.100.104:5678 => /0.0.0.0:1234),
> > HeapBuffer[pos=0 lim=4 cap=2048: 00 00 00 00]
> > Received: (datagram, server, /172.29.100.104:5678 => /0.0.0.0:1234),
> > HeapBuffer[pos=0 lim=4 cap=2048: 00 00 00 00]
> > Closed: (datagram, server, /172.29.100.104:5678 => /0.0.0.0:1234)
> > unbound
> >
> > I changed the code a little bit, to be able to distinguish the messages.
> >
> > Also added a sleep before the unbind, (I think there's one line missing
> > in your output :-)
> >
> >        f1.getSession().write(ByteBuffer.allocate(1)).await();
> >        f1.getSession().write( ByteBuffer.allocate(2)).await();
> >
> >        f2.getSession().write(ByteBuffer.allocate(3)).await();
> >        f2.getSession().write(ByteBuffer.allocate(4)).await();
> >
> >        Thread.sleep(2000);
> >        acceptor.unbind();
> >        System.out.println ("unbound");
> >        System.exit(0);
> >
> > The messages sent to the broadcast address are received multiple times:
> > twice per enabled network connection.
> > When I enable all 4 network interfaces (LAN, wireless LAN and two
> > virtual ones for VMWare) I receive them 8 times !
> >
> > Maarten
> >
> > On 9/17/07, Trustin Lee < trustin@gmail.com> wrote:
> > >
> > > Hi,
> > >
> > > I made a lot of changes to the current datagram implementation in
> > > trunk.  DatagramAcceptor now collaborates with DatagramConnector to
> > > create connected datagram socket which listens to the remote address
> > > of the received packet.  The following is simplified description of
> > > flow:
> > >
> > > * DatagramAcceptor's underlying DatagramChannel.receive is invoked
> > > * Once data is received, new connected datagram session is created
> > > using DatagramConnector.connect(receivedRemoteAddress,
> > > acceptor.getLocalAddress()).  If there's already a session instance
> > > associated with the remote address, it's reused.
> > >
> > > The advantages of this implementation are:
> > >
> > > * The acceptor-side datagram sessions can perform much better in
> > > multi-core environment.
> > > * There's no need for IoSessionRecycler on the acceptor-side anymore.
> > > You have full control over disconnection; probably using sessionIdle
> > > event in most cases.
> > > * Code duplication can be reduced once again, and most part of the
> > > existing acceptor code can be extracted into a generic acceptor
> > > implementation.
> > >
> > > The disadvantage is that it forces you to set reuseAddress to true,
> > > because multiple datagram channels are bound to the same local
> > > address.
> > >
> > > In Linux, connected datagram channels have priority over unconnected
> > > channels, so most traffic will go directly into DatagramConnector's
> > > NIOProcessors.  The only exception I've found is broadcast packets. It
> > > is always received from the unconnected channel in DatagramAcceptor.
> > > DatagramAcceptor immediately forwards the event to an appropriate
> > > session that DatagramConnector is managing, or creates a new session
> > > using connect().
> > >
> > > I think this behavior won't have any big differences among different
> > > platforms (e.g. Windows and SUNOS).  As long as multiple datagram
> > > channels can be bound to the same local address, this implementation
> > > should work fine.  To make this sure, please run the following test
> > > code in your machine, and let me know what the result is:
> > >
> > > -------- CODE BEGINS --------
> > > package net.gleamynode.tmp;
> > >
> > > import java.net.InetAddress;
> > > import java.net.InetSocketAddress;
> > >
> > > import org.apache.mina.common.ByteBuffer;
> > > import org.apache.mina.common.ConnectFuture;
> > > import org.apache.mina.common.IoHandlerAdapter ;
> > > import org.apache.mina.common.IoSession;
> > > import org.apache.mina.transport.socket.nio.DatagramAcceptor;
> > > import org.apache.mina.transport.socket.nio.DatagramConnector;
> > >
> > > public class Main {
> > >
> > >     private static final int SERVER_PORT = 1234;
> > >     private static final int CLIENT_PORT = 5678;
> > >
> > >     public static void main(String args[]) throws Exception {
> > >         DatagramAcceptor acceptor = new DatagramAcceptor();
> > >         acceptor.setLocalAddress (new InetSocketAddress(SERVER_PORT));
> > >
> > >         acceptor.setHandler(new IoHandlerAdapter() {
> > >             @Override
> > >             public void sessionOpened(IoSession session) {
> > >                 System.out.println("Open: " + session);
> > >             }
> > >
> > >             @Override
> > >             public void sessionClosed(IoSession session) {
> > >                 System.out.println("Closed: " + session);
> > >             }
> > >
> > >             @Override
> > >             public void messageReceived(IoSession session, Object o) {
> > >
> > >                 System.out.println("Received: " + session + ", " + o);
> > >             }
> > >         });
> > >         acceptor.bind();
> > >
> > >         DatagramConnector connector = new DatagramConnector();
> > >         connector.getSessionConfig().setReuseAddress(true);
> > >         connector.setHandler(new IoHandlerAdapter() {
> > >             @Override
> > >             public void messageReceived(IoSession session, Object o) {
> > >                 System.out.println("ERR?");
> > >             }
> > >         });
> > >
> > >         // Print the local host.
> > >         System.out.println("Local host: " + InetAddress.getLocalHost
> > > ());
> > >
> > >         // Try point-to-point.
> > >         ConnectFuture f1 = connector.connect(
> > >                 new InetSocketAddress(
> > >                         InetAddress.getLocalHost(), SERVER_PORT),
> > >                 new InetSocketAddress(
> > >                          InetAddress.getLocalHost(), CLIENT_PORT));
> > >         f1.await();
> > >
> > >
> > >         f1.getSession().write(ByteBuffer.allocate(1)).await();
> > >         f1.getSession().write(ByteBuffer.allocate(1)).await();
> > >
> > >
> > >         // Try broadcast.
> > >         ConnectFuture f2 = connector.connect(
> > >                 new InetSocketAddress(
> > >                         " 255.255.255.255", SERVER_PORT),
> > >                 new InetSocketAddress(
> > >                         InetAddress.getLocalHost(), CLIENT_PORT));
> > >
> > >         f2.await();
> > >         f2.getSession().write(ByteBuffer.allocate(1)).await();
> > >         f2.getSession().write(ByteBuffer.allocate(1)).await();
> > >
> > >         acceptor.unbind();
> > >
> > >         System.exit(0);
> > >     }
> > > }
> > > -------- CODE ENDS --------
> > >
> > > The expected result is:
> > >
> > > -------- RESULT BEGINS --------
> > > Local host: primary/127.0.0.1
> > > Open: (datagram, server, /127.0.0.1:5678 => /0:0:0:0:0:0:0:0:1234)
> > > Received: (datagram, server, /127.0.0.1:5678 =>
> > > /0:0:0:0:0:0:0:0:1234), HeapBuffer[pos=0 lim=1 cap=2048: 00]
> > > Received: (datagram, server, /127.0.0.1:5678 =>
> > > /0:0:0:0:0:0:0:0:1234), HeapBuffer[pos=0 lim=1 cap=2048: 00]
> > > Received: (datagram, server, /127.0.0.1:5678 =>
> > > /0:0:0:0:0:0:0:0:1234), HeapBuffer[pos=0 lim=1 cap=2048: 00]
> > > Closed: (datagram, server, /127.0.0.1:5678 => /0:0:0:0:0:0:0:0:1234)
> > > -------- RESULT ENDS --------
> > >
> > > If this test fails on any platform that runs Java 5, I am doomed to
> > > revert my changes. :)
> > >
> > > Trustin
> > > --
> > > what we call human nature is actually human habit
> > > --
> > > http://gleamynode.net/
> > > --
> > > PGP Key ID: 0x0255ECA6
> > >
> >
> >
>

Re: Request for a test on various platforms:

Posted by Maarten Bosteels <mb...@gmail.com>.
On linux 2.6.9, jdk 1.6

Local host: mortimer/172.30.6.12
Open: (datagram, server, /172.30.6.12:5678 => /0:0:0:0:0:0:0:0:1234)
Received: (datagram, server, /172.30.6.12:5678 => /0:0:0:0:0:0:0:0:1234),
HeapBuffer[pos=0 lim=1 cap=2048: 00]
Received: (datagram, server, /172.30.6.12:5678 => /0:0:0:0:0:0:0:0:1234),
HeapBuffer[pos=0 lim=2 cap=2048: 00 00]
Received: (datagram, server, /172.30.6.12:5678 => /0:0:0:0:0:0:0:0:1234),
HeapBuffer[pos=0 lim=3 cap=2048: 00 00 00]
Received: (datagram, server, /172.30.6.12:5678 => /0:0:0:0:0:0:0:0:1234),
HeapBuffer[pos=0 lim=4 cap=2048: 00 00 00 00]
unbound
Closed: (datagram, server, /172.30.6.12:5678 => /0:0:0:0:0:0:0:0:1234)

Adding a virtual interface (eth0:0) doesn't make a difference.
Maarten

On 9/18/07, Maarten Bosteels <mb...@gmail.com> wrote:
>
> Hello Trustin,
>
> I ran the code on Windows XP jdk 1.6 , and this is the output I got:
>
> Local host: kweenie/172.29.100.104
> Open: (datagram, server, /172.29.100.104:5678 => /0.0.0.0:1234)
> Received: (datagram, server, /172.29.100.104:5678 => /0.0.0.0:1234),
> HeapBuffer[pos=0 lim=2 cap=2048: 00 00]
> Received: (datagram, server, /172.29.100.104:5678 => /0.0.0.0:1234),
> HeapBuffer[pos=0 lim=1 cap=2048: 00]
> Received: (datagram, server, /172.29.100.104:5678 => /0.0.0.0:1234),
> HeapBuffer[pos=0 lim=3 cap=2048: 00 00 00]
> Received: (datagram, server, /172.29.100.104:5678 => /0.0.0.0:1234),
> HeapBuffer[pos=0 lim=3 cap=2048: 00 00 00]
> Received: (datagram, server, /172.29.100.104:5678 => /0.0.0.0:1234),
> HeapBuffer[pos=0 lim=3 cap=2048: 00 00 00]
> Received: (datagram, server, /172.29.100.104:5678 => /0.0.0.0:1234),
> HeapBuffer[pos=0 lim=3 cap=2048: 00 00 00]
> Received: (datagram, server, /172.29.100.104:5678 => /0.0.0.0:1234),
> HeapBuffer[pos=0 lim=4 cap=2048: 00 00 00 00]
> Received: (datagram, server, /172.29.100.104:5678 => /0.0.0.0:1234),
> HeapBuffer[pos=0 lim=4 cap=2048: 00 00 00 00]
> Received: (datagram, server, /172.29.100.104:5678 => /0.0.0.0:1234),
> HeapBuffer[pos=0 lim=4 cap=2048: 00 00 00 00]
> Received: (datagram, server, /172.29.100.104:5678 => /0.0.0.0:1234),
> HeapBuffer[pos=0 lim=4 cap=2048: 00 00 00 00]
> Closed: (datagram, server, /172.29.100.104:5678 => /0.0.0.0:1234)
> unbound
>
> I changed the code a little bit, to be able to distinguish the messages.
> Also added a sleep before the unbind, (I think there's one line missing in
> your output :-)
>
>        f1.getSession().write(ByteBuffer.allocate(1)).await();
>        f1.getSession().write(ByteBuffer.allocate(2)).await();
>
>        f2.getSession().write(ByteBuffer.allocate(3)).await();
>        f2.getSession().write(ByteBuffer.allocate(4)).await();
>
>        Thread.sleep(2000);
>        acceptor.unbind();
>        System.out.println ("unbound");
>        System.exit(0);
>
> The messages sent to the broadcast address are received multiple times:
> twice per enabled network connection.
> When I enable all 4 network interfaces (LAN, wireless LAN and two virtual
> ones for VMWare) I receive them 8 times !
>
> Maarten
>
> On 9/17/07, Trustin Lee <tr...@gmail.com> wrote:
> >
> > Hi,
> >
> > I made a lot of changes to the current datagram implementation in
> > trunk.  DatagramAcceptor now collaborates with DatagramConnector to
> > create connected datagram socket which listens to the remote address
> > of the received packet.  The following is simplified description of
> > flow:
> >
> > * DatagramAcceptor's underlying DatagramChannel.receive is invoked
> > * Once data is received, new connected datagram session is created
> > using DatagramConnector.connect(receivedRemoteAddress,
> > acceptor.getLocalAddress()).  If there's already a session instance
> > associated with the remote address, it's reused.
> >
> > The advantages of this implementation are:
> >
> > * The acceptor-side datagram sessions can perform much better in
> > multi-core environment.
> > * There's no need for IoSessionRecycler on the acceptor-side anymore.
> > You have full control over disconnection; probably using sessionIdle
> > event in most cases.
> > * Code duplication can be reduced once again, and most part of the
> > existing acceptor code can be extracted into a generic acceptor
> > implementation.
> >
> > The disadvantage is that it forces you to set reuseAddress to true,
> > because multiple datagram channels are bound to the same local
> > address.
> >
> > In Linux, connected datagram channels have priority over unconnected
> > channels, so most traffic will go directly into DatagramConnector's
> > NIOProcessors.  The only exception I've found is broadcast packets. It
> > is always received from the unconnected channel in DatagramAcceptor.
> > DatagramAcceptor immediately forwards the event to an appropriate
> > session that DatagramConnector is managing, or creates a new session
> > using connect().
> >
> > I think this behavior won't have any big differences among different
> > platforms (e.g. Windows and SUNOS).  As long as multiple datagram
> > channels can be bound to the same local address, this implementation
> > should work fine.  To make this sure, please run the following test
> > code in your machine, and let me know what the result is:
> >
> > -------- CODE BEGINS --------
> > package net.gleamynode.tmp;
> >
> > import java.net.InetAddress;
> > import java.net.InetSocketAddress;
> >
> > import org.apache.mina.common.ByteBuffer;
> > import org.apache.mina.common.ConnectFuture;
> > import org.apache.mina.common.IoHandlerAdapter ;
> > import org.apache.mina.common.IoSession;
> > import org.apache.mina.transport.socket.nio.DatagramAcceptor;
> > import org.apache.mina.transport.socket.nio.DatagramConnector;
> >
> > public class Main {
> >
> >     private static final int SERVER_PORT = 1234;
> >     private static final int CLIENT_PORT = 5678;
> >
> >     public static void main(String args[]) throws Exception {
> >         DatagramAcceptor acceptor = new DatagramAcceptor();
> >         acceptor.setLocalAddress(new InetSocketAddress(SERVER_PORT));
> >         acceptor.setHandler(new IoHandlerAdapter() {
> >             @Override
> >             public void sessionOpened(IoSession session) {
> >                 System.out.println("Open: " + session);
> >             }
> >
> >             @Override
> >             public void sessionClosed(IoSession session) {
> >                 System.out.println("Closed: " + session);
> >             }
> >
> >             @Override
> >             public void messageReceived(IoSession session, Object o) {
> >                 System.out.println("Received: " + session + ", " + o);
> >             }
> >         });
> >         acceptor.bind();
> >
> >         DatagramConnector connector = new DatagramConnector();
> >         connector.getSessionConfig().setReuseAddress(true);
> >         connector.setHandler(new IoHandlerAdapter() {
> >             @Override
> >             public void messageReceived(IoSession session, Object o) {
> >                 System.out.println("ERR?");
> >             }
> >         });
> >
> >         // Print the local host.
> >         System.out.println("Local host: " + InetAddress.getLocalHost());
> >
> >         // Try point-to-point.
> >         ConnectFuture f1 = connector.connect(
> >                 new InetSocketAddress(
> >                         InetAddress.getLocalHost(), SERVER_PORT),
> >                 new InetSocketAddress(
> >                          InetAddress.getLocalHost(), CLIENT_PORT));
> >         f1.await();
> >
> >
> >         f1.getSession().write(ByteBuffer.allocate(1)).await();
> >         f1.getSession().write(ByteBuffer.allocate(1)).await();
> >
> >
> >         // Try broadcast.
> >         ConnectFuture f2 = connector.connect(
> >                 new InetSocketAddress(
> >                         "255.255.255.255", SERVER_PORT),
> >                 new InetSocketAddress(
> >                         InetAddress.getLocalHost(), CLIENT_PORT));
> >
> >         f2.await();
> >         f2.getSession().write(ByteBuffer.allocate(1)).await();
> >         f2.getSession().write(ByteBuffer.allocate(1)).await();
> >
> >         acceptor.unbind();
> >
> >         System.exit(0);
> >     }
> > }
> > -------- CODE ENDS --------
> >
> > The expected result is:
> >
> > -------- RESULT BEGINS --------
> > Local host: primary/127.0.0.1
> > Open: (datagram, server, /127.0.0.1:5678 => /0:0:0:0:0:0:0:0:1234)
> > Received: (datagram, server, /127.0.0.1:5678 =>
> > /0:0:0:0:0:0:0:0:1234), HeapBuffer[pos=0 lim=1 cap=2048: 00]
> > Received: (datagram, server, /127.0.0.1:5678 =>
> > /0:0:0:0:0:0:0:0:1234), HeapBuffer[pos=0 lim=1 cap=2048: 00]
> > Received: (datagram, server, /127.0.0.1:5678 =>
> > /0:0:0:0:0:0:0:0:1234), HeapBuffer[pos=0 lim=1 cap=2048: 00]
> > Closed: (datagram, server, /127.0.0.1:5678 => /0:0:0:0:0:0:0:0:1234)
> > -------- RESULT ENDS --------
> >
> > If this test fails on any platform that runs Java 5, I am doomed to
> > revert my changes. :)
> >
> > Trustin
> > --
> > what we call human nature is actually human habit
> > --
> > http://gleamynode.net/
> > --
> > PGP Key ID: 0x0255ECA6
> >
>
>

Re: Request for a test on various platforms:

Posted by Maarten Bosteels <mb...@gmail.com>.
Hello Trustin,

I ran the code on Windows XP jdk 1.6 , and this is the output I got:

Local host: kweenie/172.29.100.104
Open: (datagram, server, /172.29.100.104:5678 => /0.0.0.0:1234)
Received: (datagram, server, /172.29.100.104:5678 => /0.0.0.0:1234),
HeapBuffer[pos=0 lim=2 cap=2048: 00 00]
Received: (datagram, server, /172.29.100.104:5678 => /0.0.0.0:1234),
HeapBuffer[pos=0 lim=1 cap=2048: 00]
Received: (datagram, server, /172.29.100.104:5678 => /0.0.0.0:1234),
HeapBuffer[pos=0 lim=3 cap=2048: 00 00 00]
Received: (datagram, server, /172.29.100.104:5678 => /0.0.0.0:1234),
HeapBuffer[pos=0 lim=3 cap=2048: 00 00 00]
Received: (datagram, server, /172.29.100.104:5678 => /0.0.0.0:1234),
HeapBuffer[pos=0 lim=3 cap=2048: 00 00 00]
Received: (datagram, server, /172.29.100.104:5678 => /0.0.0.0:1234),
HeapBuffer[pos=0 lim=3 cap=2048: 00 00 00]
Received: (datagram, server, /172.29.100.104:5678 => /0.0.0.0:1234),
HeapBuffer[pos=0 lim=4 cap=2048: 00 00 00 00]
Received: (datagram, server, /172.29.100.104:5678 => /0.0.0.0:1234),
HeapBuffer[pos=0 lim=4 cap=2048: 00 00 00 00]
Received: (datagram, server, /172.29.100.104:5678 => /0.0.0.0:1234),
HeapBuffer[pos=0 lim=4 cap=2048: 00 00 00 00]
Received: (datagram, server, /172.29.100.104:5678 => /0.0.0.0:1234),
HeapBuffer[pos=0 lim=4 cap=2048: 00 00 00 00]
Closed: (datagram, server, /172.29.100.104:5678 => /0.0.0.0:1234)
unbound

I changed the code a little bit, to be able to distinguish the messages.
Also added a sleep before the unbind, (I think there's one line missing in
your output :-)

       f1.getSession().write(ByteBuffer.allocate(1)).await();
       f1.getSession().write(ByteBuffer.allocate(2)).await();

       f2.getSession().write(ByteBuffer.allocate(3)).await();
       f2.getSession().write(ByteBuffer.allocate(4)).await();

       Thread.sleep(2000);
       acceptor.unbind();
       System.out.println("unbound");
       System.exit(0);

The messages sent to the broadcast address are received multiple times:
twice per enabled network connection.
When I enable all 4 network interfaces (LAN, wireless LAN and two virtual
ones for VMWare) I receive them 8 times !

Maarten

On 9/17/07, Trustin Lee <tr...@gmail.com> wrote:
>
> Hi,
>
> I made a lot of changes to the current datagram implementation in
> trunk.  DatagramAcceptor now collaborates with DatagramConnector to
> create connected datagram socket which listens to the remote address
> of the received packet.  The following is simplified description of
> flow:
>
> * DatagramAcceptor's underlying DatagramChannel.receive is invoked
> * Once data is received, new connected datagram session is created
> using DatagramConnector.connect(receivedRemoteAddress,
> acceptor.getLocalAddress()).  If there's already a session instance
> associated with the remote address, it's reused.
>
> The advantages of this implementation are:
>
> * The acceptor-side datagram sessions can perform much better in
> multi-core environment.
> * There's no need for IoSessionRecycler on the acceptor-side anymore.
> You have full control over disconnection; probably using sessionIdle
> event in most cases.
> * Code duplication can be reduced once again, and most part of the
> existing acceptor code can be extracted into a generic acceptor
> implementation.
>
> The disadvantage is that it forces you to set reuseAddress to true,
> because multiple datagram channels are bound to the same local
> address.
>
> In Linux, connected datagram channels have priority over unconnected
> channels, so most traffic will go directly into DatagramConnector's
> NIOProcessors.  The only exception I've found is broadcast packets. It
> is always received from the unconnected channel in DatagramAcceptor.
> DatagramAcceptor immediately forwards the event to an appropriate
> session that DatagramConnector is managing, or creates a new session
> using connect().
>
> I think this behavior won't have any big differences among different
> platforms (e.g. Windows and SUNOS).  As long as multiple datagram
> channels can be bound to the same local address, this implementation
> should work fine.  To make this sure, please run the following test
> code in your machine, and let me know what the result is:
>
> -------- CODE BEGINS --------
> package net.gleamynode.tmp;
>
> import java.net.InetAddress;
> import java.net.InetSocketAddress;
>
> import org.apache.mina.common.ByteBuffer;
> import org.apache.mina.common.ConnectFuture;
> import org.apache.mina.common.IoHandlerAdapter;
> import org.apache.mina.common.IoSession;
> import org.apache.mina.transport.socket.nio.DatagramAcceptor;
> import org.apache.mina.transport.socket.nio.DatagramConnector;
>
> public class Main {
>
>     private static final int SERVER_PORT = 1234;
>     private static final int CLIENT_PORT = 5678;
>
>     public static void main(String args[]) throws Exception {
>         DatagramAcceptor acceptor = new DatagramAcceptor();
>         acceptor.setLocalAddress(new InetSocketAddress(SERVER_PORT));
>         acceptor.setHandler(new IoHandlerAdapter() {
>             @Override
>             public void sessionOpened(IoSession session) {
>                 System.out.println("Open: " + session);
>             }
>
>             @Override
>             public void sessionClosed(IoSession session) {
>                 System.out.println("Closed: " + session);
>             }
>
>             @Override
>             public void messageReceived(IoSession session, Object o) {
>                 System.out.println("Received: " + session + ", " + o);
>             }
>         });
>         acceptor.bind();
>
>         DatagramConnector connector = new DatagramConnector();
>         connector.getSessionConfig().setReuseAddress(true);
>         connector.setHandler(new IoHandlerAdapter() {
>             @Override
>             public void messageReceived(IoSession session, Object o) {
>                 System.out.println("ERR?");
>             }
>         });
>
>         // Print the local host.
>         System.out.println("Local host: " + InetAddress.getLocalHost());
>
>         // Try point-to-point.
>         ConnectFuture f1 = connector.connect(
>                 new InetSocketAddress(
>                         InetAddress.getLocalHost(), SERVER_PORT),
>                 new InetSocketAddress(
>                         InetAddress.getLocalHost(), CLIENT_PORT));
>         f1.await();
>
>
>         f1.getSession().write(ByteBuffer.allocate(1)).await();
>         f1.getSession().write(ByteBuffer.allocate(1)).await();
>
>
>         // Try broadcast.
>         ConnectFuture f2 = connector.connect(
>                 new InetSocketAddress(
>                         "255.255.255.255", SERVER_PORT),
>                 new InetSocketAddress(
>                         InetAddress.getLocalHost(), CLIENT_PORT));
>
>         f2.await();
>         f2.getSession().write(ByteBuffer.allocate(1)).await();
>         f2.getSession().write(ByteBuffer.allocate(1)).await();
>
>         acceptor.unbind();
>
>         System.exit(0);
>     }
> }
> -------- CODE ENDS --------
>
> The expected result is:
>
> -------- RESULT BEGINS --------
> Local host: primary/127.0.0.1
> Open: (datagram, server, /127.0.0.1:5678 => /0:0:0:0:0:0:0:0:1234)
> Received: (datagram, server, /127.0.0.1:5678 =>
> /0:0:0:0:0:0:0:0:1234), HeapBuffer[pos=0 lim=1 cap=2048: 00]
> Received: (datagram, server, /127.0.0.1:5678 =>
> /0:0:0:0:0:0:0:0:1234), HeapBuffer[pos=0 lim=1 cap=2048: 00]
> Received: (datagram, server, /127.0.0.1:5678 =>
> /0:0:0:0:0:0:0:0:1234), HeapBuffer[pos=0 lim=1 cap=2048: 00]
> Closed: (datagram, server, /127.0.0.1:5678 => /0:0:0:0:0:0:0:0:1234)
> -------- RESULT ENDS --------
>
> If this test fails on any platform that runs Java 5, I am doomed to
> revert my changes. :)
>
> Trustin
> --
> what we call human nature is actually human habit
> --
> http://gleamynode.net/
> --
> PGP Key ID: 0x0255ECA6
>