So I was working on a UDP API for the past couple of days and I've tried to test my API on my local machine first.
So I created a server and a client instance in separate threads.
As I was sending packets to the server with the client, the server received those packets, but when I tried to send packets from the server to the client, the server just sent its messages to itself instead and responded to the packets it received, ending up in a loop of infinite message sending.
Here are some parts of the current code:
Client:
package com.github.sebyplays.jsimpleudp;
import lombok.Getter;
import lombok.Setter;
import lombok.SneakyThrows;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.util.Scanner;
import java.util.concurrent.TimeUnit;
public class Client implements ICommunicator{
@Getter private DatagramSocket datagramSocket;
private boolean running;
@Getter @Setter private byte[] buffer = new byte[1024];
@Getter @Setter private PacketReceiver packetReceiver;
@Getter @Setter private InetAddress host;
private Type type = Type.CLIENT;
@Getter private int port;
@Getter private DatagramPacket lastReceivedPacket;
@Getter private DatagramPacket lastSentPacket;
private long lastReceivedTime = 0;
private long lastSentTime = 0;
@SneakyThrows
public Client(String host, int port, PacketReceiver packetReceiver) {
this.packetReceiver = packetReceiver;
this.port = port;
this.host = InetAddress.getByName(host);
this.datagramSocket = new DatagramSocket();
}
@Override
public void start() {
running = true;
Thread thread = new Thread("udpclient"){
@SneakyThrows
@Override
public void run() {
while (running){
DatagramPacket datagramPacket = new DatagramPacket(buffer, buffer.length, host, port);
datagramSocket.receive(datagramPacket);
lastReceivedPacket = datagramPacket;
lastReceivedTime = System.currentTimeMillis();
callReceiver(datagramPacket);
}
}
};
thread.start();
}
@Override
public void stop() {
running = false;
if(!datagramSocket.isClosed()){
datagramSocket.close();
}
}
public void sendPacket(DatagramPacket datagramPacket){
try {
datagramSocket.send(datagramPacket);
lastSentPacket = datagramPacket;
lastSentTime = System.currentTimeMillis();
} catch (IOException e) {
e.printStackTrace();
}
}
public void callReceiver(DatagramPacket datagramPacket){
packetReceiver.onPacket(this, datagramPacket, datagramPacket.getAddress(),
new String(datagramPacket.getData(), 0, datagramPacket.getLength()), this.getType());
}
@Override
public Type getType() {
return this.type;
}
@Override
public void sendMessage(InetAddress inetAddress, String message){
byte[] messageBytes = message.getBytes();
DatagramPacket datagramPacket = new DatagramPacket(messageBytes, messageBytes.length, inetAddress, port);
sendPacket(datagramPacket);
}
@Override
public long getLastReceivedTime() {
return System.currentTimeMillis() - lastReceivedTime;
}
@Override
public long getLastSentTime() {
return System.currentTimeMillis() - lastSentTime;
}
public static void main(String[] args) {
Client client = new Client("mcsilent.de", 2312, new PacketReceiver() {
@Override
public void onPacket(ICommunicator iCommunicator, DatagramPacket datagramPacket, InetAddress source, String packet, Type type) {
System.out.println(packet);
}
});
client.start();
Scanner scanner = new Scanner(System.in);
while (true){
if(scanner.nextLine().equalsIgnoreCase("r")){
client.sendMessage(client.getHost(), "InfoRequest::lobby01");
}
}
}
}
Server:
package com.github.sebyplays.jsimpleudp;
import lombok.Getter;
import lombok.Setter;
import lombok.SneakyThrows;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
public class Server implements ICommunicator{
@Getter private DatagramSocket datagramSocket;
private boolean running;
@Getter @Setter private byte[] buffer = new byte[1024];
private Type type = Type.SERVER;
private int port;
@Getter @Setter private PacketReceiver packetReceiver;
@Getter private DatagramPacket lastReceivedPacket;
@Getter private DatagramPacket lastSentPacket;
private long lastReceivedTime = 0;
private long lastSentTime = 0;
public Server(int port, PacketReceiver packetReceiver) throws SocketException {
this.datagramSocket = new DatagramSocket(port);
this.packetReceiver = packetReceiver;
this.port = port;
}
public void start(){
this.running = true;
Thread thread = new Thread("udpserver"){
@SneakyThrows
@Override
public void run() {
while (running){
DatagramPacket datagramPacket = new DatagramPacket(buffer, buffer.length);
datagramSocket.receive(datagramPacket);
lastReceivedPacket = datagramPacket;
lastReceivedTime = System.currentTimeMillis();
callReceiver(datagramPacket);
}
}
};
thread.start();
}
@Override
public void stop(){
this.running = false;
if(!datagramSocket.isClosed()){
datagramSocket.close();
}
}
public void sendPacket(DatagramPacket datagramPacket){
try {
datagramSocket.send(datagramPacket);
lastSentPacket = datagramPacket;
lastSentTime = System.currentTimeMillis();
} catch (IOException e) {
e.printStackTrace();
}
}
public void callReceiver(DatagramPacket datagramPacket){
packetReceiver.onPacket(this, datagramPacket, datagramPacket.getAddress(),
new String(datagramPacket.getData(), 0, datagramPacket.getLength()), this.getType());
}
@Override
public Type getType() {
return this.type;
}
@Override
public void sendMessage(InetAddress inetAddress, String message) {
byte[] messageBytes = message.getBytes();
DatagramPacket datagramPacket = new DatagramPacket(messageBytes, messageBytes.length, inetAddress, port);
sendPacket(datagramPacket);
}
@Override
public long getLastReceivedTime() {
return System.currentTimeMillis() - lastReceivedTime;
}
@Override
public long getLastSentTime() {
return System.currentTimeMillis() - lastSentTime;
}
}
I've solved my problem and will post the answer for public reference.
Both endpoints were listening on the same host, on the same port.
They couldn't distinguish each other, so it caused a whole lot of confusion. The client was listening for packets on the same port as the server did. Also the client sent packets on the same port as the server and client listened on it.
So the issue fix was just to choose different listening ports for each instance.
So the client was listening on port 31254 for example and the server was listening on 2132. The client sent the packet to 2132 and the server sent to 31254.
So as iggy guessed.
Thank y'all very much.