Forum: PC-Programmierung Java <-> VBA - unterschiedliche Verhalten


von Roger L. (Gast)


Lesenswert?

Hi zusammen,

ich programmiere derzeit eine Client-Software für die Kommunikation 
zwischen einem Messgerät und einem PC. Die Software (Client, PC) ist in 
Java geschrieben.
Zunächst testete ich das Ganze mit einem VBA-Skript in Excel, um 
möglichst einfach einen Socket aufzubauen.

Hier der Codeausschnitt von VBA, mit dem das Auslesen der Version des 
Messgeräts einwandfrei klappt:
1
x = OpenSocket(Hostname$, Port$)
2
    
3
    'Send IDN request
4
    x = SendCommand("*VERSION?")
5
    retval = ioctlsocket(socketId, FIONBIO, 1)
6
7
    Do
8
        buffer = Space(100)
9
        retval = recv(socketId, ByVal buffer, Len(buffer), 0)
10
        If retval <> 0 And retval <> SOCKET_ERROR Then
11
            reply = reply & Left(buffer, retval)
12
            Exit Do
13
        End If
14
     
15
     DoEvents
16
    Loop Until retval = 0

Nachdem ich obige Routine ausführe, erhalte ich die Version des 
Messgeräts.


Da ich nun das Ganze auf einem PC laufen lassen möchte, welcher kein 
Excel installiert hat, habe ich eine PC-Software geschrieben in Java.

Der Ausschnitt hierfür ist folgender.
Der Code funktioniert einwandfrei mit einem Serverprogramm am localhost 
und am entfernten PC, jedoch nicht mit dem Messgerät, da ich mit diesem 
Java-Programm schlichtweg keine VERSION vom Messgerät empfange.
1
Socket socket = new Socket(IP_Address,Port);
2
        
3
        OutputStream _output = socket.getOutputStream();
4
        PrintStream ps = new PrintStream(_output,true);
5
        
6
        ps.println("VERSION?");  
7
        
8
        InputStream _input = socket.getInputStream();
9
        BufferedReader buff = new BufferedReader(new InputStreamReader(_input));
10
        System.out.println("verf\u00FCgbare Bytes: " + _input.available());
11
12
              while (buff.ready() ) 
13
              {      
14
                   Received_DeviceInfo[i] = ((char)buff.read());
15
                   i++;
16
              }
17
            
18
              String DeviceInfo = new String (Received_DeviceInfo);
19
            
20
              String Devicename = LeftRightMid.left(DeviceInfo,12);
21
        String Firmwareversion = LeftRightMid.mid(DeviceInfo, 13, 9);
22
        String unknown_device_info = LeftRightMid.mid(DeviceInfo, 22,5);    
23
        
24
        lbl_Device.setText(Devicename);
25
              lbl_FirmwareVersion.setText(Firmwareversion);
26
        
27
            if(socket != null)
28
        {
29
          socket.close(); 
30
        }


Woran kann es also liegen, dass es im Excelsheet sowohl am 
Serverprogramm als auch am Messgerät klappt und mit meinem Java-Code 
"nur" auf dem Serverprogramm?


Vielen Dank euch!

von Peter II (Gast)


Lesenswert?

Roger L. schrieb:
> Woran kann es also liegen, dass es im Excelsheet sowohl am
> Serverprogramm als auch am Messgerät klappt und mit meinem Java-Code
> "nur" auf dem Serverprogramm?

vermutlich musst du bei Java auch auf das ende der Nachricht warten, du 
kannst nicht davon ausgehen das alle Daten auf einmal kommen.
Vermutlich kommt bei dir am ende ein \n so lange musst du lesen.

von Roger L. (Gast)


Lesenswert?

Ok gute Idee...

Habe aber soeben mal im Server-Programm sowohl einen String mit \n und 
einen ohnen \n gesendet...bei beiden Fällen habe ich vom Server-Programm 
im Java-Programm den String korrekt empfangen.

Hmm...

von Peter II (Gast)


Lesenswert?

Roger L. schrieb:
> Habe aber soeben mal im Server-Programm sowohl einen String mit \n und
> einen ohnen \n gesendet...bei beiden Fällen habe ich vom Server-Programm
> im Java-Programm den String korrekt empfangen.

das ist davon abhängig, wie die Daten gesendet werden. Wenn der Server 
jedes Byte in ein extra packet steckt, dann geht es bei dir schief.

von Gregor O. (zappes)


Lesenswert?

Mir fällt auf, dass Du im VBA-Code die Anfrage "*VERSION?" schickst, in 
Java aber nur "VERSION?" ohne den Stern am Anfang. Ist das nur ein 
Copy/Paste-Fehler oder steht das auch so im Code?

von Roger L. (Gast)


Lesenswert?

Ja das war ein Copy/Paste-Fehler.

Also ich schreibe bei beiden den gleichen String runter.

Sorry

von db23 (Gast)


Lesenswert?

Versuch doch mal
1
String DeviceInfo = buff.readLine();

statt
1
              while (buff.ready() ) 
2
              {      
3
                   Received_DeviceInfo[i] = ((char)buff.read());
4
                   i++;
5
              }


Allenfalls wäre ein
1
ps.flush()
 auch noch gut um sicherzustellen, dass auch was rausgeht.

Grundsätzlich würde ich mich aber Peter II anschliessen. Vielleicht 
würde dir eine kleine Bibliothek wie z.B. Apache MINA helfen. Reine 
Socket-Kommunikation in Java ist nicht unbedingt lustig.

Im Zweifel hilft auch mal die Kommunikation mit Wireshark zu beobachten.

von Roger L. (Gast)


Lesenswert?

>Versuch doch mal
>...statt...

hi, ich habe es nun versucht, den String vom Server-Programm empfange 
ich schonmal korrekt.

Ich werde es dann am Messgerät ausprobieren, ob es denn dann auch dort 
funktioniert. :)

Das "VERSION?" geht auf jeden Fall richtig "raus", da ich das auch im 
Serverprogramm sehe, dass es empfangen wird.

Danke erstmal für deine/eure Hilfe, ich melde mich!

von Roger L. (Gast)


Lesenswert?

Guten Morgen zusammen!

Gestern habe ich nun versucht den von euch dankend erhaltenen Java-Code 
bzw. den von mir vorher geschriebenen (siehe Eröffnungs-Thread) direkt 
am Messgerät zu testen.
Leider führte beides nicht zum gewünschten Verhalten.

Bei meiner Variante sieht man auf der Konsole des Messgeräts, dass das 
Gerät den Anfrage-String "VERSION?" empfängt, daraufhin auch einen 
Antwortstring an mein Client-Programm zurückschickt.
Dieses Clientprogramm empfängt jedoch nichts, sprich in der 
Konsolenausgabe vom Clientprogramm kommt "verfügbare Bytes: 0".
Auch beim Verwenden von Delaytimes ("Thread.sleep(x)") tut sich keine 
Besserung auf.

Bei der Variante von "db23"
>String DeviceInfo = buff.readLine();
habe ich das Problem, dass sich das Messgerät nach dem Empfangen des 
Strings "VERSION?" sofort "aufhängt" und in einer Endlosschleife 
verharrt und somit keinen Antwortstring schickt.

Ich war gestern drei Stunden an dem Problem gesessen, habe 
Schritt-für-Schritt die Codezeilen auskommentiert. Leider auch hier kein 
Erfolg.


Könntet ihr mir weiterhelfen?


Vielen Dank!

von Gregor O. (zappes)


Lesenswert?

Also, korrekt ist definitiv nur die readLine()-Variante, weil die 
Konstruktion mit ready() sofort stirbt, wenn die Antwort vom Messgerät 
zu lange dauert. Wenn Du schon einen BufferedReader hast, dann benutze 
ihn auch. :) Das available() ergibt an der Stelle auch nur dann Sinn, 
wenn das Timing passt, das kannst Du eigentlich wegwerfen.

Wichtig wäre dann aber, dass das Messgerät unbedingt einen mit \n 
terminierten String schicken oder die Verbindung beenden muss, sonst 
wartet der Reader ewig auf das Ende des Strings. Ist das derzeit der 
Fall?

von Roger L. (Gast)


Lesenswert?

Hallo,

>Wichtig wäre dann aber, dass das Messgerät unbedingt einen mit \n
>terminierten String schicken oder die Verbindung beenden muss, sonst
>wartet der Reader ewig auf das Ende des Strings. Ist das derzeit der
>Fall?

Dann werfe ich als erstes mal die while-Schleife raus und verwende 
stattdessen
>String DeviceInfo = buff.readLine();

Auch die Zeile mit "available" werf ich raus.

Das Messgerät schickt ein "\n" am Ende.


Komisch ist eben, weshalb das Messgerät bei Verwendung von "readLine()" 
in einer Endlosschleife hängt, nachdem es den String "VERSION?" 
empfangen hat.

von Gregor O. (zappes)


Lesenswert?

Roger L. schrieb:
> Komisch ist eben, weshalb das Messgerät bei Verwendung von "readLine()"
> in einer Endlosschleife hängt, nachdem es den String "VERSION?"
> empfangen hat.

Hast Du mal einen Debugger (wahlweise auf Java- oder Messgerätseite) 
verwendet, um rauszukriegen, wer da tatsächlich hängt? Oder mit 
geeigneter Software das Netzwerk gesnifft, um zu sehen, was tatsächlich 
über die Leitungen geht? Irgendwie kommt es mir sehr verdächtig vor, 
dass die sendende Seite hängen soll, ich würde Probleme eher auf der 
Empfängerseite vermuten.

von Udo S. (urschmitt)


Lesenswert?

Roger L. schrieb:
> Komisch ist eben, weshalb das Messgerät bei Verwendung von "readLine()"
> in einer Endlosschleife hängt, nachdem es den String "VERSION?"
> empfangen hat.

Vieleicht fehlt ein abschliessender '\n' in deinem String "VERSION" und 
der Server (Messgerät) wartet darauf?

: Bearbeitet durch User
von Roger L. (Gast)


Lesenswert?

Ok, ich werde es nochmal versuchen...melde mich dann entsprechend.

Gedebuggt habe ich bisher nicht, ich habe aber Wireshark drangehängt. Da 
habe ich gesehen, dass die Client-Software richtig anfragt, der 
Antwortstring auch entsprechend vom Messgerät zurückgeschickt wird, aber 
im Java-Programm nicht ersichtlich ist. (Natürlich im Falle des 
"Nicht-Aufhängens")

Grüße

von Gregor O. (zappes)


Lesenswert?

Roger L. schrieb:
> Natürlich im Falle des
> "Nicht-Aufhängens"

Was ist beim Aufhängen? Kommt die Antwort dann auch und landet nur nicht 
in der Ausgabe oder wird sie gar nicht ert losgeschickt?

von Roger L. (Gast)


Lesenswert?

>Was ist beim Aufhängen? Kommt die Antwort dann auch und landet nur nicht
>in der Ausgabe oder wird sie gar nicht ert losgeschickt?

Da bin ich mir gerade nicht sicher...ich werde die Szenarien nochmal 
genauestens untersuchen und berichten. Leider komme ich erst wieder 
übernächste Woche an das Gerät :-/

Natürlich doof, wenn man das Ganze nicht direkt zuhause testen kann, 
wenn das Messgerät stationär sich wo befindet.

Danke derweil für die Hilfe!!

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Zur Analyse: Nimm Wireshark oder Ethereal und sieh Dir die 
Netzwerkpakete an, die zum Gerät gesendet werden; vergleiche den Inhalt 
der Pakete, die das VBA-Programm erzeugt mit dem des Java-Programmes, 
und Du müsstest die Problemstelle eingrenzen können.

von Roger L. (Gast)


Lesenswert?

Ok mache ich!

von Läubi .. (laeubi) Benutzerseite


Lesenswert?

Lass doch mal die ganzen BufferStream etc. weg, das ist hier für die 
Fehleranalyse nicht zielführend. Versuch mal folgendes Testprogramm:
1
Socket socket = new Socket(IP_Address, Port);
2
OutputStream os = socket.getOutputStream();
3
InputStream is = socket.getInputStream();
4
System.out.println("Write...");
5
os.write("VERSION?\r\n".getBytes());
6
os.flush();
7
int read;
8
System.out.println("Read...");
9
while((read = is.read()) > -1) {
10
    System.out.println(Integer.toHexString(read & 0xFF)+": "+((char)read));
11
}
12
System.out.println("Done!");

von Eric B. (beric)


Lesenswert?

Mal 2 wilde Ideeen:
- '\n' wird mal als CR/LF, mal als nur CR interpretiert. Wie macht Java 
das?
- Java benutzt grundsätzlich Unicode für Strings, nicht ASCII. Schickt 
dein Java-Programm wirklich
1
{ 0x2A, 0x56, 0x45, 0x52, 0x53, 0x49, 0x4E, 0x3F, 0x0D, 0x0A }
oder vielleicht doch
1
{ 0x00, 0x2A, 0x00, 0x56, 0x00, 0x45, 0x00, 0x52, 0x00, 0x53, 0x00, 0x49, 0x00, 0x4E, 0x00, 0x3F, 0x00, 0x0D, 0x00, 0x0A }
?

von Gregor O. (zappes)


Lesenswert?

@beric

Da er beim Erzeugen seines PrintWriter kein Encoding angegeben hat, wird 
das Standardencoding seines Systems benutzt, also vermutlich 8859-1, 
8859-15, cp1251 oder UTF-8 - in allen Fällen käme das selbe wie bei 
ASCII raus, da der String ja nur einfache Zeichen enthält. Er sagt ja 
auch, dass der Request noch richtig ankommt.

Der BufferedReader würde sowohl \n als auch \r\n als Zeilenende 
erkennen, daran sollte es nicht liegen.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.