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