Probleme mit SendStream und ReceiveBuf



  • Danke Burkhi für die Antwort.

    Also die genaue Fehlermeldung heißt:
    "Zugriffsverletzung bei Adresse 00000000. Lesen von Adresse 00000000."

    Ich erhalte die Fehlermeldung, nachdem versucht wird, die ankommenden Daten zu empfangen. Es springt auf jeden Fall schonmal in die Funktion, soweit konnte ich es schon testen.

    Hab deinen Code oben eingesetzt und daher müsste es ja funktionieren.
    Wenn nur file nur ein Zeiger ist, muss dann die Sendefunktion nicht auch anders programmiert werden?

    Nochmal danke.



  • den fehler bekommst du, weil du file nicht mit new erstellt hast.

    die sende funktion musst du nicht ändern, da sie extram zum senden von streams gemacht ist, du kannst jedoch auf ca die selbe art und weise die SendBufer mehtode benutzen



  • ABer file wurde doch mit new erstellt ... oder versteh ich da was falsch?

    TFileStream* file = new TFileStream(DateiSpeichern->FileName, fmCreate);
    char buf[1024];
    int c;
    do
    {
      c = Socket->ReceiveBuf(buf, sizeof(buf));
      file->Write(buf,c);
    }
    while (c == sizeof(buf));
    delete file;
    


  • ich habs auch gerade versucht, ich bekomme den fehler auch, aber er deutet darauf hin, dass ein zeige nach NULL zeigt, wenn ich mich nicht irre, also irgend wo muss ein zeiger noch zugewiesen werden...

    EDIT: Ich bekomme den fheler aber beim senden...


  • Mod

    Hallo

    warum pruefst du file nicht ab
    (zB if ( file )
    Ich glaube da kommt dein Fehler her

    MfG
    Klaus



  • Wenn file den Wert 0 enthält, so könnte die Datei, die erstellt werdne soll, nicht erstellt werden.
    Darauf mußt du prüfen.



  • Burkhi schrieb:

    Wenn file den Wert 0 enthält...

    Normalerweise sollte der TFileStream-Konstruktor in diesem Fall aber eine Exception werfen.

    @HolyCow: Aus Deinen Beiträgen geht nicht so richtig hervor, in welcher Zeile nun genau der Fehler auftritt - beim ReceiveBuf oder beim Write?

    Der Code von Burkhi sieht gut aus und sollte erst einmal funktionieren.
    Allerdings würde ich die while-Bedingung so schreiben:

    while (c != -1)
    

    Wenn ich die Hilfe richtig verstanden habe, ist es nicht sicher, daß tatsächlich immer die angeforderte Anzahl an Bytes übertragen wird.



  • @dschensky:

    c = Socket->ReceiveBuf(buf, sizeof(buf));
    

    Die Funktion liefert dir zurück, wieviele Zeichen tatsächlich empfangen wurden. Der zweite Parameter gibt die maximale Größe des Puffers an, der die Zeichen aufnehmen soll.
    Daraus folgt: 0 <= c <= sizeof(buf) 😉

    Wenn c == sizeof(Buf) ist, so können noch weitere Zeichen empfangen worden sein, deshalb die Schleife.



  • Burkhi schrieb:

    Daraus folgt: 0 <= c <= sizeof(buf) 😉

    Wenn c == sizeof(Buf) ist, so können noch weitere Zeichen empfangen worden sein, deshalb die Schleife.

    Hmmm, laut BCB-Hilfe ist gilt -1 <= c <= sizeof(buf). Und -1 wird zurückgegeben, wenn keine Daten übertragen wurden. (Da würde mich so nebenbei mal interessieren, wo der Unterschied zwischen c=-1 und c=0 besteht.)
    Das Problem bei Deiner Schleife ist, daß sie prinzipiell beendet wird, wenn c ungleich, also speziell auch kleiner als sizeof(buf) ist. Wird also irgendwo in der Mitte der Übertragung ein Daten-Paket empfangen, dessen Länge kleiner als sizeof(buf) ist, bricht die Schleife ab, obwohl noch nicht alle Daten angekommen sind.



  • Hallo zusammen,

    ich habe jetzt etwas weitergearbeitet und die Sendefunktion ist soweit nun komplett richtig .. glaub ich wenigstens.
    Diese Funktion sendet mir die komplette Datei, hatte Testhalber einen Zähler drin der die Datenpackete zählte, nur das Empfangen macht noch Probleme.

    //Anlegen des Streams ...
    TFileStream* file = new TFileStream(DateiOeffnen->FileName, fmOpenRead);
    char buf[1024]; //Buffer
    int c,b;        //Testvariabeln
    
    //Solange senden bis Buffer nichtmehr voll geschriben wird,
    //also Datei zu ende ist
    do
    {
      //Auslesen der zu sendenden Informationen
      b = file->Read(buf,sizeof(buf));
    
      //Senden des Buffers
      c = DCSocket->Socket->SendBuf(buf,sizeof(buf));
    
      //Falls nicht gesendet werden konnte, also interner Speicher voll war,
      //solange warten, bis gesendet werden kann
      while(c == -1)
      {
         Delay(10);
         c = DCSocket->Socket->SendBuf(buf,sizeof(buf));
      }
    }
    while(b == sizeof(buf));
    

    Hatte ihn mal soweit, dass die ersten 61 gesendeten Datenpackete auch ordnungsgemäß empfangen wurden (bei Bildern konnte ich dann z.B. schon einen kleinen Teil erkennen), nach diesen Packeten sprang er jedoch aus der Funktion und nach einigen Sekunden wieder zurück und ich konnte die Datei nicht mehr öffnen und erhielt einen Fehler wie "Kann Datei nicht anlegen".
    Hatte alles mögliche versucht, z.B. die Datei mit FileCreate oder mit Fstream anzulegen oder was weiß ich was mir noch so alles eingefallen ist.
    Naja langsamm bin ich hier am verzweifeln 😞

    Nun ja, die Empfangfunktion sieht nun so aus. Fast wie am Anfang, da ich sie eben einfach mal versucht hab von Beginn an neu zu programmieren, hilf manchmal bei mir.

    TFileStream* file = new TFileStream(DateiSpeichern->FileName, fmCreate);
    char buf[1024];
    int c;
    do
    {
      c = Socket->ReceiveBuf(buf, sizeof(buf));
      if(c != -1)
        file->WriteBuffer(buf,sizeof(buf));
        Hauptfenster->Mhauptfenster->Lines->Add("-----> " + IntToStr(c));
    }
    while(c != -1);
    delete file;
    

    Ich erhalte jetzt in meiner Testausgabe seltsammerweise sehr oft eine "-1", das dürfte aber wegen der If-Anweisung gar nicht sein.
    Nun ja, werde morgen nochmal was dran arbeiten, geh jetzt erstmal was grillen, sonst werd ich noch verrückt 😃



  • Ich bins nochmal ..

    So einfach kann es sein, funktioniert jetzt bei mir, endlich 🙂

    Also, falls es wen interessiert, hier ist der Code nochmal:

    Senden:

    //Anlegen des Streams ...
    TFileStream* file = new TFileStream(DateiOeffnen->FileName, fmOpenRead);
    file->Seek(0,soFromBeginning);
    char buf[1024]; //Buffer
    int c,b;    //Testvariabeln
    
    //Solange senden bis Buffer nichtmehr voll geschriben wird,
    //also Datei zu ende ist
    do
    {
      //Auslesen der zu sendenden Informationen
      b = file->Read(buf,sizeof(buf));
    
      //Senden des Buffers
      c = DCSocket->Socket->SendBuf(buf,sizeof(buf));
    
      //Falls nicht gesendet werden konnt, also interner Speicher voll war,
      //solange warten, bis gesendet werden kann
      while(c == -1)
      {
        Delay(10);
        c = DCSocket->Socket->SendBuf(buf,sizeof(buf));
      }
    }
    while(b == sizeof(buf));
    
    //Löschen des temporären Streams
    delete file;
    

    Empfangen:
    1.Ein Filestream wird in der Headerdatei deklariert.

    class TDatei : public TForm
    {
    [...]
      public:
        TFileStream* file;
    [...]
    };
    

    2.Der Stream wird irgendwo im Programm initialisiert

    if(DateiSpeichern->Execute())
    {
      DSSocket->Socket->Connections[0]->SendText("senden");
      file = new TFileStream(DateiSpeichern->FileName, fmCreate);
    }
    else
      DSSocket->Socket->Connections[0]->SendText("abbrechen");
    

    3. Daten werden ohne Schleife in der Read-Funktion abgespeichert.

    char buf[1024]; //Buffer
    int c;  //Testvariabel
    
    //Daten auslesen und Größe speichern
    c = Socket->ReceiveBuf(buf,sizeof(buf));
    //Falls Daten gelesen in Filestream speichern
    if(c != -1)
      file->Write(buf,c);
    

    Hmm hätte zwar nicht gedacht, dass es ohne Schleife funktioniert, aber irgendwie geht es bei mir. Jetzt müssen nur noch paar kleiner Abfragen rein und dann solls das gewesen sein.
    Naja wie auch immer, habs also doch noch geschafft.

    Daher vielen Dank an die umfangreiche und freundliche Hilfe.
    ThX 👍

    Man sieht sich sicher noch, bin mit meinem Programm ja noch nicht fertig 😃



  • P.S.: Beim Senden müssen die Zeilen

    c = DCSocket->Socket->SendBuf(buf,sizeof(buf));
    durch
    c = DCSocket->Socket->SendBuf(buf,b);

    ersetzt werden.
    Bei kleineren Datenpacketen wird sonst der gesammte Buffer, obwohl er keine verwertbaren Daten beinhaltet, gesendet.



  • Hi, kann mir jemand helfen?
    Hab HolyCows Code ausprobiert, nur bei mir funzt er nicht!
    Der Stream wird gesendet nur nicht richtig empfangen.
    Ich sende ein Bild (9.966 Byte), es kommen alle 9.966 Byte an, aber die sind irgend wie leer, denn das Bild kann nicht geladen werden (ins TImage)

    Senden:

    //Anlegen des Streams ...
    TMemoryStream* file = new TMemoryStream;
    file->LoadFromFile("1.bmp");
    //Image1->Picture->Bitmap->SaveToStream(file);
    Image2->Picture->Bitmap->LoadFromStream(file);
    
    file->Seek(0,soFromBeginning);
    char buf[1024]; //Buffer
    int c,b;    //Testvariabeln
    
    //Solange senden bis Buffer nichtmehr voll geschriben wird,
    //also Datei zu ende ist
    do
    {
      //Auslesen der zu sendenden Informationen
      b = file->Read(buf,sizeof(buf));
    
      //Senden des Buffers
      c = ClientSocket1->Socket->SendBuf(buf,b);
    
      //Falls nicht gesendet werden konnt, also interner Speicher voll war,
      //solange warten, bis gesendet werden kann
      while(c == -1)
      {
        for(int i=0;i<1000000;i++){}
        c = ClientSocket1->Socket->SendBuf(buf,sizeof(buf));
      }
    }
    while(b == sizeof(buf));
    
    //Löschen des temporären Streams
    delete file;
    

    Empfangen:

    char buf[1024]; //Buffer
    int c;  //Testvariabel
    
    //Daten auslesen und Größe speichern
    c = Socket->ReceiveBuf(buf,sizeof(buf));
    //Falls Daten gelesen in Filestream speichern
    if(c != -1)
      Stream->Write(buf,c);
    ListBox1->Items->Add("Recieve");
    Caption=Stream->Size;
    Image1->Picture->Bitmap->LoadFromStream(Stream);
    

    Bitte um hilfe!!!!

    Gruß FB4 😉



  • HolyCow,

    HolyCow schrieb:

    char buf[1024]; //Buffer
    ...
    c = Socket->ReceiveBuf(buf,sizeof(buf));
    ...
    

    Hmm hätte zwar nicht gedacht, dass es ohne Schleife funktioniert, aber irgendwie geht es bei mir.

    wenn ich das richtig sehe, "funktioniert" Deine Variante nur bei Dateien bis zu einer Größe von 1024 Byte. Ich fürchte, um die Schleife kommst Du nicht herum - so ungefähr (ungetestet):

    int bytesReseived(0);
    do
    {
        bytesReseived = Socket->Receive(buffer, bufferSize);
        inStream->Write(buffer, bufferSize);
    }
    while (bytesReseived != -1)
    


  • Habs jetzt doch hinbekommen!
    Trotzdem Danke dschensky!

    Gruß FB4


Anmelden zum Antworten