Dateiübertragung über serielle Schnittstelle zerstört Datei.



  • Hallo,
    ich war mir nicht sicher, in welchem Forum ich das Posten soll. Weil es gibt hier C# und C++ Code. Falls es falsch ist, sorry.

    Ich habe folgendes Problem.
    Ich habe ein kleines Server-Client Programm für serielle Verbindung geschrieben. Der Server, der Nachrichten und Dateien empfängt läuft auf Windows Embedded CE 6.0 und ist geschrieben in Visual C++. Ich habe mehr oder minder mir ein kleines Protokoll ausgedacht, dass nicht der Überflieger ist aber das Ganze eigentlich funktionieren sollte. Ich kann Nachrichten wunderbar empfangen und es funktioniert alles. Ich kann auch Textdateien empfangen, die kein Unicode sind. Also wenn ich einfach eine *.txt erstelle, "Hallo" reinschreibe und das Versende funktioniert es wunderbar.

    Jetzt ist es so, dass ich einen Client für WindowsXP geschrieben habe in C#, mit einer einfachen Oberfläche. Dort Öffne ich eine beliebige Datei, lese sie ein und versuche sie an der Server in definierten Paketen zu schicken. Nachdem ich die Datei empfangen habe und rausgeschrieben habe, ist sie unbrauchbar.

    Irgendwas mache ich falsch und aller Wahrscheinlichkeit ist es wohl was mit den Datentypen aber ich bin da schon 3 Tage am rummachen und finde keine Lösung.

    Hier die Methode (Client) zum einlesen und versenden einer Datei:

    protected void SendFileLoopThread(Object parameter)
            {
                string fname = (string)parameter;
    
                const string mxBinHeader = "M!FB01|";
                string mxBinMessage = String.Empty;
                string mxFileMessage = String.Empty;
    
                byte[] buf = new byte[BINARY_SIZE]; // Binary size = 512
                long binCount = 0;
                int bytesRead = 0;
    
                // Open filestream, calculate how many binary messages will have to be sent.
                FileStream fs = new FileStream(fname, FileMode.Open, FileAccess.Read);
                binCount = this.CalculateBinCount(fs.Length);
                string[] fileName = fname.Split('\\');
    
                mxFileMessage = "M!FVXX|" + fs.Length + "|" + fileName[fileName.Length - 1];
                this.SendMessage(mxFileMessage);
    
                try
                {
                    while ((bytesRead = fs.Read(buf, 0, BINARY_SIZE)) > 0)
                    {
                        mxBinMessage = mxBinHeader + System.Text.Encoding.ASCII.GetString(buf);
                        this.SendMessage(mxBinMessage);
                        mxBinMessage = String.Empty;
                        Array.Clear(buf, 0, buf.Length);
                    }
                }
                catch (Exception e)
                {
                    this.Log(LogType.DEBUG, e.Message + "\nDateitransfer abgebrochen");
                }
                finally
                {
                    fs.Close();
                }
    
                watch.Stop();
    
                this.Log(LogType.DEBUG, "Dateitransfer abgeschlossen nach " + watch.Elapsed.Seconds + " Sekunden");
            }
    

    Hier die Methode zum Senden an den COM-Port. Immernoch Client, immernoch C#

    public override void SendMessage(string message)
            {
                string toSend = String.Empty;
                toSend += '\x01';
                toSend += message;
                toSend += '\x17';
                try
                {
                    byte[] bytes = System.Text.Encoding.ASCII.GetBytes(toSend.ToCharArray());
                    this.m_port.Write(bytes, 0, bytes.Length);
                }
                catch (Exception e)
                {
                    throw e;
                }
            }
    

    Und hier Die Methode, die auf dem Server läuft und immer eine Nachricht empfängt. Verarbeitet wird die Nachricht wo anders.

    int CProtocol::ReceiveFileFromCom(string& message, CSerialServer* serv, unsigned int bytes)
    {
        // in parameter "bytes" steht die anzhal, der bytes, die gelesen werden sollen, falls der rest einer Datei kleiner ist als 512 oder wenn 
        // allgemein eine datei verschickt wurde, die kleiner ist als 512 byte
    
        message.clear();
        UCHAR *msg = new UCHAR[bytes+9]; 
        DWORD bytesRead = 0;
        int receiveTries = 0;
    
        for(;;)
        {
            if(!ReadFile(serv->GetComPort(), msg, bytes + 9, &bytesRead, NULL))
            {
                delete[] msg;
                return GetLastError();
            }
    
            if(bytesRead == (bytes + 9))        // +9 -> <SOH>M!FB00|<512 byte daten><ETB>
            {
                for(unsigned int j = 1; j < bytesRead - 1; j++)
                    message.push_back(msg[j]);
                delete[] msg;
                return SUCCESS;
            }
            else
            {
                return ERR_TIMEOUT;
            }
        }
    }
    

    Kann das so funktionieren mit meinen Datentypen? Oder liegt mein Fehler doch wo anders?

    mfg



  • Das Problem wird vermutlich System.Text.Encoding.ASCII sein.
    Ich würde eher alles direkt binär senden und nur das "M!FVXX|"-Zeugs in byte[] umwandeln



  • Dieser Thread wurde von Moderator/in Martin Richter aus dem Forum WinAPI in das Forum C++/CLI mit .NET verschoben.

    Im Zweifelsfall bitte auch folgende Hinweise beachten:
    C/C++ Forum :: FAQ - Sonstiges :: Wohin mit meiner Frage?

    Dieses Posting wurde automatisch erzeugt.



  • Du übergibst vermutlich die Länge falsch... Du kannst Die Länge erst ausrechnen, wenn Du den Text nach ASCII konvertiert hast und nicht schon vorher... Also erst in der SendMessage Methode kannst Du eine Länger erzeugen! Oder Du musst eben der SendMessage Methode schon ein byte-Array übergeben!



  • Meinst du die Länge in Zeile 15 der SendFileLoopThread()?
    Dort wird ja nur anhand der kompletten Dateigröße berechent wieviele Pakete geschickt werden.
    Außerdem benutze ich das sonst in der Methode nicht mehr. Es ist nur ein Überbleibsel aus meiner erfolglosen Fehlersuche.


Anmelden zum Antworten