Alright so for fun I'm practicing multithreading and networking in Java right now but I've ran into something really weird. I have my code structure as follows. Client and Server are threads, which contain PacketListeners which are also threads that just add packets to a ConcurrentLinkedQueue when received.
My Server class looks like this
public Server(int port) {
setThreadName("ServerThread");
this.clients = new ArrayList<SocketAddress>();
try {
//this.socket = new DatagramSocket(null);
//this.socket.setReuseAddress(true);
//this.socket.bind(new InetSocketAddress(port));
//this.socket.setReuseAddress(true);
//this.socket.bind(new InetSocketAddress(port));
//sender = new PacketSender(socket);
this.listener = new PacketListener(port);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
listener.start();
}
synchronized private void processPacket(DatagramPacket packet) {
if (packet != null) {
String data = new String(packet.getData(), 0, packet.getLength());
System.out.println("Received a packet " + data);
if (data.equalsIgnoreCase("connecting")) {
System.out.println("wut");
} else {
System.out.println("Packet from :" + packet.getAddress().toString() + " saying: " + data);
}
} else {
System.out.println("Packet == null");
}
}
@Override
public void run() {
System.out.println("running server on port " + socket.getLocalPort());
while (isRunning()) {
if (listener.hasPacket()) {
System.out.println("listener has a packet");
processPacket(listener.getNextPacket());
}
sleep(1); // sleep for 1ms (keeps cpu usage from sky rocketing)
}
}
My PacketListener class looks like this
public PacketListener(int port) throws IOException {
this.socket = new DatagramSocket(null);
this.socket.setReuseAddress(true);
this.socket.bind(new InetSocketAddress(port));
System.out.println("Packet listener bound @ " + socket.getLocalAddress() + " on port " + socket.getLocalPort());
receivedPackets = new ConcurrentLinkedQueue<DatagramPacket>();
}
synchronized private void addPacket(DatagramPacket packet) {
if (!receivedPackets.add(packet)) {
System.err.println("We dropped a packet because full queue");
} else {
System.out.println("We added a received packet! - " + receivedPackets.size());
}
}
synchronized public boolean hasPacket() {
return !receivedPackets.isEmpty();
}
synchronized public DatagramPacket getNextPacket() {
return receivedPackets.poll();
}
@Override
public void run() {
byte[] buffer = new byte[256];
DatagramPacket inPacket = new DatagramPacket(buffer, buffer.length);
while (isRunning()) {
try {
socket.receive(inPacket);
addPacket(inPacket);
} catch (Exception e) {
e.printStackTrace();
}
}
}
Now the weird thing is that on the client end, say I send a few packets. Let's say I send "hello", then "test1", then "test2" The server will print out
Packet received
We added a received packet! - 1
listener has a packet
Packet received
Received a packet test1
We added a received packet! - 1
Packet from :/127.0.0.1 saying: test1
listener has a packet
Packet received
Received a packet test2
We added a received packet! - 1
Packet from :/127.0.0.1 saying: test2
listener has a packet
This should actually print out something along the lines of
We added a received packet! - 1
listener has a packet
Received a packet hello
Packet from :/127.0.0.1 saying: hello
We added a received packet! - 1
listener has a packet
Received a packet test1
Packet from :/127.0.0.1 saying: test1
We added a received packet! - 1
listener has a packet
Received a packet test2
Packet from :/127.0.0.1 saying: test2
DatagramSockets?Multiple packets sent from one machine to another may be routed differently, and may arrive in any order.from Javadocs.