char-Array auslesen in recv-Methode vom TCP/IP Server C++



  • Furble Wurble schrieb:

    Moin!

    Das Problem, dass es zu lösen gilt: in welchem Format werden die Daten angeliefert?
    Die Daten kommen von Matlab, richtig?
    Du hast das Skript* für Matlab geschrieben, richtig?
    Irgendwo in dem Skript wird fwrite() aufgerufen, richtig?
    Und aus diesem Aufruf ergibt sich, wie die 2 Zahlen codiert sind, die recv() ausliest.
    Deswegen wäre die Stelle in dem Matlab-Skript mit fwrite() wichtig.

    Einen Schuß in's Blaue habe ich ja in meinem Posting vom 12.08 9:15 mal gemacht. Hast Du das gar ausprobiert?

    😉 k.A. ob sich das Skript nennt.

    Hallo!
    Der Lösungsansatz von dir hat leider nicht geklappt. Da passiert gar nichts. Der Lösungsansatz von "Caligulaminus" hat mich aber weiter gebracht. das funktioniert so, wenn ich das Programm in der Konsole laufen lasse! Super.
    Jetzt sitze ich gerade an Matlab und versuche das zu implementieren. Ich schaue mal wegen fwrite(). Bis jetzt sehe ich da nichts von.Ansonsten poste ich gleich mal den Matlab Code.



  • Caligulaminus schrieb:

    Nach der Lektüre dieses Posts denke ich an:

    ...
    int kanalID, Intensity;
    char comma;
    std::stringstream ss(recvbuf);
    ss >> kanalID >> comma >> Intensity;
    ...
    

    baronsocke schrieb:

    Der Lösungsansatz von "Caligulaminus" hat mich aber weiter gebracht. das funktioniert so, wenn ich das Programm in der Konsole laufen lasse! Super.

    Da bin ich wohl etwas spät eingestiegen, und habe nicht konzentriert genug gelesen.
    Caligulaminus hat das besser gemacht... 😉

    Nur aus Neugier: poste doch bitte trotzdem den Matlab-Code, der für das Schreiben verantwortlich ist.



  • Hier mein Matlab Code. In einem extra Skript, rufe ich die Klasse Licht auf mit:

    obj = Licht (5,1000); //(Kanal = 5, Intensität = 1000)

    classdef Licht
    
        properties
    
            target   ='E:\msteuerung\Matlab';
            batPath;
            channelID;
            intens;
    
        end
    
        methods
                function obj=Licht(channelID,intens)
                if(~exist(obj.target, 'dir'))
                    mkdir(obj.target);
                end;
                obj.channelID = channelID;
                obj.intens    = intens;
                obj.batPath   = fileparts( mfilename('fullpath'));
    
                cmd  = ['sendCmd.bat ' , int2str(channelID),int2str(intens)];
    
                oldP = pwd; % pwd: identify current folder, returns the current folder as a string to currentFolder
                cd(obj.batPath); % cd(newFolder): change current folder to newFolder
                [ok, res] = system(cmd); % system: execute operating system command and return output
                cd(oldP);
                if(ok==2)
                    oldP = pwd;
                    cd(obj.batPath);
                    system('startServer.bat');
                    cd(oldP);
                end;
            end; 
        end  
    end
    

    Die sendCmd.bat Datei ist:

    @echo OFF
    echo %1 | ncat 127.0.0.1 27015
    

    Die startServer.bat Datei ist:

    @echo off
    start "" "cmd /c ConsoleApplication1.exe"
    

    Wenn ich das ganze ohne Matlab laufen lasse (sondern über die Konsole). Funktioniert es einwandfrei. Beim Aufruf "10,1000" in der Konsole wird der Kanal 10 de Lichtquelle auf Intensität 1000 gestellt.

    Wenn ich es nun über Matlab machen möchte funktioniert es noch nicht.
    Wenn ich eingebe "5,1000", dann steht in meiner cmd-datei: 'sendCmd.bat 51000'
    Meine Ausgabe:
    Bytes received <iResult>: 8
    51000
    51000
    -858993460

    Hier habe ich schon alles probiert: Ein Komma zwischen die Zahlen 5 und 1000 bewirkt:
    Bytes received <iResult>: 4
    5
    5
    -858993460

    Übergebe ich von vornherein einen string im ganzen ('5,1000'), kommt das Gleiche wieder:
    Bytes received <iResult>: 4
    5
    5
    -858993460

    Ich brauche ein Komma zwischen beiden Werten, da die Lösung von "Caligulaminus" darauf aufbaut.
    Es kommen scheinbar nicht alle Bytes an. Für die Werte "5,1000" müssten 7 Bytes ankommen: 6 für die Zeichen und das Schlusssymbol '/0', oder?



  • Und was hat es mit der Zahl

    -858993460

    am Ende auf sich? Wo kommt die denn her und was bedeutet sie?



  • Aha.
    Warum denn dieser Umweg über ncat? Matlab bietet doch auch tcp/ip an.
    Die Lampe ist der Server, oder? Der sollte doch eh laufen....


  • Mod

    baronsocke schrieb:

    Und was hat es mit der Zahl

    -858993460

    am Ende auf sich? Wo kommt die denn her und was bedeutet sie?

    ist CCCCCCCC in hex. Also vermutlich mal nicht initialisierter Speicher o.ä.



  • Und was kann ich nun tun, damit die Zahlen richtig in der recv-Methode ankommen? Über die Konsole funktioniert es ja wunderbar. Da gebe ich ja den selben ncat-Befehl ein und danach die Werte 10,1000. Warum klappt das denn nicht in Matlab?
    Ich habe auch schon in der sendCmd.bat Datei echo %2 oder echo %3 ausprobiert... Auch nichts.

    Ein wissenschaftlicher Mitarbeiter hat das mit ncat eingerichtet. Es funktioniert ja, aber die Zahlen kommen aus Matlab scheinbar noch nicht richtig an:(
    Die Lampe müsste der Server sein. Sie erhält über die recv-Methode die Daten.

    Liegt es am nicht initialisierten Speicher? Was muss ich dagegen tun?



  • Ich würde sagen, da fehlt die Nullterminierung.
    Hier hast Du noch eine drin gehabt.



  • Das 0xCCCCCCCC bekommst Du mit Sicherheit weg. Keine Panik.
    (Ich hoffe an dieser Stelle, dass man noch normal mit Dir reden kann und du nicht morgen abgeben musst!) 😉

    Meinst Du nicht, dass Du es schaffst, tcp/ip direkt aus Matlab anzusprechen? (http://www.mathworks.de/de/help/instrument/tcpip.html)
    Erwähnten "wissenschaftlichen Mitarbeiter" hättest Du dann schonmal überholt.



  • Die Terminierung ist weiter vorhanden. So sieht aktuell meine recv-Methode aus:

    iResult = recv(ClientSocket, recvbuf, recvbuflen, 0);
    			if (iResult > 0) {
    				printf("Bytes received (iResult): %d\n", iResult);
    
    				recvbuf[iResult] = '\0';
    				printf(recvbuf);
    
    				std::stringstream ss(recvbuf);
    				ss >> channel >> comma >> intens;
    				std::cout << channel << std::endl;
    				std::cout << intens << std::endl;
    				led->setChannelIntensity(channel,intens,status);
    


  • Ich könnte auch den CPP-Code des TCP/IP Servers posten, aber das ist ein längerer Code und das möchte ich keinem zumuten.



  • Es sieht so aus, als würde die recv-Methode nicht alle Bytes empfangen? Stimmt das? Wie kann ich gewährleisten, dass alle Daten empfangen werden?



  • Sicher dass

    cmd  = ['sendCmd.bat ' , int2str(channelID),int2str(intens)];
    

    macht was du denkst?
    ich glaube kaum. Denn das komma zwischen den beiden int2str landet bestimmt nicht im parameter string

    Es sollte vermudlich eher so sein

    cmd = ['sendCmd.bat ' , int2str(channelID)**+','+**int2str(intens)];

    wie auch immer man in Matlab strings konkatiniert.



  • Ne das ist ein Schreibfehler. Den habe ich schon korrigiert gehabt. ich habe alles möglich probiert...

    cmd = [’sendCmd.bat ', num2str(channel), num2str(intens)]
    //ohne Komma

    cmd = [’sendCmd.bat ', [num2str(channel), ',’ ], num2str(intens)]
    //mit Komma und 2 Strings

    cmd = [’sendCmd.bat ', [num2str(channel), ',’ , num2str(intens)] ]
    //mit Komma und 1 String

    Wenn ich 10,1000 ausgebe...: in der recv-Methode heißt es, es kommen nur 4 Bytes an. Die 5 wird und das Komma wird korrekt ausgegeben. Die 1000 nicht. Die Ausgabe heißt dann "-858993460"



  • Was ist denn das für eine Abschlußarbeit?

    Wenn das irgendwie mit Informatik zu tun hat, würde ich erwarten, dass Du Dich ein wenig in Matlab einliest, bevor Du jetzt weiter hin und her probierst.

    Wenn ich das gerade richtig gelesen habe, könnte Dein Constructor z.B. so aussehen:

    function obj=Licht(channelID,intens)
            if(~exist(obj.target, 'dir'))
                mkdir(obj.target);
            end;
            obj.channelID = channelID;
            obj.intens    = intens;
            obj.batPath   = fileparts( mfilename('fullpath'));
            conn = tcpip('127.0.0.1', 2015);
            try
              fopen(conn);
            catch exc1
              % evtl laeuft der Server nicht?
              oldP = cd(obj.batPath);
              system('startServer.bat');
              cd(oldP);
            end
            try
              fopen(conn);
            catch exc2
              delete(conn);
              rethrow(exc2);
            end
            fwrite(conn, [channelID, intens], 'int32', 0, 'ieee-be');
            fclose(conn);
            delete(conn);
          end;
    

    Ich kann das nicht testen, ich habe auch gar keine Ahnung von Matlab, aber ich kann lesen - in diesem Fall die Matlab Dokumentation im Netz.*

    Mit dem Code solltest Du jetzt 2 32Bit Ganzahlen in network byte order (big endian) empfangen.
    Damit kann dann jeder hier was anfangen und Dir sagen, wie Du die aus dem char[] liest, den recv() füllt.

    😉 zugegeben wird das Verstehen von neuen Programmiersprachen einfacher, wenn man schon eine kann - insofern bin ich hier leicht im Vorteil...



  • Matlab nimmt grundsaätzlich einen Gleitkommazahlentyp mit doppelter Genauigkeit. D.h. da muss noch gecastet werden...

    Wirklich schade, dass ich kein Matlab habe... 😞


Anmelden zum Antworten