Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Netzwerke (https://www.delphipraxis.net/14-netzwerke/)
-   -   Delphi wie versende ich mit tclient/serversocket eine datei? (https://www.delphipraxis.net/76747-wie-versende-ich-mit-tclient-serversocket-eine-datei.html)

gandime 9. Sep 2006 00:00


wie versende ich mit tclient/serversocket eine datei?
 
hi,
ich wollte fragen wie ich mit tserversocket und mit tclientsocket eine datei verschicke?

mfg gandime

flossinger 9. Sep 2006 00:40

Re: wie versende ich mit tclient/serversocket eine datei?
 
Jo,

kommt darauf an.

Beispielsweise mit .sendstream .

der flossinger

gandime 9. Sep 2006 09:24

Re: wie versende ich mit tclient/serversocket eine datei?
 
ja soweit bin ich auch schon aber wie emfange ich das dann?

edit:
mein bisheriger versuch

clinet:
Delphi-Quellcode:
procedure TForm1.Button1Click(Sender: TObject);
var
  FStream: TFileStream;
begin
  ClientSocket1.Active:=true;
  ClientSocket1.Socket.Connect(5000);
  FStream := TFileStream.Create('C:\la.avi', fmOpenRead or fmShareDenyWrite);
  ClientSocket1.Socket.Write(FStream.Size);
  ClientSocket1.Socket.SendStream(FStream);
  ClientSocket1.Socket.Disconnect(5000);
  ClientSocket1.Active:=false;
  freeandnil(fstream);
end;

server:
Delphi-Quellcode:
procedure TForm1.ServerSocket1ClientConnect(Sender: TObject;
  Socket: TCustomWinSocket);
var
  FStream:tfilestream;
  i_size:integer;
begin
  FStream := TFileStream.Create('C:\ka.avi', fmCreate or fmShareExclusive);
  Socket.Read(i_size);
  Socket.ReceiveBuf(fstream,i_size);
  freeandnil(fstream);
end;

flossinger 9. Sep 2006 10:58

Re: wie versende ich mit tclient/serversocket eine datei?
 
Du hast da ein paar falsche Annahmen über das Funktionieren der Sockets. Ist kein Wunder, sie sind schlecht dokumentiert. Sei froh, sie funktionieren viieel einfacher, als du glaubst.

Ein kleines Demobeispiel, das grundlegende Funktionen zeigt:
Delphi-Quellcode:
procedure log(text:string);
begin
form1.memo1.lines.add(text);
end;

procedure TForm1.Button1Click(Sender: TObject);
var stream1:tfilestream;filename:string;
begin
filename:= 'C:\irgendeinPfad\test.txt';
stream1:=tfilestream.Create(filename,fmOpenRead or fmShareExclusive);
serversocket1.Socket.connections[0].SendStream(stream1);
end;

procedure TForm1.ClientSocket1Read(Sender: TObject;
  Socket: TCustomWinSocket);
begin
log(socket.receivetext);
end;
Wenn empfangen wird, wird das read ereignis ausgelöst. Zum Zeitpunkt connect Ereignis kannst du noch nichts auswerten. Connect sagt nur, dass die Verbindung steht, nicht das Daten da sind.

grüsse,
der flossinger

gandime 9. Sep 2006 12:41

Re: wie versende ich mit tclient/serversocket eine datei?
 
ich verstehe ich ganz wie das funktionieren soll

client:
Delphi-Quellcode:
procedure TForm1.Button1Click(Sender: TObject);
begin
  ClientSocket1.Active:=true;
  ClientSocket1.Socket.Connect(5000);
end;

procedure TForm1.ClientSocket1Read(Sender: TObject; Socket: TCustomWinSocket);
begin
  FStream := TFileStream.Create('C:\ka.mdf', fmCreate or fmShareExclusive);
  i_size:=strtoint(socket.ReceiveText);
  socket.ReceiveBuf(fstream,i_size);
end;
server:
Delphi-Quellcode:
procedure TForm1.Button1Click(Sender: TObject);
begin
  FStream := TFileStream.Create('X:\bluetooth.mdf', fmOpenRead or fmShareDenyWrite);
  serversocket1.Socket.connections[0].SendText(inttostr(fstream.Size));
  serversocket1.Socket.connections[0].SendStream(fstream);
end;
blos wo is da der fehler?

flossinger 9. Sep 2006 13:22

Re: wie versende ich mit tclient/serversocket eine datei?
 
Zitat:

Zitat von gandime
ich verstehe ich ganz wie das funktionieren soll
blos wo is da der fehler?

ja von welchem Fehler sprichst du denn? Vielleicht machst du dir mal die Mühe Fehlermeldungen zu lesen und bei deinen Hilferufen wörtlich zu posten.

Was soll .connect(5000) bewirken? ist unverständlich.

Fehler:

.receivebuf verlangt als 1. Parameter einen bufferpointer, keinen stream.

Wenn du mit .sendtext was sendest, heisst das noch lange nicht, das bei on read nur dieser Inhalt empfangen wird.
Wenn du mit sendstream was sendest, heisst das nicht, das nur der Stream bei onread empfangen wird, oder dass der in einem Paket empfangen wird.

Bei einem read ereignis können mehrere getrennt gesendete Inhalte aneinander kleben. Ein Stream kann in Teilen mit mehreren read Ereignissen ankommen.

Dein Projekt scheint zwei Nummern zu gross für dich zu sein. Man muss bei einem Projekt zumindest so weit sein, dass man konkrete sinnvolle Fragen stellen kann, sonst kann einem keiner helfen. Und man sollte in der Lage sein Anbtworten zu lesen und den Code aus Antworten zu testen und zu modifizieren.

der flossinger

Muetze1 9. Sep 2006 13:44

Re: wie versende ich mit tclient/serversocket eine datei?
 
Zitat:

Zitat von flossinger
Delphi-Quellcode:
procedure log(text:string);
begin
form1.memo1.lines.add(text);
end;

Für einen Anfänger ein mehr als schlechtes Beispiel: Nutze niemals eine Instanzenvariable direkt für den Zugriff auf Elemente der Klasse. Wenn, schreibe eine Methode und lass bloss die Instanzenvariable aus dem Spiel!

@Threadersteller:
http://www.delphipraxis.net/internal...ct.php?t=81128
http://www.delphipraxis.net/internal...ct.php?t=53882

gandime 9. Sep 2006 14:14

Re: wie versende ich mit tclient/serversocket eine datei?
 
also:

Zitat:

Zitat von flossinger
Was soll .connect(5000) bewirken? ist unverständlich.

ich kenne leider den tserversocken und clientsocket nicht so besonders gut und deshalb wusste ich nicht, dass wenn der client aktiviert wird, dass er sofort connectet.

Zitat:

Zitat von flossinger
.receivebuf verlangt als 1. Parameter einen bufferpointer, keinen stream.

ja tut mir leid habe ich nicht dran gedacht

Zitat:

Zitat von flossinger
Dein Projekt scheint zwei Nummern zu gross für dich zu sein. Man muss bei einem Projekt zumindest so weit sein, dass man konkrete sinnvolle Fragen stellen kann, sonst kann einem keiner helfen. Und man sollte in der Lage sein Anbtworten zu lesen und den Code aus Antworten zu testen und zu modifizieren.

also dazu
nein das projekt ist ganz bestimmt keine 2 nummern zu groß für mich!

ich versuche ja immer konkrete fragen zu stellen aber wenn ich noch absolut ka habe wie das mit dem socket modul geht ist das meinermeinung nach schlecht

flossinger 9. Sep 2006 14:17

Re: wie versende ich mit tclient/serversocket eine datei?
 
ja fein,
dann läuft ja alles bestens

der flossinge

flossinger 9. Sep 2006 14:26

Re: wie versende ich mit tclient/serversocket eine datei?
 
@koos

es ist ja wunderbar, wie du solche Grundsätze herunterbeten kannst. Aber ein paar Demozeilen, in denen es um etwas anderes geht, so klugscheisserisch zu kritisieren, das entbehrt nicht eines etwas skurilen charmes. Aber gratuliere, dass du eine anscheinend dringend benötigte Glegenheit gefunden hast, dein ach so grosses Wissen zu verbreiten.

smiling, der flossinger

gandime 9. Sep 2006 15:07

Re: wie versende ich mit tclient/serversocket eine datei?
 
so und jetzt habe ich mich malwieder etwas damit bescheftig und ich hoffe das es jetzt etwas besser is als vorher, aber es geht immer noch nicht so wie ich es will

client:
Delphi-Quellcode:
procedure TForm1.Button1Click(Sender: TObject);
var
  buffer:pointer;
begin
  FStream := TFileStream.Create('X:\bluetooth.mdf', fmOpenRead or fmShareDenyWrite);
  buffer := AllocMem(fStream.Size);
  FStream.Read(buffer^,FStream.Size);
  ClientSocket1.Socket.SendBuf(buffer^,FStream.Size);
  FreeMem(buffer);
  FreeAndNil(fstream);
end;
server:
Delphi-Quellcode:
procedure TForm1.ServerSocket1ClientRead(Sender: TObject;
  Socket: TCustomWinSocket);
var
  buffer:pointer;
  len:integer;
begin
  len := Socket.ReceiveLength;
  FStream:=tfilestream.Create('c:\ka.mdf',fmcreate);
  FStream.Seek(0,soFromEnd);
  buffer := AllocMem(len);
  socket.receivebuf(buffer^,len);
  FStream.Write(buffer^,len);
  FreeMem(buffer);
  freeandnil(FStream);
end;

flossinger 9. Sep 2006 15:32

Re: wie versende ich mit tclient/serversocket eine datei?
 
in welcher Zeile tritt der Fehler auf, und wie heisst die Fehlermeldung? Oder was ist das falsche Ergebnis genau?

poste konkrete und vollständige Fehlermeldungen und keine allgemeinen Klagen.

der flossinger

gandime 9. Sep 2006 16:01

Re: wie versende ich mit tclient/serversocket eine datei?
 
so das problem is:
ich bekomme keine fehlermeldung und die datei wird nur zum teil übertragen

flossinger 9. Sep 2006 16:16

Re: wie versende ich mit tclient/serversocket eine datei?
 
na endlich, juhuuuu,

er gibt information von sich. Vielleicht gehts etwas genauer:

Wieviele bytes werden gesendet, wieviele werden on read empfangen, in wieviel durchgängen und wieviele werden im File gespeichert.

Enthält dein File den Anfang oder das Ende des gesendeten Streams?


Du bist hier im Thread schon darauf hingewiesen worden, dass ein Stream in Stücken mit mehreren read ereignissen ankommen kann. Wo triffst du Vorsorge dafür? Vielleicht ist es sinnvoll, die bisherigen Hinweise genau und vollständig durch zu lesen.

Anderes, zukünftiges Problem: Was passiert, wenn der File sehr gross ist und du erzwingst auf der Sendeseite eine Puffergrösse in Grösse der Filelänge. Puffer werden verwendet, um genau das zu vermeiden. .sendstream handelt den Puffer ohnehin sebsttätig.

der flossinger

Muetze1 9. Sep 2006 18:25

Re: wie versende ich mit tclient/serversocket eine datei?
 
Zitat:

Zitat von flossinger
@koos

es ist ja wunderbar, wie du solche Grundsätze herunterbeten kannst. Aber ein paar Demozeilen, in denen es um etwas anderes geht, so klugscheisserisch zu kritisieren, das entbehrt nicht eines etwas skurilen charmes. Aber gratuliere, dass du eine anscheinend dringend benötigte Glegenheit gefunden hast, dein ach so grosses Wissen zu verbreiten.

smiling, der flossinger

Ich habe einen Nick und man muss nicht unbedingt einem mit dem Nachnamen ansprechen. Und ich weiss nicht warum ich ein Beispiel geben sollte wie eine Methode aussieht. Ich habe geschrieben wie man das angesprochene Makel leicht beheben kann und du willst wirklich das ich als Beispiel Codezeilen dazu liefere? Also wenn dir nicht bewusst ist was der Unterschied zwischen Methoden und Proceduren ist, dann glaube ich auch nicht, dass dir die Codezeilen helfen werden. Aber bitte, hier hast du sie:

Delphi-Quellcode:
procedure TForm1.log(text:string);
begin
  memo1.lines.add(text);
end;
Und, hilft's?

Obwohl ich nicht glaube das es beachtet wird, aber trotzdem noch ein paar Dinge (und nein, ohne Code - wenn man es selber macht, versteht man es besser...)

1. Einen TFileStream mit fmCreate im Konstruktor überschreibt auch vorhandene Dateien, also müsste unterschieden werden ob die Datei schon vorhanden ist oder nicht und entsprechend andere Parameter übergeben werden.
2. SendStream() beim senden war doch recht einfach und hat die Sache genauso gut erledigt. Du merkst ja vielleicht selber, dass der neue Weg über einen Buffer umständlicher ist als nötig (zumindest beim senden)
3. Wenn die Datei grösser ist, dann hast du beim Empfangen (sowie zZ noch beim Senden) ein Problem, da du soviel Speicher alloziierst. Besser wäre hier eine feste Puffergrösse und entsprechend immer Blockweise einlesen und senden bis alle Daten empfangen/gesendet wurden.

flossinger 9. Sep 2006 19:06

Re: wie versende ich mit tclient/serversocket eine datei?
 
aber koos,

durch Wiederholungen wird das schon gesagte weder wichtiger noch relevanter für den Ursprungsposter. Auch wenns die Amsel nocht so oft singt.

Bei so viel Wiederholungen ihrerseits, kommt der Verdacht auf, dass sie die threads, in denen sie posten, nicht lesen. Nichtsdetoweniger ist ihnen die Bewunderung für ihre Weisheit sicher.

Wunderbar - alles so frisch aus dem Lehrbuch.

hochachtungsvoll,
der flossinger

Muetze1 9. Sep 2006 19:20

Re: wie versende ich mit tclient/serversocket eine datei?
 
Hach, Bergsmann,

Zitat:

Zitat von flossinger
durch Wiederholungen wird das schon gesagte weder wichtiger noch relevanter für den Ursprungsposter. Auch wenns die Amsel nocht so oft singt.

Ich habe Ihren Code kritisiert und es betrifft Sie und war für Sie gedacht und nicht für den Ursprungsposter. Aber solche Sachen werden erfolgreich von Ihnen ignoriert. Gratulation - aber immerhin konsequent.

Zitat:

Zitat von flossinger
Bei so viel Wiederholungen ihrerseits, kommt der Verdacht auf, dass sie die threads, in denen sie posten, nicht lesen.

Hmm, wie komme ich nur auf fehlerhafte Stellen im Code welche die wage beschriebenen Dinge verursachen können (fmCreate)? Naja, war mir wohl im Traum eingefallen, da ich den Thread ja nicht lese. Aber kein Problem, ich werde nichts mehr von mir geben, Sie haben ja alles im Griff - mit den geheimnisvollen Dingen aus einem Nicht-Lehrbuch.

Zitat:

Zitat von flossinger
Wunderbar - alles so frisch aus dem Lehrbuch.

Keine Ahnung, in Sachen Programmierung habe ich mir noch nie eins angeschaut. Könnte sehr gut sein, aber da vertraue ich Ihnen mal und fühle mich voller Stolz, dass ich es genauso sehe wie grosse Lehrbuch-Autoren.

Neidvoll sich vor Ihren pädagogischen Wissen beugend,
Muetze1

flossinger 9. Sep 2006 19:32

Re: wie versende ich mit tclient/serversocket eine datei?
 
Na, wenigstens vestehenn sie Ironie und können google benützen.

In der Praxis kümmere ich mich bei einem Testbeispiel tatsächlich und absichtlich nicht um Randthemen, wenn es darum geht, sich auf das Wesentliche zu beschränken. Das können sie gern kritisieren, wenn es hilft, ihr ego aufzublasen. Es tut mitr nur leid, das bei so viel Selbstdarstellung das Ursprungsthema so stark in den Hintergrund tritt, dass der thread schon langweilig geworden ist.

gähnend, der flossinger

flossinger 10. Sep 2006 06:42

Re: wie versende ich mit tclient/serversocket eine datei?
 
@ gandime

tut mir leid, dass ich mich von deinem Hauptthema habe ablenken lassen.

Du hast eine fehlerhaftes Ergebnis und weisst nicht, woran das liegt.
Der beste Weg da weiter ztu kommen ist, sich an zu sehen, was GENAU geschieht.

Ein Weg ist, sich zusätzlich ein memo zu Testzwecken auf das Form zu ziehen und dort jeden ereignisaufruf protokollieren zu lassen. Dazu gleich festhalten, wieviel daten verarbeitet werden und eventuell welche Daten genau. Stringlängen, Filegrössen und andere Werte sind oft zu Beginn und am Ende einer procedure interessant.

So weisst du, wieviel und was gesendet wurde, wieviel und was davon ankommt, wieviel und was in den file geschrieben wurde. In weiterer Folge lernst du die Konsequenzen von Befehlen gut kennen, auch wenn dir eine gute Dokumentation fehlt.

Grüsse,
der Flossinger

gandime 10. Sep 2006 16:15

Re: wie versende ich mit tclient/serversocket eine datei?
 
joa da is dann das prob wie zerteile und setzte ich die datei?

flossinger 10. Sep 2006 18:13

Re: wie versende ich mit tclient/serversocket eine datei?
 
ja wie meinst du die Frage nach dem Teilen und Zusammensetzen. Es wurde schon ein Beispiel gepostet, das völlig korrekt teilt und zusammensetzt. Damit ist deine Frage ja schon beantwortet. Es hat wenig Sinn, so etwas zu wiederholen, nachdem dir das nicht geholfen hat. Welchen Teil hast du nicht verstanden, welchen Teil hast du nicht nach vollzogen. Warum läuft ein funktionierendes Beispiel bei dir nicht?
Von welchem der Verarbeitungsschritte sprichst du jetzt? Was funktioniert bei deinen Testdaten und was genau funktioniert nicht?

Hast du schon herausgefunden, was dein Programm jetzt GENAU macht? Die entsprechenden Rückfragen wurden dir im Thread gestellt und deine Antworten stehen noch aus. Du hast schon eine Anleitung erhalten, WIE du das herausfinden kannst und wie du damit deine Fragen konkretisieren kannst.

Denkst du, du bekommst viele Antworten, wenn du die erteilten Antworten offensichtlich missachtest? Hast du eigentlich die Vorstellung dass sich viele Menschen danach drängen, eine Antwort zu geben, die voraussichtlich ignoriert wird? Überleg das mal in einer ruhigen Minute.

grüsse,
der flossinger

gandime 10. Sep 2006 21:19

Re: wie versende ich mit tclient/serversocket eine datei?
 
so das habe ich jetzt auch hinbekommen mit dem splitten usw. aber wie weiss das prog das die datei komplett ist damit es freeandnil(fstream) machen kann?

flossinger 11. Sep 2006 14:50

Re: wie versende ich mit tclient/serversocket eine datei?
 
gratuliere,

entweder ist zu Beginn die Anzahl der Bytes mitgeteilt worden, oder es gibt ein EOF Zeichen, das im File selbst sicher nicht vorkommt.

Erstere Variante verwendet beispielsweise das http Protokoll, bekanntlich: Content-Length: nnnn.

Letztere Variante eignet sich nur für bestimmte Files. Ein http header beispielsweise wird bekanntlich durch crlfcrlf beendet. crlfcrlf kann dazu verwendet werden, weil es im header selbst nie vorkommen kann. Anderes bekanntes Beispiel: Bei der Übertragung von emails wird crlf.crlf verwendet.

Dritte Variante: Es wird jedes mal vom Sender eine EOF sequenz gesucht, die im File nicht vorkommt, und dem Empfänger mitgeteilt.

Am besten ist es, du schaust dir die Protokolle in den rfcs an und baust etwas nach, das deinem beabsichtigten Einsatz am besten dient. Hat alles seine Vor- und Nachteile und es kommt ganz darauf an.

grüsse,
der flossinger

Arnulf 5. Feb 2007 21:59

Re: wie versende ich mit tclient/serversocket eine datei?
 
Zitat:

3. Wenn die Datei grösser ist, dann hast du beim Empfangen (sowie zZ noch beim Senden) ein Problem, da du soviel Speicher alloziierst. Besser wäre hier eine feste Puffergrösse und entsprechend immer Blockweise einlesen und senden bis alle Daten empfangen/gesendet wurden.
Tja ich denke genau an dem problem häng ich gerade.
Ich kann natürlich den stream zerlegen und die daten schön langsam senden.
Die frage ist aber wie langsam muß ich die daten schicken? - woher weiß ich wieviel puffer ich noch am socket hab bzw. wieviel schon weggeschickt wurde.

das sorgt bei mir noch für etwas verwirrung - ich hätte nämlich vor ein video zu streamen und das geht recht langsam von statten.

hoffe es gibt dazu noch tips
Arnulf

Muetze1 6. Feb 2007 00:17

Re: wie versende ich mit tclient/serversocket eine datei?
 
Lese deinen Puffer voll und schreibe ihn in den Stream. Und dies so lange, bis du die gesamte Datei/gesamten Daten im Stream hast.

Arnulf 7. Feb 2007 10:55

Re: wie versende ich mit tclient/serversocket eine datei?
 
Zitat:

Lese deinen Puffer voll und schreibe ihn in den Stream. Und dies so lange, bis du die gesamte Datei/gesamten Daten im Stream hast.
sorry wenn ich das nicht gleich verstehe.

ich soll den stream ganz einlesen und auch in den puffer - damit meinst wohl den pointer mit der size?

Delphi-Quellcode:
            AStream := TfileStream.Create(income, fmOpenRead or fmShareDenyWrite );
            try
               buffer := AllocMem(AStream.Size);
               AStream.Read(buffer^,AStream.Size);
und ja jetzt könnte ich von buffer weg nur teile in die sendstream methode schreiben.
die frage ist aber wie viel (bytes) kann in gleichzeit in die sendstream methode jagen ohne einen cache overflow im
socket zu bekommen.
Und wie weiß ich wann ich sendstream wieder aufrufen kann um den rest zu schicken?
Ich weiß ja nicht wie voll der cache ist.
also im prinzip das hier in packerl auf geteilt und hald langsamer in den stream geschickt - aber wenn ich da eine schleife mache, dann mach ich den cache ja wieder voll - oder irr ich mich da?

Delphi-Quellcode:
               with Socket do
                    SendBuf(buffer^, AStream.Size);
               finally
                      FreeMem(buffer);
                      FreeAndNil(AStream);
               end;
mit ist schon klar dass ich bei Astream.Size die größe eingeben kann - und in einer schleife einfach packerweise mehr schicken kann - aber macht das einen unterschied? - ich weiß ja immer noch nicht wie voll der socket cache ist bzw. ob ich einen overflow bekomme wenn ich zu viel rein schreibe.
thx
Arnulf

Arnulf 7. Feb 2007 11:09

Re: wie versende ich mit tclient/serversocket eine datei?
 
ok sorry - ich habs gerade ausprobiert und es funktioniert wirklich.
wenn jemand weiß warum würde ich das gerne wissen...
was macht den unterschied wenn ich den stream in packerln zerleg oder als ganzes rein schreib.
wie groß dürfen die packerln maximal sein?
also warum funktioniert das :)

lg
Arnulf
Edit:
also ganz richtig funktioniert es nicht - kann aber nur vermutungen anstellen warum.
ich bekomm jetzt keinen fehler mehr wenn ich eine 700 mb datei wegschicke.
allerdings schreib ich einen minni webserver und der muß ja die verbindung immer wieder trennen.

scheinbar trennt er die verbindung aber zu früh - bevor die datei noch ganz rauf geladen ist.
hier liegt wohl das gleiche problem wie vorher - ich kann die verbindung nicht trennen bevor nicht alles
rauf geladen ist:

so schaut der code aus:
Delphi-Quellcode:
              try
               buffer := AllocMem(AStream.Size);
               for s := 1 to AStream.Size div Package do
                 begin
                      AStream.Read(Buffer^,Package);
                      Socket.SendBuf(buffer^,Package);
                      Sleep (50);
                      uploaded := s;
                      memo1.Lines.Add(inttostr(uploaded * package));
                 end;
                 Sleep(50);
                 if ((uploaded*Package) < AStream.Size)
                 then begin
                      last := AStream.Size - (uploaded * Package);
                      AStream.Read(Buffer^,last);
                      Socket.SendBuf(buffer^,last);
                      end;
               finally
                 FreeMem(buffer);
                 FreeAndNil(AStream);
               end;
        socket.close;
das socket.close dürfte einfach zu früh kommen - aber darüber hab ich keine kontrolle zumindestens keine die ich kenne.
lg
Arnulf

Muetze1 7. Feb 2007 13:01

Re: wie versende ich mit tclient/serversocket eine datei?
 
1. Der Buffer braucht nur "Package" gross sein - schliesslich nutzt du auch nur soviel von ihm.
2. Der Socket hat intern einen Puffer und füllt den immer nur bis zu seiner Maximalgrösse. Wenn du nun mit SendBuf() Daten hinein schreibst, dann gibt dir SendBuf() zurück, wieviel er davon in seinen internen Buffer aufgenommen hat. Daher muss du auch darauf resgieren und entsprechend auch mal Teile von deinem Buffer erneut dem SendBuf() übergeben.
Zitat:

Zitat von Delphi Hilfe
Bei nicht-blockierenden Sockets werden die Daten an die WinSock DLL gesendet, die über eigene interne Puffer verfügt. Wenn WinSock weitere Daten akzeptieren kann, gibt SendBuf sofort die Anzahl der Byte in der Warteschlange zurück. Wenn der interne Puffer von WinSock den gesendeten Puffer nicht mehr aufnehmen kann, gibt SendBuf -1 zurück, und es werden keine Daten in die Warteschlange übernommen. In diesem Fall müssen Sie etwas warten, bis WinSock die sich bereits in der Warteschlange befindlichen Daten gesendet hat und es dann erneut versuchen.

3. Read() vom TStream gibt dir zurück, wieviele Bytes er ausgelesen hat. Somit kannst du leicht den Rückgabewert von Read() nutzen um ihn beim SendBuf() entsprechend anzugeben. Hierdrüber kannst du dir auch leicht deine letzte "Sonder-If-Abfrage" für das "Reste-senden" sparen.
4. Du hast selber schon geschrieben (fälschlicherweise wahrscheinlich), dass es noch die Methode SendStream() gibt. Diese erledigt alle von dir gesuchten Aufgaben asynchron. Du gibst ihr ein TStream Nachkomme (z.B. TFileStream) und sie kümmert sich um das Senden des Streams. Wenn der Stream erfolgreich gesendet wurde, dann gibt der Socket den Stream auch weider automatisch frei. Die SendStream() beinhaltet dein gesamten Code samt Warten etc. Du darfst nach der Übergabe der TStream Instanz diese nicht mehr weiter verwenden in deinem Programm, da der Socket in seinem Thread damit arbeitet.

PS: Und ja, so wie du es umgesetzt hast meinte ich es auch...

Arnulf 8. Feb 2007 20:08

Re: wie versende ich mit tclient/serversocket eine datei?
 
Ich verstehe - danke für deine genaue antwort.

Ich hab das ganze nochmal in java versucht :) weil ich in delphi damit nicht weiter gekommen bin.
Delphi-Quellcode:
             while ((len = is.read(buf)) != -1)
             {
               out.write(buf, 0, len);
              }
was in meinem fall genau garnichts gebracht hat... naja
jedenfalls verstehe ich jetzt warum ich mit sendstream immer so viele probleme hatte, weil ich den stream danach meistens gleich
wieder frei gegeben hab - und wenn der socket noch am senden war dann hatte das wohl ein jähes ende ...

jedenfalls wird mir hier einiges klarer - aber das löst mein problem nicht wirklich - leider.
irgendwie macht mich dieser streaming client von pinnacle noch wahnsinnig.
also wieder zurück zu delphi und weiter versuchen ..

Wenn ich das richtig verstehe, hab ich bei sendstream einfach keine kontrolle über den verlauf des sendens.
Ich weiß nicht wann er fertig ist und wieviel schon im puffer ist.
damit muß ich das eh manuell mit sendbuf machen damit kann ich wenigstens den stream genau kontrollieren ...

thx lg
Arnulf

PS: ja tatsächlich wer lesen kann ist klar im vorteil - und ich dachte da steht nichts vernünftiges drin
Zitat:

Note: The Stream passed as a parameter to SendStream becomes “owned” by the windows socket object. The Windows socket object frees the stream when it is finished with it. Do not attempt to free the stream after it has been passed as a parameter.

jokerfacehro 9. Feb 2007 08:09

Re: wie versende ich mit tclient/serversocket eine datei?
 
hallo,
da mich das Thema auch interessiert, hab ich grad ma fix ne funktion gebastelt,
die das hinkriegt.
es ist leichter als man denkt :D :D :D

zu erst senden wir alles per stream vom client:
Delphi-Quellcode:
procedure Button1Click(Sender: TObject);
var AStream:TFileStream;
begin
AStream := TFileStream.Create('hallo.txt', fmOpenRead or fmShareDenyWrite );
Clientsocket1.Socket.SendStream(AStream);
end;
so und jetz müssen wir das ganze nur noch am server empfangen :)
Delphi-Quellcode:
procedure TForm1.Server1Read(Sender:TObject;Socket:TCustomWinSocket);
begin
Memo2.Text:=Memo2.Text+Socket.ReceiveText;
end;
fertig :D :D :D
funktioniert wunderbar

man kann ja end EOF zeichen vereinbaren oder direkt danach die verbindung trennen
und dann per ondisconnect die datei schreiben :)

jokerfacehro 9. Feb 2007 08:17

Re: wie versende ich mit tclient/serversocket eine datei?
 
Zitat:

wie groß dürfen die packerln maximal sein?
ich hab grad einfach mal die textlänge von einem teil ausgelesen und
die maximale länge ist 2^13 = 8192 zeichen ;)
das sind genau 8KByte

Muetze1 9. Feb 2007 14:13

Re: wie versende ich mit tclient/serversocket eine datei?
 
Das ist unterschiedlich und hängt von vielen Dingen ab. Dies stellt den Puffer der WinSockets dar und kann frei festgelegt werden. Grundlegend habt ihr mit dem Rückgabewert der SendBuf() Funktion die Möglichkeit dies ordentlich ohne Wissen über die Größe des Puffers zu implementieren. Daher ist die Frage nach der Größe des Puffers unerheblich.

jokerfacehro 10. Feb 2007 15:59

Re: wie versende ich mit tclient/serversocket eine datei?
 
Zitat:

so und jetz müssen wir das ganze nur noch am server empfangen Smile
macht das mit ner stringlist oder etwas anderes aber nicht mit nem memo ;)
ich hab mit ner stringlist gerade 60mbyte erfolgreich versendet
mit ner memo geht nicht ma 1mb :D

Arnulf 11. Feb 2007 11:10

Re: wie versende ich mit tclient/serversocket eine datei?
 
Zitat:

fertig Very Happy Very Happy Very Happy
funktioniert wunderbar
ja aber wie du siehst wollte ich das versenden etwas genauer steuern.
ich wollte genau wissen wieviel wann versendet wurde und wie schnell das geht ( auch ca. die bandbreite festlegen ).
das geht mit sendstream nicht - ausserdem hab ich brav wie ich bin den stream immer frei gegeben und das macht wie ich
nun weis die sendstream methode selbst schon.

sendbuf ist die methode der wahl wenn man genaue kontrolle braucht.

Arnulf

jokerfacehro 11. Feb 2007 12:48

Re: wie versende ich mit tclient/serversocket eine datei?
 
Zitat:

sendbuf ist die methode der wahl wenn man genaue kontrolle braucht.
^^
bei sendstream brauchst du doch nur wenn der server was empfängt,
die größe des gesamten textes dem client zurückschicken ;)

außerdem könnte man dazu noch den timestamp und die pakcetgröße schicken und
hätte denn exakte daten für die bandbreite ;)

wär schön wenn du deine funktion mal postest :)

Arnulf 11. Feb 2007 20:00

Re: wie versende ich mit tclient/serversocket eine datei?
 
wenn ich zeit hab eine zu schreiben mach ich das :).
nein - sollte kein problem sein - ich kümmere mich aber vorher erstmal um das protokoll meines streaming clients.
vorher hat es nicht viel sinn die streams zu kontrollieren.

Zitat:

bei sendstream brauchst du doch nur wenn der server was empfängt,
die größe des gesamten textes dem client zurückschicken Wink

außerdem könnte man dazu noch den timestamp und die pakcetgröße schicken und
hätte denn exakte daten für die bandbreite Wink
darum geht es nicht wirklich.
wenn ich eine statistik machen wollte könnte man das so machen.

die funktion die ich bereits gepostet hab hat ja schon die benutzte bandbreite kontrolliert.
je nach packetgröße bzw. sleep wird hald schneller oder langsamer verschickt.
das hab ich gebraucht, weil ich von einem spiel aus screenshots übers netz verschickt hab und den spieler
wärend des spiels nicht stören wollet ( sonst lagts im game ).

was ich jetzt machen will ist genaue kontrolle über den stream haben weil ich an einen streaming client ( pinnacle showcenter ) videos streamen will.
Dabei will ich live tv von der tv karte grabben und als stream rauf schicken.
wenn ich jetzt den sender umschalte möchte ich nahtlos und möglichst schnell den stream wechseln können.
das bedeutet ich muß möglichst wenig im puffer haben ( ein paar mb sind bei einem film nicht ausschlaggebend ) und möglichst nahtlos den neuen sender übertragen.

wenn ich das nicht mache muß jedes mal wenn ich den sender wechsle der stream vom client neu initalisiert werden und das würde ein paar sekunden dauern - das ist nicht wirklich schön wenn man wie ich die fernbediehnung ständig in der hand hat und umschalten will.
Timeshifting und pause usw. sollen auch realisiert werden.
Deshalb werd ich wohl nichts anderes nehmen könnne als sendbuf und eben genau abfragen wieviel noch im puffer ist bzw. ich nachladen muß.

sobald ich das protokoll des showcenters entschlüsselt hab werd ich mich wieder um die streams kümmern und gerne auch den code posten ...

lg
Arnulf


Alle Zeitangaben in WEZ +1. Es ist jetzt 00:02 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz