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 <[EMAIL PROTECTED]> wrote:
> On 9/19/07, Trustin Lee <[EMAIL PROTECTED]> 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