Entwickler-Ecke

Delphi Language (Object-Pascal) / CLX - Probleme mit Array of Byte Buffer


Seraph - Fr 31.10.08 19:21
Titel: Probleme mit Array of Byte Buffer
Hi Leute!

Ich beschäftige mich zur Zeit mit der Dateiübertragung zwischen Sockets!
Ziel ist es, eine Datei zwischen Client(TClientSocket) und Server(TServerSocket) zu übertragen ohne NichtStandard-Komponenten zu verwenden!

Ja denk ich mir: Kein Thema, oder doch?

Mein Denkansatz war der! Ich mache eine Schablone als Array of Bytes und lege diese Blockweise über meine Datei. Danach verschicke ich den so entstandenen ByteBuffer via Socket.SendBuf();
Auf der Serverseite hole ich via Socket.ReceiveBuf() das ganze wieder in ein Array of Bytes und schreibe is wieder Blockweise in eine Datei!

So der bisherige Code:


Delphi-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:
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:
//Client:----------------------------------------

//....

type TFileBlocks = Array [0..1024 - 1of Byte; //meine Schablone

var
  Form1: TForm1;
  FileBuffer: TFileBlocks;
  SendFile: file;

implementation


//...

procedure SendFileBlock(StartBlock: Integer);
var
 iReadCount: Integer;
begin
 ZeroMemory(@FileBuffer, 0);

 if(not eof(SendFile))
 then begin
  BlockRead(SendFile, FileBuffer, sizeof(FileBuffer), iReadCount);
  Form1.ClientSocket1.Socket.SendBuf(FileBuffer, iReadCount);
 end else begin
  CloseFile(SendFile);
  CloseFile(tFile);
  Form1.ClientSocket1.Socket.SendText('endoffile'); //server sendet 'next' bis 'endoffile'
 end;
end;

procedure TForm1.SendFileBttnClick(Sender: TObject);
begin
  ClientSocket1.Socket.SendText('sending:Test.file'); //leitet das senden ein
end;

procedure TForm1.ClientSocket1Read(Sender: TObject;
  Socket: TCustomWinSocket);
var
 RecText: String;
begin
 RecText := Socket.ReceiveText;
 
 //hier die Kommunikation zwischen Server und Client
 if(RecText = 'ready')//der Server schickt 'ready', wenn die Datei geschickt werden kann 
 then begin
  AssignFile(SendFile, Path.Text);
  Reset(SendFile, 1);

  SendFileBlock(); //1. Block schicken (siehe oben)
 end else if(RecText = 'next')//wenn der Server 'next' schickt...
 then begin
  SendFileBlock(); //nächsten Block schicken (siehe oben)
 end;
end;
//__________________________
//__________________________



Delphi-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:
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:
//Server:--------------------------------------------------

//...

type TFileBlocks = Array [0..1024of Byte;
pBuffer = ^TFileBlocks;

var
  Form1: TForm1;
  FILE_NAME: String;
  TargetFile: file;

implementation


//...

procedure TForm1.ServerSocket1ClientRead(Sender: TObject;
  Socket: TCustomWinSocket);
var
 RecText: String;
 BlockCount, WriteCount: Integer;
 RecLength: Integer;
 bBuffer: Array of Byte;
 pFileBuffer: pBuffer;
begin
 RecLength := Socket.ReceiveLength;
 RecText := Socket.ReceiveText;
 
 //BITTE KEIN KOMMENTAR ZU MEINEN ABFRAGEN ;-)
 //ICH MACH DAS EIGENTLICH ÜBER EINE EXPLODE FUNC,
 //ABER ICH GLAUBE DASS SIE HIER NUR ZUR ALLGEMEINEN VERWIRRUNG BEITRAGEN WÜRDE
 if(MidStr(RecText, 1, StrLen(PChar('sending:'))) = 'sending:')
 then begin
  FILE_NAME := MidStr(RecText, StrLen(PChar('sending:')) + 1, StrLen(PChar(RecText)) - StrLen(PChar('sending:')));

  AssignFile(TargetFile, 'C:\' + FILE_NAME);
  Rewrite(TargetFile, 1);

  ServerSocket1.Socket.Connections[0].SendText('ready');
 end else if(RecText = 'endoffile')
 then begin
   CloseFile(TargetFile);
   ShowMessage('ENDE');
 end else begin
  ZeroMemory(pFileBuffer, 0);

  GetMem(pFileBuffer, RecLength);

  Socket.ReceiveBuf(pFileBuffer , BlockCount);
  
  BlockWrite(TargetFile, pFileBuffer^, RecLength, WriteCount);
  ServerSocket1.Socket.Connections[0].SendText('next');
 end;
end;


Es ist ja nicht so dass jetzt in der Datei nix drin steht!

Der Inhalt der orginalfile ist:

Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
#EXTM3U
#EXTINF:326,Black Eyed Peas - My Humps
Personal Dats\Mucke2\005 - Black Eyed Peas - My Humps.mp3
#EXTINF:225,Rammstein - Benzin
Personal Dats\Mucke2\006 - Rammstein - Benzin.mp3
#EXTINF:213,Sean Paul - We Be Burnin'
Personal Dats\Mucke2\008 - Sean Paul - We Be Burnin'.mp3
#EXTINF:237,20 Pink - Just like a Pill
Personal Dats\Mucke2\01 - 20 Pink-Just like a Pill.mp3
#EXTINF:207,Jack Johnson - Better Together
Personal Dats\Mucke2\01 - Better Together.mp3
....

Ja das ist eine Winamp Playlist ;-)


Das ist das, was dabei raus kommt: :-(

1. Variante:

Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
òÍ
(

54,Michael Jackson - Wanna Be Startin Somethin 2008
Personal Dats\Mucke2\Top100_4_08\067-michael_jackson_-_wanna_be_startin_somethin_2008-ministry.mp3
#EXTINF:215,Colbie Caillat - The Little Things
Personal Dats\Mucke2\Top100_4_08\068-colbie_caillat_-_the_little_things-ministry.mp3
#EXTINF:203,Kanye West ft Chris Martin - Homecoming
Personal Dats\Mucke2\Top100_4_08\069-kanye_west_ft_chris_martin_-_homecoming-ministry.mp3
#EXTINF:233,Amy Winehouse - Valerie
...


2. Variante ist dann Binäres gedöns!

Es sieht immer anders aus! :-(

Huhuhuuuuuu..... Ich hock dran und könnt kotzen!


Danke im Voraus und Gruß,
Seraph


Ps.: @Narses: Dein Tutorial hab ich schon gesehen (Respekt übrigens) aber das ist mächtiger als das was ich benötige!

Es muss doch auf diesem Weg gehen!


Sinspin - Fr 31.10.08 20:25

Das Senden von binären Daten ist nicht ganz so einfach wie es mit Texten läuft, was im übrigen auch ginge.
Du könntest die Datei als einzelne Strings übertragen, die ja intern nichts weiter als eine Folge von Bytes sind.
Aber besser ist es natürlich es mit SendBuf zu erledigen.
Als erstes solltest du der anderen Seite natürlich mal mitteilen wie groß die Datei ist die du übertragen willst.
Das erleichtert es dir hinterher das zusammenbauen. Da du dann weist wann nichts mehr kommen kann was mit der Datei zu tun hat.
Des weiteren solltest du beim addressieren des Puffers mit dem du arbeitest die Addresse der ersten Speicherstelle angeben:

Delphi-Quelltext
1:
2:
  BlockRead(SendFile, FileBuffer[0], sizeof(FileBuffer), iReadCount);
  Form1.ClientSocket1.Socket.SendBuf(FileBuffer[0], iReadCount);

Beim Lesen machst du das ganze dann genauso. Denn das was du da schreibst deutet darauf hin das du dir an irgend einer Stelle Daten einhandelst die irgendwo im Speicher stehen, nur nicht dort wo du es willst.


Seraph - Mo 03.11.08 14:23

Danke für deine schnelle Antwort Sinspin,
aber das Funktioniert auch nicht!

Der Buffer muss doch so wie er Deklariert wurde [0..XXXX] passen oder etwa nicht?

Bin echt ratlos langsam!

Ich scheine so nah dran zu sein, aber der letze Funke will net überspringen!

Die größe der Datei passt exakt!
Aber der Inhalt ist größtenteils für den *popo*!

Währe cool, wenn mir noch jemand den letzten Hinweis geben könnte!

Danke im Voraus,
Seraph

p.s.: wenn ich mir den Buffer mit ReadText ausgeben lasse, dann erscheinen die Blöcke exakt richtig und vollständig!


Seraph - Mi 12.11.08 12:37
Titel: Push
Klappt bis heute nicht!

Keiner ne Idee?


jaenicke - Mi 12.11.08 13:50

Moment mal:

Delphi-Quelltext
1:
2:
3:
  ZeroMemory(pFileBuffer, 0);

  GetMem(pFileBuffer, RecLength);
Du füllst da Speicher mit 0, aber was ist das denn für Speicher? Du hast pFileBuffer ja noch gar nicht initialisiert.

Ich vermute du überschreibst da Speicher, was sich bei später ausgeführtem Code dann bemerkbar macht.


Volle - Mi 12.11.08 14:11

Hoi,

bin mir grad nich sicher aber musst du nich aus


Delphi-Quelltext
1:
BlockRead(SendFile, FileBuffer, sizeof(FileBuffer), iReadCount);                    


das hier machen?

Delphi-Quelltext
1:
BlockRead(SendFile, FileBuffer, 1024*sizeof(FileBuffer[0]), iReadCount);                    


gibt sizeof() in diesem fall nich einfach nur die groesse eines Pointers aus?
Hoffentlich erzaehl ich hier grad kein mist ....

cYa

[edit]
ich hab mist erzaehlt ... :<
vergiss es .. hab da was verwechselt ...
[/edit]