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 <[EMAIL PROTECTED]> 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 <[EMAIL PROTECTED]> wrote: > > Also tested it on a Solaris box with just one network interface: > > > > [EMAIL PROTECTED] 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 > > [EMAIL PROTECTED] tmp]$ > > [EMAIL PROTECTED] tmp]$ uname -a > > SunOS mercury 5.10 Generic_118833-24 sun4u sparc SUNW,Ultra-250 > > [EMAIL PROTECTED] tmp]$ > > [EMAIL PROTECTED] 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) > > [EMAIL PROTECTED] tmp]$ > > > > Maarten > > > > On 9/18/07, Maarten Bosteels <[EMAIL PROTECTED]> wrote: > > > > > > On 9/18/07, Trustin Lee <[EMAIL PROTECTED]> wrote: > > > > > > > > How many network devices exist in SunOS? > > > > > > > > > > > > [EMAIL PROTECTED] # 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 <[EMAIL PROTECTED]> 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 <[EMAIL PROTECTED] > 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 < [EMAIL PROTECTED]> 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 < [EMAIL PROTECTED] > 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