Binärer Dateitransfer zwischen Visual Basic Client und C++ Server



  • Hallo!
    Ich arbeite an einem Client/Server Projekt, bei dem der Server in MSVC++6.0 (Win32/ein Konsolenprogramm mit Sockets) geschrieben ist und der Client in Visual Basic 6.0 (Standard Exe mit dem Winsock Steuerelement).
    Der Client soll in der Lage sein eine Datei vom Server herunterzuladen.

    Mein Code funktioniert einwandfrei für Textdateien, aber nicht für Binärdateien. Ich kann eine Textdatei ohne weiteres transferieren, aber ein Jpeg-Bild (gleicher Größe) kommt als korrupte Datei an.

    Zu den Details:
    Im C++-Server wird mit einem File-Stream gearbeitet:

    fin = fopen(fName,"rb")
    fseek(fin, fPos, SEEK_SET);
    memblock = new char [fChunkSize - 1];
    fread(memblock, fChunkSize,1,fin);
    sprintf(sendbuffer, "BN|DWNPUT|%i|\0", fHandle);
    strcat(sendbuffer, memblock);
    fclose(fin)
    send(tSocket,sendbuffer,strlen(sendbuffer),0);
    memset(&memblock, 0, sizeof(memblock));
    memset(&sendbuffer, 0, sizeof(sendbuffer));
    

    Diese Funktion wird für jeden Block ausgeführt. D.h wenn dieser Block beim Clienten angekommen ist, verlangt der Client den nächsten und diese Prozedur wird im Server wieder anfgerufen.

    Diese Methode habe ich bereits mit reinem Visual Basic getestet (Client und Server in VB), es funktioniert!

    Der Visual Basic Client geht etwa so vor:
    Open .LocalFile For Binary As .LocalFileNumber
    [..]
    Dim Data As String
    wskWinsock(Index).GetData Data
    Dim BlockStart As Integer
    [..]
    BlockStart = InStr(11, Data, "|", vbTextCompare)
    Dim BinData As String
    BinData = Right(Data, Len(Data) - BlockStart)
    [..]
    Put .LocalFileNumber, .FilePos + 1, BinData
    [..]
    SendData "00|DWNGET|[..]"
    [..]
    Close .LocalFileNumber

    Das Problem:
    Textdateien kommen auf den Byte richtig an, allerdings kommen Binäredateien korrupt an. Schaut man sich den Dateiinhalt an, findet man sehr viele Zeichen, die in der Orginaldatei nicht da waren.
    Woran könnte das liegen?
    Benutzt VB womöglich einen anderen Zeichensatz? Unicode Probleme??

    Ich bin für jede Hilfe sehr Dankbar!



  • Ich nutze immer fstream und bei den Funktionen ofstream und ifstream kann man mit ios auf binäre Dateisysteme umstellen. Denke da wird also ein Unterschied sein... vielleicht versuchst du es mal damit! Weiss aber nicht, ob dir das weiterhilft!



  • Ich bezweifle, dass das funktioniert, da die Zeile:

    fin = fopen(fName,"rb")
    

    die Datei schon eindeutig für den binären lesevorgang öffnet.
    r=read und b=binary
    Ein Versuch kann trotzdem nicht schaden. Ich werde mich morgen wieder melden.



  • Ich habe es jetzt gestestet, mit...

    File *fin;
    fin = fopen(fName,"rb")
    [..]
    fseek(fin, fPos, SEEK_SET);
    [..]
    fread(memblock, fChunkSize,1,fin);
    [..]
    fclose(fin)
    

    passiert das gleiche wie mit...

    ifstream file ("fName", ios::in | ios::binary)
    [..]
    file.seekg(fPos, ios_base::beg);
    [..]
    file.read (memblock, fChunkSize);
    [..]
    file.close();
    

    trotzdem danke!
    vielleicht kennt ein anderer die Lösung



  • CodeRed schrieb:

    ...
    strcat(sendbuffer, memblock);
    ...
    send(tSocket,sendbuffer,strlen(sendbuffer),0);
    ...
    

    strcat macht bei der ersten 0 schluss, geht also nicht für binärdaten. nimm besser memcpy.
    du solltest auch den rückgabewert von send beachten.
    🙂



  • Und fread(memblock, fChunkSize,1,fin) gegen fread(memblock, 1,fChunkSize,fin) tauschen, und den Returncode auswerten.



  • hustbaer schrieb:

    Und fread(memblock, fChunkSize,1,fin) gegen fread(memblock, 1,fChunkSize,fin) tauschen...

    😕



  • Ja lies halt die Doku.
    fread(p, 100, 1, f)
    wird 0 zurückgeben wenn z.B. nach 90 Byte EOF war.
    fread(p, 1, 100, f)
    wird dagegen in dem Fall 90 liefern.



  • strcat macht bei der ersten 0 schluss, geht also nicht für binärdaten.

    klang sehr viel versprechend.
    Habe

    fin = fopen(fName,"rb")
    fseek(fin, fPos, SEEK_SET);
    
    char * memblock;
    char * sendbuffer;
    memblock = new char [fChunkSize - 1];
    sendbuffer = new char [fChunkSize+40];
    
    fread(memblock, fChunkSize,1,fin);
    sprintf(sendbuffer, "BN|DWNPUT|%i|\0", fHandle);
    strcat(sendbuffer, memblock);
    
    fclose(fin);
    send(tSocket,sendbuffer,strlen(sendbuffer),0);
    memset(&memblock, 0, sizeof(memblock));
    memset(&sendbuffer, 0, sizeof(sendbuffer));
    

    Gegen

    fin = fopen(fName,"rb")
    fseek(fin, fPos, SEEK_SET);
    
    char * memblock;
    char * sendbuffer;
    memblock = new char [fChunkSize - 1];
    sendbuffer = new char [fChunkSize+40];
    
    fread(memblock, 1,fChunkSize,fin);
    sprintf(sendbuffer, "BN|DWNPUT|%i|\0", fHandle);
    memmove (sendbuffer+strlen(sendbuffer),memblock,fChunkSize);
    
    fclose(fin);
    send(tSocket,sendbuffer,strlen(sendbuffer),0);
    memset(&memblock, 0, sizeof(memblock));
    memset(&sendbuffer, 0, sizeof(sendbuffer));
    

    ausgetauscht und werde es so lassen, da ich auch denke das '\0'-Zeichen im Binärenstream Probleme verursachen könnten und das Programm so schneller läuft.
    Es löst aber nicht das Problem
    -CreateFile, ReadFile Apis gegen fin = fopen(fName,"rb") austauschen, hat nichts gebracht
    -fin = fopen(fName,"rb") gegen ifstream file (fName, ios::in | ios::binary), hat auch nichts gebracht
    -strcat gegen memmove hat auch nichts gebracht.

    ich denke immer noch, dass es an einem Unterschied zwischen dem Umgang mit Strings zwischen Visual Basic und C++ liegt. Kann mir den keiner Helfen?



  • du benutzt strlen!



  • [code]Dim Data As String
    wskWinsock(Index).GetData Data
    [code]

    Woher weiss "wskWinsock(Index).GetData" wieviele Daten gelesen werden sollen???



  • ja ich weiß, aber mit 'sizeof' funktioniert es nicht. was kann ich sonst benutzen?
    Ich will auch noch die Rückgaben der read-Funktionen überprüfen, um zu sehen, ob da der gesammte Block gelesen wird oder ob er schon da verloren geht. Bei der Send-Funktion will ich das gleiche machen.

    Aber welche Alternativen zu 'strlen' gibt es den?

    Danke für die schnellen Antworten!

    an Hustbaer: In Visual Basic muss man die Länge nicht angeben. Die Strings werden anders aufgebaut als in C++. Am Anfang eines VB-Strings steht die Länge des gesammten Strings, daher sind Längenangaben und Terminator am Ende nicht mehr nötig.

    Ich dachte ursprünglich das da das Problem liegt. Jetzt stelle ich fest, dass es mit einem C++ Clienten auch nicht funktioniert! (Es kommt zu wenig an)



  • Ich habe das Problem gerade eben lösen können. Dazu habe ich strlen durch eine errechnete Packetgröße ersetzt.

    long tosend=fChunkSize+strlen(sendbuffer)
    

    (-> direkt nach dem eingeben des Befehls in den SendBuffer, vor memmove)

    So funktioniert alles.
    -SizeOf hört wohl da auf, wo sich in dem CharArray nichts mehr befindet, was aber bei Jpeg-Bildern durchaus vorkommen kann.
    -Strlen hört beim ersten "\0" auf, was auch im Binärenstrom vorkommen kann.

    Ich danke allen, die sich die Mühe gemacht haben mir zu Antworten!
    Problem gelöst!



  • CodeRed schrieb:

    Dazu habe ich strlen durch eine errechnete Packetgröße ersetzt.

    Bitte, bitte entweder Paketgröße oder packet size 😉


Anmelden zum Antworten