Entwickler-Ecke
Internet / Netzwerk - [TWinSocket] Stream von mit ClientSocket empfangen
Jakob Schöttl - Do 07.09.06 13:43
Titel: [TWinSocket] Stream von mit ClientSocket empfangen
Hallo,
ich mach grad ein programm, das Dateien über eine Socketverbindung schicken soll.
Genauer gesagt:
Delphi-Quelltext
1: 2:
| Image1.Picture.Bitmap.SaveToStream(WinSocketStream); ServerSocket1.Socket.SendStream(WinSocketStream); |
Jetzt soll natürlich ClientSocket1 den Stream empfangen, bloß ich finde nicht die richtige Methode!
Für SendText -> ReceiveText
Für SendBuf -> ReceiveBuf
Für SendStream -> ?
Hoffentlich könnt ihr mir helfen!
Danke schon mal
Narses - Do 07.09.06 14:29
Moin!
bokaj hat folgendes geschrieben: |
Jetzt soll natürlich ClientSocket1 den Stream empfangen, bloß ich finde nicht die richtige Methode!
Für SendText -> ReceiveText
Für SendBuf -> ReceiveBuf
Für SendStream -> ? |
Es gibt keine Stream-Empfangsmethode, weil diese ja nicht wissen kann, wie groß der Datenblock ist, der da empfangen werden soll. ;)
Beim Senden wird intern .SendStream auf wiederholte .SendBuf-Aufrufe runtergebrochen. Fazit: Du mußt die Daten mit .ReceiveBuf annehmen und selbst rausfinden, was davon zu deinem Stream gehört. :D
Daraus folgt: du brauchst ein Protokoll (wie auch immer das aussieht, ist ein anderes Problem). Ein Beispiel, wie man ein Protokoll entwickelt, findest du
hier [
http://www.delphi-library.de/topic_ProtokollChatTutorial+TServerSocketTClientSocket+v300_54269.html].
cu
Narses
PS: Den WinSocketStream brauchst du nur für blocking-socket-calls, du kannst ruhig "normale" Streams nehmen, wenn du non-blocking arbeitest. ;)
Jakob Schöttl - Do 07.09.06 16:16
Danke Narses, in Sachen Netzwerk ist auf dich immer Verlass!
In meinem Fall brauche ich (glaub ich) gar kein Protokoll, weil der Server immer eine gleichgroße bmp-Datei an den Client schickt.
Wenn aber der Server mit
SendStream den Stream schickt, dann kommt beim Client kein OnRead-Ereignis. Wie kann ich also dann
ReceivedBuf abfragen?
Liegt es vllt daran, dass beim Server steht
Delphi-Quelltext
1: 2: 3:
| ServerSocket1.Socket.SendStream(Stream); ServerSocket1.Socket.Connections[0].SendStream(Stream); |
??
Narses - Do 07.09.06 16:57
Moin!
bokaj hat folgendes geschrieben: |
| In meinem Fall brauche ich (glaub ich) gar kein Protokoll, weil der Server immer eine gleichgroße bmp-Datei an den Client schickt. |
Ob du ein Protokoll brauchst oder nicht, mußt du natürlich selbst entscheiden. Wenn du schon vorher weißt, wie groß der Stream ist, den du empfangen willst, dann geht das natürlich auch ohne. Wenn allerdings die Größe variabel ist (oder sich später mal ändert), dann wäre ein Protokoll-Ansatz sicherlich die bessere Wahl.
bokaj hat folgendes geschrieben: |
| Wenn aber der Server mit SendStream den Stream schickt, dann kommt beim Client kein OnRead-Ereignis. |
Dann machst du was falsch, es muss ein Ereignis ausgelöst werden (s.u.).
bokaj hat folgendes geschrieben: |
Liegt es vllt daran, dass beim Server steht
Delphi-Quelltext 1: 2: 3:
| ServerSocket1.Socket.SendStream(Stream); ServerSocket1.Socket.Connections[0].SendStream(Stream); |
?? |
Ja, du mußt an die Connections aus dem Array des Servers senden, da hängen die Clients dran. ;) Alternativ kannst du auch den
Socket: TCustomWinSocket-Parameter aus der Ereignisprozedur nehmen, das ist garantiert immer die Richtige Verbindung. Siehe auch
FAQ-Beitrag [
http://www.delphi-library.de/topic_die+Clients+von+TServerSocket+auseinanderhalten_47183.html].
cu
Narses
Jakob Schöttl - Do 07.09.06 17:15
Narses, vllt siehst du ja sofort, was ich falsch mache: :cry:
Beim Server:
Zuerst lese ich aus der Verbindung, und schicke gleich anschließen den Stream zurück. Beide ShowMessage tauchen auf, und ich klicke ok.
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:
| procedure TMainForm.ServerSocket1ClientRead(Sender: TObject; Socket: TCustomWinSocket); var Picture: TPicture; s: string; n: integer; begin Picture := TPicture.Create; Stream := TMemoryStream.Create; try ShowMessage('Client Read'); s := Socket.ReceiveText; if s = 'SendScreenShot' then begin MakeScreenShot(Picture.Bitmap); Picture.Bitmap.SaveToStream(Stream); ShowMessage('Stream wird verschickt'); Socket.SendStream(Stream); end; finally Picture.Free; end; end; |
Dann beim Client:
Die ShowMessage taucht nicht auf, und auch bei einem Haltepunkt bleibt er nicht stehen.
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12:
| procedure TMainForm.ClientSocket1Read(Sender: TObject; Socket: TCustomWinSocket); var Stream: TMemoryStream; begin ShowMessage('Read'); Stream := TMemoryStream.Create; try showMessage(s); finally Stream.Free; end; end; |
Narses - Do 07.09.06 17:34
Moin!
bokaj hat folgendes geschrieben: |
| Narses, vllt siehst du ja sofort, was ich falsch mache: :cry: |
Der Fehler ist vermutlich hier:
Delphi-Quelltext
1: 2: 3: 4: 5:
| Picture.Bitmap.SaveToStream(Stream); ShowMessage('Stream wird verschickt'); Stream.Position := 0; Socket.SendStream(Stream); end; |
Allerdings würde ich da noch andere Dinge ändern:
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:
| procedure TMainForm.ServerSocket1ClientRead(Sender: TObject; Socket: TCustomWinSocket); var Bitmap: TBitmap; s: string; n: integer; begin Bitmap := TBitmap.Create; Stream := TMemoryStream.Create; try ShowMessage('Client Read'); s := Socket.ReceiveText; if (s = 'SendScreenShot') then begin MakeScreenShot(Bitmap); Bitmap.SaveToStream(Stream); ShowMessage('Stream wird verschickt'); Stream.Position := 0; Socket.SendStream(Stream); end; finally Bitmap.Free; end; end; |
Wenn ich mir so den Code ansehe, dann machst du einen klassischen Fehler: du verläßt dich auf die Ereignisse als Signalisierung. Das ist allgemein ein Fehler, siehe
FAQ-Beitrag [
http://www.delphi-library.de/topic_Datenpakete+bei+den+SocketKomponenten+auseinanderhalten_56194.html]. ;)
Und da du Befehle und Daten in deiner Übertragung hast, würde ich dir hiermit GANZ DRINGEND ein Protokoll ans Herz legen. Schau mal in das Tut, im Kapitel 8 wird eine Bitmap übertragen, zusätzlich zum Chatten, das ist genau das, was du hier auch machen willst. ;) Sorry, aber die meisten Probleme laufen einfach immer wieder darauf hinaus, dass ein Protokoll die Lösung ist; nur die Problemstellung variiert leicht... :D
cu
Narses
Jakob Schöttl - Do 07.09.06 17:51
Einarbeiten muss ich mich sowieso, dann mach ichs genau, so wie dus im Tutorial empfiehlst, denn jetzt kommt zwar das Ereignis OnRead beim Client, aber auch eine Exception beim Server: ESocketError, Meldung 'Asynchroner Socket-Fehler'.
Ich dachte es kann nicht so schwer sein, eine Datei übers Netzwerk zu verschicken...
Es gibt da keinen einfachen Befehl, oder so?
Narses - Do 07.09.06 18:00
Moin!
bokaj hat folgendes geschrieben: |
Ich dachte es kann nicht so schwer sein, eine Datei übers Netzwerk zu verschicken...
Es gibt da keinen einfachen Befehl, oder so? |
Wenn ich einen kennen würde, hätte ich dann das Tut geschrieben? :mrgreen:
Aber sagen wir mal so: wenn du einen findest, sag mir bescheid! ;)
cu
Narses
Jakob Schöttl - Do 07.09.06 18:05
OK, Danke trotzdem für deine Hilfe Narses!
Ich schaff das schon :roll: - Vielleicht, wenn ich genügend nerve habe ...
Entwickler-Ecke.de based on phpBB
Copyright 2002 - 2011 by Tino Teuber, Copyright 2011 - 2026 by Christian Stelzmann Alle Rechte vorbehalten.
Alle Beiträge stammen von dritten Personen und dürfen geltendes Recht nicht verletzen.
Entwickler-Ecke und die zugehörigen Webseiten distanzieren sich ausdrücklich von Fremdinhalten jeglicher Art!