Autor Beitrag
alexschultze Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 317



BeitragVerfasst: Sa 07.12.02 12:29 
ich hab jetzt wieder ausprobiert:

ausblenden Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
 memostr:=Tmemorystream.create;

 memostr2:=Tmemorystream.create;

socket.ReceiveBuf(memostr, sizeof(TMemoryStream));
memostr2.copyfrom(memostr,memostr.size-6);


memostr2.write(RecRecord, SizeOf(TMyRecord));

anstelle von memostr.size-6 hatte ich schon:
memostr.size+6
sizeof(tmemorystream)+6
sizeof(tmemorystream)-6

alles ohne Erfolg :(((

bin ratlos :(
alexschultze Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 317



BeitragVerfasst: Sa 07.12.02 20:06 
ich hab rausgefunden, dass:

Server:
ausblenden Quelltext
1:
2:
3:
sendrecord.s1:='Zonk';
sendrecord.s1:='Döner Kebab';
Socket.SendBuf(Sendrecord, SizeOf(TMyRecord));

Client:
ausblenden Quelltext
1:
2:
3:
4:
socket.ReceiveBuf(recrecord, sizeof(TMyRecord));

showmessage(RecRecord.s1);
showmessage(RecRecord.s2);

schon nicht geht!!!!!!!

Was ist falsch? Was ist zu verbessern?
*help* ist dringend :((
Savage
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 110



BeitragVerfasst: So 08.12.02 10:19 
Hallo,

ich habe mir das ganze nochmal angeschaut.
Ich würde das was ich sende und empfange zuerst in einen Memorystream packen. Also ich würde nicht SendBuf verwenden sondern sendstream.

Ich Zeige dir im unteren Teil, wie man aus einen String mit fester länge und einen Record einen Memorystream macht und ihn wieder auseinander nimmt.
Wie man den empfangenen Buffer in einen Stream umwandelt.

Also ein paar Grundlagen, die du zB verwenden kannst.

Bsp1:
Ich habe einen Record mit 2 ShortString's geschrieben und verwende diesen als myrec. Ich erstelle einen Memorystream und speichere dort zuerst einen Befehl mit der länge 5 und danach den Record. Danach lese ich aus den Stream den Befehl und den Record. Verwende also den Stream als Zwischenstation.

ausblenden volle Höhe 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:
type
   myrec = record
    rec1 : ShortString;
    rec2 : Shortstring;
 end;

...

var ms : TMemorystream;
    mrec,mrec2 : Myrec;
    i : Integer;
    s,s2 : Shortstring;
begin

mrec.rec1 := 'Zeile 1';
mrec.rec2 := 'Zeile 2';
s := 'Hallo';
i := Sizeof(mrec);

ms := TMemorystream.Create;

// String + Record in Stream schreiben
ms.WriteBuffer(s,6);         // ! länge des Strings + 1
ms.writeBuffer(mrec,i);

//String + Record wieder extrahieren
ms.Position := 0;             // !
ms.ReadBuffer(s2,6);      // ! länge des Strings + 1
ms.position := 6;            // !
ms.Readbuffer(mrec2,i);

//Testen
memo1.Lines.Add(mrec2.rec1);
memo1.Lines.Add(mrec2.rec2);
memo1.lines.add(s2);

end;



Bsp 2:
Bei OnRead empfange ich einen Buffer, bei receivebuf glaube ich einen Pointer. Man muss also ersteinmal den Buffer in den Stream laden.

ausblenden Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
var i : Integer;
    p : PChar;
    ms : TMemorystream;
begin

i := socket.ReceiveLength;
 getmem(p,i);                //Speicher reservieren
 socket.ReceiveBuf(p^,i);    //Puffer in den PCHar legen

 ms := TMemorystream.Create;
 ms.Write(p^,i);             // Puffer in einen Stream laden
 freemem(p);

end;


Danach hast du also den empfangen Buffer wieder in einen Stream und kannst ihn wie in Bsp2 extrahieren.

Das war die Variante, die ich immer verwende. Es geht bestimmt auch noch anders (vieleicht sogar einfacher), aber das müsste jetzt eigentlich funktionieren.

Viel spaß beim probieren :wink:

MfG
Savage
alexschultze Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 317



BeitragVerfasst: So 08.12.02 10:49 
ich probiere schon seit Ewigkeiten ;)

ich hab jetzt noch ein paar Sachen herausgefunden:
wenn man zweimal hintereinander sendText macht, kommt bei receivetext beides zusammengepresst.

Weiter: wenn man sendText und SendBuf direkt hintereinander macht, werden das 2 Pakete.


Und wenn man ein receiveText o.ä. macht, dann werden der receivetext, als auch receivebuf geleert!

Ich glaub ich hab den Dreh raus ;)

ich probier noch ein bissl. aber deine Methode ist in mein momentan schon mit Strings arbeitenten Programm schwerlich zu integrieren. Aber ich schau mal.
Savage
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 110



BeitragVerfasst: So 08.12.02 10:59 
aber du musst eines noch beachten. Wenn das Paket "sehr groß" ist, kann es auch passieren, dass ein Paket geteilt ankommt, sprich hintereinander in 2 Paketen.

Mir passiert das z.B., wenn ich eine HTML-Seite (ca. 40 kb) aus dem Inet über einer TClientsocket-Kompo downloade. Diese kommt bei mir öffters mal mit 2 oder gar 3 Stücken an. Ob das jetzt nur im HTTP-Verkehr so ist oder generel so, weis ich nicht, aber du kannst ja mal darauf achten.

MfG
Savage
alexschultze Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 317



BeitragVerfasst: So 08.12.02 11:10 
das ist definitiv so und von der Buffergröße Abhängig (im langen Codebeispiel ist das ziemlich gut dargestellt, er nimmt die Pakete a 4096 Pakete ab, und zwar mehrmals hintereinander.
Meine Pakete werden die 4 KB-Größe nicht überschreiten, sind nur kleine Records!

also,
ich hab hier aktuell:

Server:
ausblenden Quelltext
1:
2:
socket.SendText('Daten'+inttostr(sizeof(sendrecord)));
Socket.SendBuf(Sendrecord, SizeOf(sendrecord));


Client:
ausblenden volle Höhe 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:
procedure TForm4.ClientSocket1Read(Sender: TObject;
  Socket: TCustomWinSocket);
if AwaitRecord=true then begin
 socket.ReceiveBuf(recrecord, awaitrecordsize);
showmessage(RecRecord.s1);
showmessage(RecRecord.s2);
awaitrecord:=false;
end;




received:=socket.ReceiveText;
form3.Label1.Caption:='Connected !';



if copy(received, 1, 5) = 'Daten' then begin
if (MatchesMask(received,'*´ÉM')) then begin
 clientsocket1.Socket.SendText('Record');
 abort;
end;


//showmessage(received);
memo1.Lines.Add(received);
Delete(received, 1, 5);
AwaitrecordSize := StrToInt(received);




Awaitrecord:=true;
end;


aber auch in dieser Reihenfolge bringt das immer ein leeres Ergebnis!!!
:(
Nun bin ich wirklich am verzweifeln. Ich experimentiere mal schnell mit statischen Strings, aber so wie das aktuell ist, gefällt mir das gar nett. Wieso geht das nett? :(

ach so, das (MatchesMask(received,'*´ÉM')) ist hiermit zu erklären:

Ab und zu (meist am Anfang des Programms) sendet der Server an den Clienten bei Text+Buf folgendes:
Daten20*´ÉM

fragt micht nicht wieso. Habt ihr ne Idee?
Wie ihr seht hab ich das umgangen in dem ich das Paket beim Server erneut anfordere, bis es fehlerfrei ist.
alexschultze Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 317



BeitragVerfasst: So 08.12.02 11:18 
okay, ich arbeite jetzt erfolgreich mit statischen Records. Aber des öfteren kommen auch hier irgendwelche Zusammengepappten Informationen...

na, mal schaun
DataCool
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 112



BeitragVerfasst: Mo 09.12.02 23:59 
Also, ich hab mir jetzt das gesamte Thema durchgelesen und muss sagen :
Das kommt mir sehr bekannt vor :wink:

Ich habe nämlich gerade erst vor 2 Monaten eine nicht kleine Client/Server Anwendung fertiggestellt, die verschiedene Datenbank miteinander abgleicht.

Aber zurück zum Thema :
Weg mit TClientSocket u. TServerSocket :twisted:

Glaubt mir ich habe fast zwei Wochen am Anfang meines Projekts damit verschwenden :bawling: bis ich dann auf Leidensgenossen in diversen Foren gestossen bin.
Die Lösung ist die Verwendung von den Indy-Komponten 8)

Im allgemeinen würde bei unterschiedlichen Daten zwei Ports zur kommunikation nutzen.
1. Port um Informationen auszutauschen, wie sende gleich Filestream mit der Größe 5MB oder File erfolgreich erhalten usw. ! Einfach halt ein kleines Nachrichten Protokoll entwerfen.

2. Port = Datenport
Dieser wird immer nur für Daten der Länge von xxxx Bytes geöffnet, wenn dies vorher auf Port 1 angekündigt wurde.

Das war auf jeden Fall im meinem Projekt notwendig, sonst hätte ich die Übersicht verloren, da das ganze Multi-Threaded abläuft. :mrgreen:


Wenn man mit einem Port auskommen möchte würde ich wie auch schon weiter oben erwähnt, Deine Daten in einer XML-Datenstruktur ablegen und diese über einen MemoryStream verschicken(aber mit Indy). :wink:

So, das wärs fürs erste. :mahn: :beer:

Sonst noch jemand irgentwelche anderen Erfahrungen ? :nut:

_________________
DataCool
alexschultze Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 317



BeitragVerfasst: Mo 16.12.02 19:30 
sagt mal, hat ein array of pchar mit 5000 Elementen eine Größe von 5000 Byte alswie ca. 5 kb?