[Solved] UPD not really fire and forget

First off, I never been good at networking. I have manage to get TCP/IP to work, but never really used UDP, so sorry for any beginner mistakes. Anyway, I have starter to make my own game, and decided to use UDP, since it doesn’t really matter if some data get lost. However, so far it’s not really as fire and forget as I had hoped.

This is difficult for me to explain, but I’ll do my best. So I created a “Client” object, which contains a simple send method, which sends data via this little code

byte[] bytes = data.getBytes();
DatagramPacket pack = new DatagramPacket(bytes, bytes.length, adress, port);
client.send(pack);

then I assumed the server would send the data back via the same DatagramSocket, and I knew that .receive freezes the method/game until it manage to receive something. So I made a different thread for it

@Override
    public void run() {
        if(true){
            try{
                byte[] buffer = new byte[1024];
                DatagramPacket pack = new DatagramPacket(buffer, buffer.length);  
                client.receive(pack);
                
                String sData = new String(pack.getData());
                read(sData, pack);
                
            }catch(Exception e){
                e.printStackTrace();
            }
        }
    }

But it never receive’s anything, I had to change my send code for me to be able to receive the message from the server.

public void send(InetAddress adress, int port, String data, boolean receive){
        try{            
            //Send data to the server
            byte[] bytes = data.getBytes();
            DatagramPacket pack = new DatagramPacket(bytes, bytes.length, adress, port);
            client.send(pack);
            
            //This is my make shift code to get the reply from the server.
            //Sadly if this doesn't get a reply it freezes the game.
            if(receive){
                //Wait to receive an answer
                byte[] buffer = new byte[1024];
                DatagramPacket back = new DatagramPacket(buffer, buffer.length);
                client.receive(back);
                read(new String(back.getData()), back);
            }
            
            //Somehow it doesn't send the data without this
            Thread.sleep(1);
            
        }catch(Exception e){
            e.printStackTrace();
        }
    }

Am I missing something here, if UDP is suppose to fire and forget, why do I need to wait for a response? or am I not understanding something here?

P.S The server send code is

public void send(String data, InetAddress address, int port){
        try{
            //Just a simple send data function, not much to it.
            byte[] sendData = data.getBytes();
            DatagramPacket send = new DatagramPacket(sendData, sendData.length, address, port);
            server.send(send);
        }catch(IOException e){
            
        }
    }

With datagram sockets you don’t send and receive with the same socket (at least I’m pretty sure that’s the case). So you’d need a send socket and a receive one. You also need to send data to the receiving datagram socket port (they won’t share the same port).

Edit 1: I am assuming you’re on the same machine testing both. Once you have bound a socket to a port you can not bind another to the same one, so you’ll need to know the ports of both the client and the server.

Edit 2: I’ve never used one socket to both send and receive data, so I’m not sure if receive “blocks the socket” from sending or not. I do know that receive blocks the thread (as you indicated).

Yes, I test on the same machine.

So I changed do the Client object now have a DatagramSocket too, and got another problem. That socket only resives the first message it gets, and then it stops working. Even if the server keeps sending data.

It’s not much, but I get “Client: waiting…”, and then the data that was received. But it never loops back around.

    @Override
    public void run() {
        //This code was meant to receive the messages from the server, so the game didn't freeze if it didn't get any.
        if(true){
            try{
                System.out.println("Client: Waiting...");
                byte[] buffer = new byte[1024];
                DatagramPacket pack = new DatagramPacket(buffer, buffer.length);  
                server.receive(pack);
                
                System.out.println(new String(pack.getData()));
                //read(new String(pack.getData()));
            }catch(Exception e){
                e.printStackTrace();
            }
        }
    }

EDIT: I’m testing another solution, each Client object, will have two client sockets. It connects to the server with both, and then the server uses one of them as a receiver and the other as sender.

EDIT 2: Nvm, it didn’t work

The comment in your code was really nice, as I think I understand why you were using an ‘if’-loop now, instead of a while loop.

First off: That you only get one packet is a good thing, since that means the code does his work. That you don’t get more is logical, since you exit the runnable right after.
To keep receiving messages, use a ‘while’ instead of an ‘if’.

But then your comment comes in, telling us that your game will freeze if you use a while-loop in that place. Have you tried using a Thread.sleep(1) every iteration, or can it be that you are not running it by ‘new Thread(runnable).start();’ ? Since the whole game freezing because of another thread is highly unlikely if I remember correctly.

Good point, it could have been impossible to send packets while you are receiving them, both on the same port /socket.

Has been a long time since I touched UDP though, so don’t take my word for granted :stuck_out_tongue:

It was meant to be a while loop all along, I simply did a mistake. Sadly my current code just allow local IP addresses. I done everything I can, but I can’t get it to work over the net. Soon I just give up and use TCP anyway.

Did you port-forward the port for UDP on the listener (the server)? And I assume you don’t bind the client sockets to ports do you?

Giving up? How about this then: http://www.jfastnet.com/ it’s from a member on our forum. (Haven’t used it myself though)

Yes, I have port forward the two ports I’m using, and even tried turning off my firewall (including the one in the router). The strange thing is, it’s always the Clients server’s port that don’t get any reply, except when I use 127.0.0.1 or 192.168.10.220

Call my stubborn, but I don’t like using libraries. I’ll try to solve this a bit longer before I move to TCP.

One thing that could help is not thinking of it in terms of client/server.

I would just set up a client(node) that can send and receive packets to and from itself. Then, once you have that node receiving the packets that it’s sending write code to support launching another node on the same machine and have them send an receive packets to each other.

Make sure you can tell each node which ports you want them to bind to and be able to tell them about the other’s port number, you can use InetAddress.getLocalPort() to verify the port number.

Once that works you should be able to move to multiple machines. The only thing you need to remember is that for each client you should have a default port to send and receive on.

After that you should be able to throw a server in there no problem.

Okay, so I re-wrote my Server and Client objects, then setup the sockets I had when I started this thread, and now it works perfectly. I have no idea why, but I guess I messed up the send or receive methods yesterday, and now when I re-coded them, I didn’t. I even send the .jar to a friend which live in another country, and while we get a ping around 400, I still get the messages.