Autor |
Beitrag |
O'rallY
      
Beiträge: 563
|
Verfasst: Fr 27.09.02 17:42
Wie kann man, unter der verwendung von Socket.SendBuf(...) eine binäre Datei verschicken. Bisher habe ich das ganze so gemacht , doch funktioniert das nur bei Textdateien:
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45:
| procedure aProcedure; var temp: string; i, PacketSize, FSize, SizeAlreadyTransferred: integer; FileStream: TFileStream
begin
FileStream := TFileStream.Create('C:\datei.txt', fmOpenRead); FileStream.Read(PChar(temp)^, FileStream.Size); FileStream.Free;
PacketSize := 4096; FSize := Length(temp);
for i := 0 to FSize div PacketSize do begin if i = FSize div PacketSize then PacketSize := FSize - SizeAlreadyTransferred; end;
ClientSocket1.Socket.SendBuf(PChar(temp)^, PacketSize);
temp := RightStr(temp, Length(temp) - PacketSize);
Inc(SizeAlreadyTransferred, PacketSize);
end;
end;
//server: var temp: string; FileStream: TFileStream;
begin temp := Socket.ReceiveText; FileStream := TFileStream.Create('C:\datei.txt', fmCreate or fmOpenReadWrite); FileStream.Write(Pchar(temp)^, Length(temp); FileStream.Free; end; |
Das das nur mit Textdateien funktioniert ist ja auch logisch, doch weiß ich eben nicht wie das ganze mir Binärdaten funktioniert (habe nur wage vorstellungen). Ich erbitte HILFE
P.S.: falls diese Frage schon des Öfteren gestellt wurde, tut mir Leid, aber die Suchfunktion ist nicht sehr ergiebig. Um genau zu sein ist sie zum

_________________ .oO'rallY
Linux is like a tipi: No gates, no windows and a gnu-eating apache inside...
|
|
DeCodeGuru
      
Beiträge: 1333
Erhaltene Danke: 1
Arch Linux
Eclipse
|
Verfasst: Fr 27.09.02 18:54
Hi,
du musst die Daten ja nicht unbedingt in einen String auslagern. Das kann eben zu dem Fehler kommen, dass man binäre Daten nicht übertragen kann. Du könntest zum Beispiel auch mit ClientSocket1.Socket.SendBuf(FileStream^,SizeOf(FileStream)); senden. Ansonsten könntest du dein temp-var auch als array of Byte deklarieren. Dann dürfte kein Fehler mehr auftreten.
So, hier habe ich nochmal eine relativ alte Sendenroutine (Server und Client im selben Programm):
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: 65: 66: 67: 68: 69: 70: 71: 72: 73: 74: 75: 76: 77: 78: 79: 80: 81: 82: 83: 84: 85: 86: 87: 88: 89: 90: 91: 92: 93: 94: 95: 96: 97: 98: 99: 100: 101: 102: 103: 104: 105: 106: 107: 108: 109: 110: 111: 112: 113: 114: 115: 116: 117: 118: 119: 120: 121: 122: 123: 124: 125: 126: 127: 128: 129: 130: 131: 132:
| procedure TMainForm.ClientRead(Sender: TObject; Socket: TCustomWinSocket); var tmp: String; FStream: TMemoryStream; Buf: Pointer; begin case CSendStatus of 0: begin tmp := Socket.ReceiveText; if Copy(tmp,1,3) = '#11' then begin CSendStatus := 1; FStream := TMemoryStream.Create; FStream.LoadFromFile(Edit2.Text); Socket.SendText('#02'+IntToStr(FStream.Size)); FStream.Free; end; if Copy(tmp,1,3) = '#12' then begin CSendStatus := 0; end; end; 1: begin tmp := Socket.ReceiveText; if Copy(tmp,1,3) = '#13' then begin Socket.SendText('#03'); CSendStatus := 2; end; if Copy(tmp,1,3) = '#14' then begin CSendStatus := 0; end; end; 2: begin tmp := Socket.ReceiveText; if Copy(tmp,1,3) = '#15' then begin FStream := TMemoryStream.Create; FStream.LoadFromFile(Edit2.Text); Buf := FStream.Memory; Socket.SendBuf(Buf^,FStream.Size); end; end; end; end;
procedure TMainForm.ServerClientRead(Sender: TObject; Socket: TCustomWinSocket); var tmp: String; a: array[0..4096]of Byte; Buf: Pointer; i: Integer; begin case SSendStatus of 0: begin tmp := Socket.ReceiveText; if Copy(tmp,1,3) = '#01' then begin if MessageDlg('Ein Client will Ihnen eine Datei schicken. Wollen Sie die Dateiübertragung akzeptieren?',mtConfirmation,[mbYes,mbNo],0) = mrYes then begin Delete(tmp,1,3); Form3.Label1.Caption := 'Dateiname: '+tmp; FileName := tmp; SSendStatus := 1; Socket.SendText('#11'); FSize := 0; FPos := 0; end else begin SSendStatus := 0; Socket.SendText('#12'); end; end; end; 1: begin tmp := Socket.ReceiveText; if Copy(tmp,1,3) = '#02' then begin Delete(tmp,1,3); FSize := StrToInt(tmp); SSendStatus := 2; Socket.SendText('#13'); Form3.Label2.Caption := 'Fortschritt: 0 von '+IntToStr(FSize); Form3.Gauge1.MaxValue := FSize; end else begin SSendStatus := 1; Socket.SendText('#14'); end; end; 2: begin tmp := Socket.ReceiveText; if Copy(tmp,1,3) = '#03' then begin SaveDialog.FileName := ExtractFileName(FileName); if SaveDialog.Execute then begin SSendStatus := 3; Socket.SendText('#15'); TMPStream := TFileStream.Create(SaveDialog.FileName,fmCreate or fmOpenWrite); end; end; end; 3: begin Timer.Enabled := True; Form3.Show; //Fortschrittsanzeige Buf := @a; i := Socket.ReceiveBuf(Buf^,4096); TMPStream.Write(Buf^,i); FPos := FPos +i; Form3.Gauge1.Progress := FPos; Form3.Label2.Caption := 'Fortschritt: '+IntToStr(FPos)+' von '+IntToStr(FSize); if FPos >= FSize then begin TMPStream.Position := 0; FPos := 0; SSendStatus := 0; Timer.Enabled := False; end; end; end; end; |
Ich denke, dass man alles aus dem Quelltext entnehmen kann. Wenn nicht bitte fragen.
_________________ Viele Grüße
Jakob
|
|
O'rallY 
      
Beiträge: 563
|
Verfasst: Fr 27.09.02 19:47
DeCodeGuru hat folgendes geschrieben: | du musst die Daten ja nicht unbedingt in einen String auslagern |
Dessen war ich mir im Klaren, doch wusste ich nicht, wie eine Alternative genau aussieht. Aber dank dir hab ichs jetzt geschnackelt. Ich dank dir  .
_________________ .oO'rallY
Linux is like a tipi: No gates, no windows and a gnu-eating apache inside...
|
|
DeCodeGuru
      
Beiträge: 1333
Erhaltene Danke: 1
Arch Linux
Eclipse
|
Verfasst: Fr 27.09.02 19:49
bitte 
_________________ Viele Grüße
Jakob
|
|
O'rallY 
      
Beiträge: 563
|
Verfasst: Fr 27.09.02 22:52
OK, habs jetzt alles nach deinem Vorschlag umgestalltet, doch bekomme ich nun, wenn ich die Datei schicken will einen Asyncronous Socket Error (10053) Eine bestehende Verbindung wurde Softwaregesteuert durch den Hostcomputer abgebrochen
_________________ .oO'rallY
Linux is like a tipi: No gates, no windows and a gnu-eating apache inside...
|
|
DeCodeGuru
      
Beiträge: 1333
Erhaltene Danke: 1
Arch Linux
Eclipse
|
Verfasst: Sa 28.09.02 09:26
hast du den gleichen Code verwendet? wenn ja könnte es an paar anderen Routinen liegne, die noch im Programm sind. Ich wollte mit dem Quellcode nur ein kleines Beispiel geben, wie man so etwas machen kann. Wenn du willst, kann ich dir das Programm mal schicken.
_________________ Viele Grüße
Jakob
|
|
O'rallY 
      
Beiträge: 563
|
Verfasst: Sa 28.09.02 12:40
Wäre nett wenn du mir mal das Programm schicken würdest. Trotzdem erstmal mein Code:
Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30:
| procedure TForm1.ClientSocket1Connect(Sender: TObject; Socket: TCustomWinSocket); var MStream: TMemoryStream; Buffer: Pointer;
begin
MStream := TMemoryStream.Create; MStream.LoadFromFile('C:\dateiin.txt'); Buffer := MStream.Memory; Socket.SendBuf(Buffer^, MStream.Size);
end;
procedure TForm1.ServerSocket1ClientRead(Sender: TObject; Socket: TCustomWinSocket); var fs: TFileStream; Buffer: pointer; BBuffer: array[0..4096] of Byte; SizeOfBuffer: integer;
begin
fs := TFileStream.Create('c:\dateiout.txt', fmCreate or fmOpenWrite); Buffer := @BBuffer; SizeOfBuffer := Socket.ReceiveBuf(Buffer^, 4096); fs.Write(Buffer^, SizeOfBuffer); end; |
Der von mir beschriebene Fehler tritt nicht auf, wenn ich beim OnClientConnet-Event folgenden Code austausche:
Quelltext 1: 2: 3: 4:
| Socket.SendBuf(Buffer^, MStream.Size); | v Socket.SendBuf(Buffer^, 4096); |
Ich vermute, es liegt daran, dass das OnClientRead-Event nur einmal ausgeführt wird und somit nur 4096 Bytes aus dem gesendeten ausliest, obwohl der Client mehr gesendet hat. Dummerweise kenne ich mich mit Socket.ReceiveBuf(...) nicht so gut aus.[/code]
_________________ .oO'rallY
Linux is like a tipi: No gates, no windows and a gnu-eating apache inside...
|
|
DeCodeGuru
      
Beiträge: 1333
Erhaltene Danke: 1
Arch Linux
Eclipse
|
Verfasst: Sa 28.09.02 13:16
jo ähm, könnteste du mir deine Mailadresse per PN schicken?
_________________ Viele Grüße
Jakob
|
|
O'rallY 
      
Beiträge: 563
|
Verfasst: Sa 28.09.02 23:02
Zitat: |
Der von mir beschriebene Fehler tritt nicht auf, wenn ich beim OnClientConnet-Event folgenden Code austausche:
Quelltext 1: 2: 3: 4:
| Socket.SendBuf(Buffer^, MStream.Size); | v Socket.SendBuf(Buffer^, 4096); |
|
Um genau zu sein tritt der Fehler erst auf, wenn MStream.Size > 233472 ist. Es hat also nichts mit den 4096 Bytes zu tun. Ist das so normal oder nicht? Hat es einen Hintergrund?
Wäre nett wenn mal ein anderer ausprobieren würde eine Datei zu schicken, die über 240000 Byte groß ist und mir dann sagen, obs geklappt hat oder nicht!
_________________ .oO'rallY
Linux is like a tipi: No gates, no windows and a gnu-eating apache inside...
|
|
O'rallY 
      
Beiträge: 563
|
Verfasst: So 29.09.02 09:22
Titel: Problem gelöst!
Ich hab gerade das Problem gelöst! *stolz* Da SendBuf ja nur begrenzt nutzbar zu sein scheint (im Sinne der Dateigröße), hab ich mal das ganze mit SendStream ausprobiert. Das sieht dann etwa so aus:
Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27:
| procedure TForm1.ClientSocket1Connect(Sender: TObject; Socket: TCustomWinSocket); var FStream: TFileStream;
begin
FStream := TFileStream.Create('C:\dateiin.txt', fmOpenRead); Socket.SendStream(FStream);
end;
procedure TForm1.ServerSocket1ClientRead(Sender: TObject; Socket: TCustomWinSocket); var fs: TFileStream; Buffer: pointer; BBuffer: array[0..4096] of Byte; SizeOfBuffer: integer;
begin
fs := TFileStream.Create('c:\dateiout.txt', fmCreate or fmOpenWrite); Buffer := @BBuffer; SizeOfBuffer := Socket.ReceiveBuf(Buffer^, 4096); fs.Write(Buffer^, SizeOfBuffer); end; |
Manchmal ist es schon verwunderlich, wie einfach ein Problem zu lösen ist (und wie depremierend eine einfache Lösung sein kann  )  . Das dumme ist, wenn man an einem Problem sitzt und versucht es zu lösen, kann es leicht passieren, das man sich festfährt und die vielleicht viel simplere Lösung nicht sieht 
_________________ .oO'rallY
Linux is like a tipi: No gates, no windows and a gnu-eating apache inside...
|
|
DeCodeGuru
      
Beiträge: 1333
Erhaltene Danke: 1
Arch Linux
Eclipse
|
Verfasst: So 29.09.02 10:38
ich will dich ja nicht enttäuschen, aber mit meiner Methode (über SendBuf)
habe ich schon Dateien um die 100MB geschickt -> es ist durchaus mit SendBuf möglich.
_________________ Viele Grüße
Jakob
|
|
O'rallY 
      
Beiträge: 563
|
Verfasst: So 29.09.02 13:50
Verdammt! *g* Ich bleib trotzdem bei SendStream. Wozu hat man es denn... 
_________________ .oO'rallY
Linux is like a tipi: No gates, no windows and a gnu-eating apache inside...
|
|
DeCodeGuru
      
Beiträge: 1333
Erhaltene Danke: 1
Arch Linux
Eclipse
|
Verfasst: So 29.09.02 15:17
hast recht
_________________ Viele Grüße
Jakob
|
|
|