Android Client - Integer versenden (falsche Werte beim Server)

  • 8 Antworten
  • Letztes Antwortdatum
S

StillLovingYou

Neues Mitglied
0
Ich habe ein kleines Problem mit einer Client-Anwendung, an der ich z.Z. sitze und zwar, möchte ich mit dem Client einen Integer an einen Server auf meinen Computer senden und den Wert des Integers zu Testzwecken auf meinem Computer ausgeben lassen. Das Senden der Daten an sich klappt einwandfrei, allerdings wird auf meinem Computer ein falscher Wert ausgegeben.
Hier mal der CodeSchnipsel, um den es geht:
Code:
package com.example.homework;

import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;
import java.net.UnknownHostException;

public class MyClient extends Thread {
    private String ip;
    private int port;
    
    public static final int SEND_THIS_VALUE = 11413;
    
    public void run(){
        try {
            Socket sock = new Socket(ip, port);
            
            DataOutputStream dOS = new DataOutputStream(sock.getOutputStream());
            
            dOS.writeInt(SEND_THIS_VALUE);
            
            sock.close();
        } catch (UnknownHostException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
    
    MyClient(String ip, int port){
        this.ip = ip;
        this.port = port;
    }
    
}
Zum Server:
Dieser ist nicht in Java, sondern in einer Basic-Sprache geschrieben.
Er ermittelt, ob sich ein Client verbunden hat, ob ein Client die verbindung zum Server gekappt hat und ob der client Daten an den Server gesendet hat. Diese 3 Dinge funktionieren tadellos. Auch das Ausgeben der Daten funktioniert soweit, nur mit dem Problem, dass er mir anstelle der Zahl "11413" die Zahl "-1792278528" ausgibt.

Noch eine kleine Erklärung zum Server:
Wenn der Server merkt, dass Daten empfangen wurden, dann speichert er diese in einem 4 Byte großen reservierten Speicherbereich. Danach liest er den Speicherbereich aus und gibt mir den darin enthaltenen Wert aus.

Ich kann mir nicht vorstellen, dass das Problem am Server-Programm liegt (aber man weiß ja nie, daher die kleine Erklärung dazu).

Jetzt wollte ich mal fragen, ob jemand an meinem Client-Code oder an meiner Server-Beschreibung erkennt, warum ein falscher Wert zurückgeliefert wird.
 
Du bist Opfer der Architektur geworden:
Die tatsächliche Bytereihenfolge vom Client und deinem Server ist unterschiedlich (bigendian vs. lowendian, (siehe auch Byte-Reihenfolge - Wikipedia))

Ich versuche zu erläutern:
11413 = 00000000 00000000 00101100 10010101 (in lowendian)

wenn du das nun Byteweise drehst (= Unterschied zwischen big- und lowendian), bekommst du:
10010101 00101100 00000000 00000000 = -1792278528 (wenn du 32 Bit signed verwendest).

Windows-Systeme sind in der Regel lowendian, während Android, soweit ich weiß, bigendian verwendet.
 
Zuletzt bearbeitet:
Ok, deine Antwort war schonmal sehr aufschlussreich, danke dafür. Gibt es denn eine Möglichkeit, das vom client parsen/konvertieren zu lassen?
 
Ich habe jetzt mal einen Lösungsansatz ausprobiert.
Ich habe anstatt eines Integers nun ein Char-Array mit 4 Werten versendet.
der abgewandete Code sieht folgendermaßen aus:
Code:
package com.example.homework;

import java.io.IOException;
import java.io.PrintWriter;
import java.net.Socket;
import java.net.UnknownHostException;

public class MyClient extends Thread {
    private String ip;
    private int port;
    
    public static final char[] SEND_THIS_VALUE = {149,44,0,0};
    
    public void run(){
        try {
            Socket sock = new Socket(ip, port);
            
            PrintWriter sender = new PrintWriter(sock.getOutputStream());
            
                sender.print(SEND_THIS_VALUE);
                sender.flush();
            
            sock.close();
        } catch (UnknownHostException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
    
    MyClient(String ip, int port){
        this.ip = ip;
        this.port = port;
    }
    
}
Solange jeder der 4 Werte im Char-Array < oder = 127 ist funktioniert alles super aber sobald einer dieser Chars den Wert von 127 überschreitet, gibt mein Server wieder falsche Werte zurück. Bei einem Byte-Typ wäre das ja noch verständlich gewesen, da dieser ja nur Werte von -128 bis 127 verwendet aber meines Wissens verwendet ein Char doch Werte von 0 bis 255, also warum funktioniert das nicht? Gibt es da vieleicht schon wieder etwas Java-Internes was anders funktioniert als auf anderen Systemen oder liegt der Fehler dieses mal an meinem Code?

Der ursprüngliche Beitrag von 16:41 Uhr wurde um 17:14 Uhr ergänzt:

Nun gut, ich habe das Problem jetzt Serverseitig gelöst, indem ich einfach einen 2. Speicherbereich reserviert habe und dann jedes einzelne byte des 1. Speicherbereichs in umgekehrter reihenfolge darin abgespeichert habe.

Allerdings würde ich mich über eine Antwort auf meine letzte Frage (bzgl. des Char-Arrays und das Problem mit den Werten > 127) sehr freuen.
 
Zuletzt bearbeitet:
Übertrag es doch einfach als Zeichenkette, also "11413". Ich glaube, die paar Byte machen es nicht aus ;)
 
Hab ich auch schon drüber nachgedacht aber ich bin ein Geizhals, wer das Byte nicht ehrt ist das TB nicht wert ^^

Außerdem besteht das Problem darin, das es möglicherweise noch dazu kommen wird, das ich weitaus mehr Daten in Integer Form versende, dass hier war nur eine kleine Experimentier-Phase. Wenn ich dann aufeinmal irgendwann die 100- oder 1000fache menge an Daten sende, dann summiert sich das mit der Zeit und wie gesagt, das Problem habe ich ja jetzt durch eine kleine Erweiterung an meinem Server-Prog gelöst. Das (mir unschlüssige) Verhalten des Char-Arrays ist jetzt nur noch eine reine Neugier-Frage.
 
Warum Konvertierst du den int nicht einfach:
ungefähr so:
Code:
publi int little2Big(int i) {  
   int b0,b1,b2,b3;    
   b0 = (i&0xff)>>0;   
   b1 = (i&0xff00)>>8;    
   b2 = (i&0xff0000)>>16;    
   b3 = (i & 0xff000000) >>> 24;    
   return ((b0<<24)|(b1<<16)|(b2<<8)|(b3<<0)); 
}
oder noch einfacher:
Code:
 public static int ConvertBIG2Little(int x) { 
        ByteBuffer buffer = ByteBuffer.allocate(8);  
       buffer.order(ByteOrder.BIG_ENDIAN);  
        buffer.putInt(x);  
       buffer.order(ByteOrder.LITTLE_ENDIAN);  
        return buffer.getint(0);  
   }
 
Zuletzt bearbeitet:
char in java ist unsigned 16bit
 
Jetzt kommt mein Senf auch noch dazu.
Dein Java Code im ersten Post ist richtig.
DataOutputStream.writeInt() wandelt in Network Byte Order um, das ist auf jedenfall die richtige Bitfolge bei der Übertragung über ein Netzwerk. Der Empfänger ist dafür zuständig von der Network Byte Order in seine jeweilige Host Byte Order umzuwandeln. Schau dir entsprechende ntohl() und ntohs() Funktionen in Basic an um die richtige Bytefolge auf dem Zielrechner zu erhalten.
 

Ähnliche Themen

M
Antworten
21
Aufrufe
1.363
swa00
swa00
Mr-Fisch
Antworten
5
Aufrufe
968
migi01
migi01
Mr-Fisch
Antworten
8
Aufrufe
1.007
Mr-Fisch
Mr-Fisch
M
Antworten
9
Aufrufe
793
mkuz24
M
A
Antworten
5
Aufrufe
697
swa00
swa00
Zurück
Oben Unten