简体   繁体   中英

Java UDP socket echoing bytes

I'm writing an android source(but just java) to communicate with some embedded device which acts as a server.

I am sure that my UDP datagrams are arriving to the device since I can observe the device state changing.

But the problem is that I am failing to get response from the server. Not receiving nothing, but I just get an echo of what I sent. My source is as below.

 public void sendSnapShot(View view) {
 //send a udp datagram to the server.
    new AsyncTask<Void, Void, Void>() {
        @Override
        protected Void doInBackground(Void... voids) {

            try {
                Log.e("Test", "send sendSnapShot onLine");

                DatagramSocket clientSocket = new DatagramSocket();

                byte[] sendData = new byte[1024];

                String sentence = "$SNAPSHOT";

                sendData = sentence.getBytes();


                DatagramPacket sendPacket = new DatagramPacket(sendData, sendData.length, InetAddress.getByName("192.168.5.255"), 9999);
                clientSocket.send(sendPacket);

                Log.e("Test", "Sent sendSnapShot REQUEST");

            } catch (Exception e) {
                Log.e("Test", "e", e);
            }

            return null;
        }
    }.execute();
}

The above code is about transfering datagram to the server. On the start of the application, the below thread will be started to listen for any datagram sent by the server.

 private class ListenerThread implements Runnable {
    //listen for incoming datagrams.
       @Override
       public void run() {
           DatagramSocket serverSocket = null;
           try {
            InetAddress serverAddr = InetAddress.getByName("192.168.5.255");
            serverSocket = new DatagramSocket(9999, serverAddr);

            while (true) {
                try {

                    byte[] receiveData = new byte[1024];

                    DatagramPacket receivePacket = new DatagramPacket(receiveData, receiveData.length);
                    serverSocket.receive(receivePacket);
                    receivePacket.getLength();
                    String receivedData = new String(receivePacket.getData(), 0, receivePacket.getLength());
                    if (!receivedData.startsWith("!HEARTBEAT")) {
                        Log.e("Test", "Received : " + receivedData);
                    } else {
                        Log.e("Test", "Received : HEARTBEAT");
                    }
                } catch (Exception e) {
                    Log.e("Test", "FROM SERVER ", e);

                }
            }
 } catch (Exception e) {
            Log.e("Test", "Exception", e);
            }
        }
    }

The guy who wrote the server code(probably written in c++) says that he is getting response in his test case, so what may I be missing? Is there a possiblity that the above code will ignore any datagram from the server and echo bytes sent from my code?

=============================================================================

I've changed my code according to the answer. I no longer use the listening thread anymore. Here's my code.

public void sendBattery(View view) {
        new AsyncTask<Void, Void, Void>() {
        @Override
        protected Void doInBackground(Void... voids) {

            try {
                Log.e("Test", "send Battery onLine");

                DatagramSocket clientSocket = new DatagramSocket(9999, InetAddress.getByName("0.0.0.0"));

                byte[] sendData = new byte[1024];
                byte[] receivedata = new byte[1024];

                String sentence = "$S0B255";
                DatagramPacket receivePacket = new DatagramPacket(receivedata, receivedata.length);

                sendData = sentence.getBytes();
                String receivedData = " ";
                DatagramPacket sendPacket = new DatagramPacket(sendData, sendData.length, InetAddress.getByName("192.168.5.1"), 9999);
                clientSocket.send(sendPacket);
                do{
                    clientSocket.receive(receivePacket);
                    receivedData = new String(receivePacket.getData(), 0, receivePacket.getLength());
                    Log.e("Test", receivedData +  ", IP CHECK Sender:  : " + receivePacket.getAddress().toString() + ", port : "+ receivePacket.getPort());
                }while(true);
               // Log.e("Test", "Sent BATTERY REQUEST COMPL");
            } catch (Exception e) {
                Log.e("Test", "e", e);
            }

            return null;
        }
    }.execute();
}

According to the heartbeat byte(making it to a string will make it "!HEARTBEAT") i'm receiving, the sender is 192.168.5.1. But still, I only get heartbeat bytes only. What shall I be missing?

  • You are receiving your own datagrams, because you are broadcasting (to 192.168.5.255). You should use the device's actual IP address.
  • You should not create a new datagram socket per send. (You are never closing that socket, so you are also leaking sockets.)
  • You should send the datagrams from the same socket you are receiving on. The device will (should) reply to the IP:port the request came from, and at present that's different every time, and you're losing the sending socket that's bound to that port, and the sending IP:port isn't the IP:port you're listening on, so you don't hear it.
  • You should not bind your listening socket to a specific IP address, and certainly not to a broadcast address. I'm surprised it works.

What EJP was saying was right about everything.

The fixed code above(the most below code snippet) which included tips from him will work, without having to receive any broadcast by myself.

I thought the issue was unresolved since I still didn't get any response from the device, but it was the device(not made by me) which was malfunctioning. The above code will work good.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM