UDP Packet content changes while transmitting

By : rapgru
Source: Stackoverflow.com
Question!

I'm programming an Server-Client Software, where the client connects to the server with an port request, the server opens a new port and sends back the new port number. Then the client communicates with an RSA shared AES key encryption and the port from the port request.

Well, it should be like that.

I had the program already running, only one client could connect to the server, and everything worked fine. But now I'm sending an "portreq" String to the server which should give a port reply. But when i check, if the incoming request is a "portreq" it gives me false. If i do same with .contains it gives me true. That's the first problem, and secondly:

When the server converts the port-Integer into an String and sends it, i can't transform it into a int again on the client-side:

java.lang.NumberFormatException: For input string: "6002������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������"
    at java.lang.NumberFormatException.forInputString(NumberFormatException.java:65)
    at java.lang.Integer.parseInt(Integer.java:580)
    at java.lang.Integer.parseInt(Integer.java:615)
    at application.PowerPanelController.addDataToCpu(PowerPanelController.java:360)
    at application.PowerPanelController.lambda$0(PowerPanelController.java:143)
    at application.PowerPanelController$$Lambda$200/357277047.handle(Unknown Source)
    at com.sun.scenario.animation.shared.TimelineClipCore.visitKeyFrame(TimelineClipCore.java:226)
    at com.sun.scenario.animation.shared.TimelineClipCore.playTo(TimelineClipCore.java:167)
    at javafx.animation.Timeline.impl_playTo(Timeline.java:176)
    at javafx.animation.AnimationAccessorImpl.playTo(AnimationAccessorImpl.java:39)
    at com.sun.scenario.animation.shared.InfiniteClipEnvelope.timePulse(InfiniteClipEnvelope.java:110)
    at javafx.animation.Animation.impl_timePulse(Animation.java:1102)
    at javafx.animation.Animation$1.lambda$timePulse$25(Animation.java:186)
    at javafx.animation.Animation$1$$Lambda$186/1977464318.run(Unknown Source)
    at java.security.AccessController.doPrivileged(Native Method)
    at javafx.animation.Animation$1.timePulse(Animation.java:185)
    at com.sun.scenario.animation.AbstractMasterTimer.timePulseImpl(AbstractMasterTimer.java:344)
    at com.sun.scenario.animation.AbstractMasterTimer$MainLoop.run(AbstractMasterTimer.java:267)
    at com.sun.javafx.tk.quantum.QuantumToolkit.pulse(QuantumToolkit.java:447)
    at com.sun.javafx.tk.quantum.QuantumToolkit.pulse(QuantumToolkit.java:431)
    at com.sun.javafx.tk.quantum.QuantumToolkit.lambda$runToolkit$363(QuantumToolkit.java:298)
    at com.sun.javafx.tk.quantum.QuantumToolkit$$Lambda$42/317723766.run(Unknown Source)
    at com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:95)

Which i don't get because the String looks pretty much the same as i send it.

Here's my client side send and receive function

private String sendCommandNoAES(String command)
{
    byte[] outData = new byte[1024];
    byte[] inD = new byte[1024];
    String message = "";
    try
    {
        // create Socket
        DatagramSocket socket = new DatagramSocket();
        // build Packet
        InetAddress serverIP = InetAddress.getByName(PowerPanelMain.ip);
        outData = command.getBytes();
        DatagramPacket out = new DatagramPacket(outData,outData.length, serverIP, PowerPanelMain.port); // send packet
        socket.send(out);
        logger.info("Sent an " + command + " Request non encrypted to " + PowerPanelMain.ip + ":" + PowerPanelMain.port);
        // Receive answer
        byte[] inData = new byte[1024];
        DatagramPacket in = new DatagramPacket(inData,inData.length);
        socket.receive(in);
        inD = in.getData();
        message = new String(inD,0,inD.length);
        // Close Socket
        socket.close();

        logger.info("Go answer " + message + " from " + in.getAddress().toString() + ":" + in.getPort());
    }
    catch(Exception ee)
    {
        logger.error("Error while requesting data from server \n" + getStackTrace(ee));
        return "offline";
    }
    return message;
}

This is where i send the portreq:

String portString = sendCommandNoAES("portreq");
int port = Integer.parseInt(portString);

Thats the server code:

byte[] inData = new byte[1024];
        byte[] outData = new byte[1024];
        String message;

        DatagramSocket socket = null;
        try
        {
            socket = new DatagramSocket(port);
            System.out.println("Bound to " + port);
            //JOptionPane.showMessageDialog(null, "Bound to " + String.valueOf(port), "Yeay", JOptionPane.OK_CANCEL_OPTION);
        }
        catch(Exception ee)
        {
            JOptionPane.showMessageDialog(null, "Error occured! \n#002", "Error #002", JOptionPane.OK_CANCEL_OPTION);
        }

...

DatagramPacket in = new DatagramPacket(inData,inData.length);
                socket.receive(in);
                InetAddress senderIP = in.getAddress();
                int senderPort = in.getPort();
                byte[] inc = in.getData();
                message = new String(inc,0,inc.length);

                System.out.println("Got " + message + " from " + senderIP + ":" + senderPort + " (byte array: " + inc.toString());

...

if(message.contains("portreq"))
                    {
                        System.out.println("Creatinfg answer");
                        outData = String.valueOf(portcount).getBytes();
                        DatagramPacket out = new DatagramPacket(outData,outData.length, senderIP, senderPort);
                        socket.send(out);

                        System.out.println("Sent " + String.valueOf(portcount));

                        UDPTraffic udpt = new UDPTraffic(portcount, this.mode);
                        udpt.start();
                        portcount++;
                    }

I'm really thankful to anyone who can solve/explain me why this is happening :D

By : rapgru


Answers

You are sending a string of one size, yet on the other side you are reading the string of 1024 bytes - which you never sent. This will not do. You should either serialize string using serialize() method, or, if you want to send raw string bytes, send string length as a separate part of the message.

By : SergeyA


inD = in.getData();

This merely reasserts the same value. Remove.

message = new String(inD,0,inD.length);

Wrong. You're ignoring the actual length of the received datagram. Change to:

message = new String(in.getData(), in.getOffset(), in.getLength());
By : EJP


This video can help you solving your question :)
By: admin