| Autor |
Beitrag |
Robii
      
Beiträge: 236
|
Verfasst: Mo 22.03.10 20:31
Guten Abend
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:
| procedure TfClient.Auswerten(var Text: string); var hBitmap: TBitmap; sBmp: TStream; begin hBitmap := TBitmap.Create; sBmp := TStream.Create; try CreateScreenshot(hBitmap); Image1.Picture.Assign(hBitmap); Image1.Picture.Bitmap.SaveToStream(sBmp); Client.Socket.SendStream(sBmp); finally hBitmap.Free; sBmp.Free; End; End;
procedure TfClient.CreateScreenshot(var Bitmap: TBitmap); var dc: THandle; begin If Assigned(Bitmap) Then Begin dc := GetDC(0); Try With Bitmap do Begin Width := Screen.Width; Height:= Screen.Height; BitBlt(Canvas.Handle,0,0,Screen.Width,Screen.Height,dc,0,0,SrcCopy); End; Finally ReleaseDC(0, dc); End; End; End; |
Das ist der Code mit dem ich einen Screenshot erstellen und ihn dann an meinen Server verschicken möchte. Allerdings
kommt beim Aufruf von der Funktion immer ein 'Abstrakter Fehler'. Wieso das?
Lieben Gruß,
Robii.
Moderiert von Gausi: Code- durch Delphi-Tags ersetzt
Moderiert von Gausi: Topic aus Internet / Netzwerk verschoben am Mo 22.03.2010 um 19:52
Moderiert von Narses: Topic aus Delphi Language (Object-Pascal) / CLX verschoben am Mo 22.03.2010 um 22:57
Moderiert von Gausi: Ja, so wie sich das Thema entwickelt, ist es hier doch besser aufgehoben.
Moderiert von Narses: Der Code implizierte das schon auf den ersten Blick... 
|
|
Gausi
      
Beiträge: 8554
Erhaltene Danke: 480
Windows 7, Windows 10
D7 PE, Delphi XE3 Prof, Delphi 10.3 CE
|
Verfasst: Mo 22.03.10 20:40
TStream ist eine abstrakte Klasse, die man so nicht instantiieren darf. Also statt
sBmp := TStream.Create; besser sBmp := TMemoryStream.Create;. Die Deklaration von sBmp kannst du bei TStream belassen.
_________________ We are, we were and will not be.
|
|
Robii 
      
Beiträge: 236
|
Verfasst: Mo 22.03.10 21:09
Danke für die schnelle Hilfe. Der gesamte Code sieht jetzt so aus:
Verschicken im Client:
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:
| procedure TfClient.Auswerten(var Text: string); var hBitmap: TBitmap; sBmp: TMemoryStream; begin If Pos('SCREEN#',Text)>0 Then Begin hBitmap := TBitmap.Create; sBmp := TMemoryStream.Create; Try CreateScreenshot(hBitmap); Image1.Picture.Assign(hBitmap); Image1.Picture.Bitmap.SaveToStream(sBmp); Client.Socket.SendStream(sBmp); Finally hBitmap.Free; sBmp.Free; End; ShowMessage('LÄUFT'); End End;
procedure TfClient.CreateScreenshot(var Bitmap: TBitmap); var dc: THandle; begin If Assigned(Bitmap) Then Begin dc := GetDC(0); Try With Bitmap do Begin Width := Screen.Width; Height:= Screen.Height; BitBlt(Canvas.Handle,0,0,Screen.Width,Screen.Height,dc,0,0,SrcCopy); End; Finally ReleaseDC(0, dc); End; End; End; |
Empfangen im Server:
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:
| procedure TForm1.ServerClientRead(Sender: TObject; Socket: TCustomWinSocket); var Stream: TStream; Text: String; Size: Integer; bStream: Boolean; begin If bStream=False Then Begin Text := Socket.ReceiveText; If Pos('STREAM#',Text)>0 Then Begin Delete(Text,1,7); Size:=StrToInt(Copy(Text,1,Length(Text)-1)); bStream:=True; End; End Else Begin If SizeOf(STREAM)<Size Then Begin Socket.ReceiveBuf(Stream,Size); End Else Begin ShowMessage('KOMPLETT'); End; End; end; |
Allerdings funktioniert das nicht so, wie ich mir das vorstelle. Wieso nicht?
Wie lade ich den Stream dann wieder in ein Image?
Lieben Gruß & Danke schonmal für die Hilfe.
Robii
Moderiert von Narses: Code- durch Delphi-Tags ersetzt
|
|
ALF
      
Beiträge: 1085
Erhaltene Danke: 53
WinXP, Win7, Win10
Delphi 7 Enterprise, XE
|
Verfasst: Mo 22.03.10 21:22
Hi, was hällst Du von
Delphi-Quelltext 1:
| Image1.Picture.Bitmap.LoadFromStream(Stream); |
Glaube so müsste es gehen. Und dann ebend noch speichern.
Gruss ALf
_________________ Wenn jeder alles kann oder wüsste und keiner hätt' ne Frage mehr, omg, währe dieses Forum leer!
|
|
Robii 
      
Beiträge: 236
|
Verfasst: Mo 22.03.10 21:54
So, danke ALF ich hab das mal versucht. Mein Code sieht jetzt so aus:
CLIENT:
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:
| procedure TfClient.Auswerten(var Text: string); var hBitmap: TBitmap; sBmp: TMemoryStream; begin If Pos('SCREEN#',Text)>0 Then Begin hBitmap := TBitmap.Create; sBmp := TMemoryStream.Create; Try CreateScreenshot(hBitmap); Image1.Picture.Assign(hBitmap); Image1.Picture.Bitmap.SaveToStream(sBmp); Client.Socket.SendText('STREAM#'+IntToStr(SizeOf(sBmp))+'#'); Client.Socket.SendStream(sBmp); Finally hBitmap.Free; sBmp.Free; End; ShowMessage('LÄIFT'); End; End;
procedure TfClient.CreateScreenshot(var Bitmap: TBitmap); var dc: THandle; begin If Assigned(Bitmap) Then Begin dc := GetDC(0); Try With Bitmap do Begin Width := Screen.Width; Height:= Screen.Height; BitBlt(Canvas.Handle,0,0,Screen.Width,Screen.Height,dc,0,0,SrcCopy); End; Finally ReleaseDC(0, dc); End; End; End; |
SERVER:
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:
| procedure TForm1.ServerClientRead(Sender: TObject; Socket: TCustomWinSocket); var Stream: TStream; Text: String; Size: Integer; begin
Stream := TMemoryStream.Create; If bStream=False Then Begin SHOWMESSAGE('INCOMING'); Text := Socket.ReceiveText; If Pos('STREAM#',Text)>0 Then Begin Delete(Text,1,7); Size:=StrToInt(Copy(Text,1,Length(Text)-1)); bStream:=True; End; End Else Begin If SizeOf(STREAM)<Size Then Begin Socket.ReceiveBuf(Stream,Size); End Else Begin Image1.Picture.Bitmap.LoadFromStream(Stream); End; End; end; |
Allerdings klappt das nicht. Ich bekomme eine Zugriffsverletzung im Server und SHOWMESSAGE('INCOMING') wird auch nicht angezeigt. bStream wird beim Form.Create auf False gesetzt. Bitte helft mir nocheinmal.
Lieben Gruß.
Moderiert von Narses: Code- durch Delphi-Tags ersetzt
|
|
ALF
      
Beiträge: 1085
Erhaltene Danke: 53
WinXP, Win7, Win10
Delphi 7 Enterprise, XE
|
Verfasst: Mo 22.03.10 22:09
Robii
| Zitat: | | Ich bekomme eine Zugriffsverletzung im Server |
Fehlermeldung währe nicht schlecht!
Wenn Du die Meldung 'INCOMING' nicht sehen kannst, kann es ja sein:
1. bstream ist vielleicht nicht bekannt in der Procedure.
2. evtl wird vorher schon abgebrochen (Zugriffsverletzung)
Es währe also nur ein Raten!
Kam den vor der Änderung ne Fehlermeldung!?
Noch was, wenn der Client funct brauchst Du nicht immer den Quelltext mit Posten!
und sei so nett und korregiere mal diese schreibweisen:
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:
| If bStream=False Then Begin
If bStream then begin ...... end;
If SizeOf(STREAM)<Size Then Begin Socket.ReceiveBuf(Stream,Size); End Else Begin Image1.Picture.Bitmap.LoadFromStream(Stream); End;
If SizeOf(STREAM) < Size then Socket.ReceiveBuf(Stream, Size) else Image1.Picture.Bitmap.LoadFromStream(Stream);
|
sieht besser aus und ist lesbarer!
Gruss ALf
_________________ Wenn jeder alles kann oder wüsste und keiner hätt' ne Frage mehr, omg, währe dieses Forum leer!
|
|
Robii 
      
Beiträge: 236
|
Verfasst: Mo 22.03.10 23:16
Also. Der Screenshot wird im Client jetzt erstellt. Allerdings bekomme ich als Fehlermeldung im Client folgendes:
Ungültige Zeigeroperation!
Hier der Code des Clienten:
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:
| var fClient: TfClient;
implementation
{$R *.dfm} procedure TfClient.Auswerten(var Text: string); var hBitmap: TBitmap; sBmp: TMemoryStream; begin If Pos('SCREEN#',Text)>0 Then Begin hBitmap := TBitmap.Create; sBmp := TMemoryStream.Create; Try CreateScreenshot(hBitmap); Image1.Picture.Assign(hBitmap); Image1.Picture.Bitmap.SaveToStream(sBmp); Client.Socket.SendText('STREAM#'+IntToStr(SizeOf(sBmp))+'#'); Client.Socket.SendStream(sBmp); Finally hBitmap.Free; sBmp.Free; End; ShowMessage('LÄIFT'); End; End;
procedure TfClient.CreateScreenshot(var Bitmap: TBitmap); var dc: THandle; begin If Assigned(Bitmap) Then Begin dc := GetDC(0); Try With Bitmap do Begin Width := Screen.Width; Height:= Screen.Height; BitBlt(Canvas.Handle,0,0,Screen.Width,Screen.Height,dc,0,0,SrcCopy); End; Finally ReleaseDC(0, dc); End; End; End;
procedure TfClient.FormCreate(Sender: TObject); begin Client.Port:=TARGET_PORT; Client.Address:='XX.XX.XXX.XXX'; Client.Active:=True; end;
procedure TfClient.ClientRead(Sender: TObject; Socket: TCustomWinSocket); var sText: String; begin sText:=Socket.ReceiveText; If Pos('#',sText)=Length(sText) Then Auswerten(sText); End; |
Im Server kommt das PopUp 'INCOMING' und als größe des Streams wird mir nur '4' angezeigt. Kann das sein? Auch der Screen wird im Image nicht angezeigt.
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:
| var Form1: TForm1; bStream: Boolean;
implementation
{$R *.dfm}
procedure TForm1.Button1Click(Sender: TObject); var i: integer; begin For i := 0 to Server.Socket.ActiveConnections-1 do Begin Server.Socket.Connections[i].SendText(Edit1.Text+'#'); End; Log.Lines.Add(Edit1.Text+'#'); end;
procedure TForm1.FormCreate(Sender: TObject); begin bStream:=False; end;
procedure TForm1.ServerClientConnect(Sender: TObject; Socket: TCustomWinSocket); begin Log.Lines.Add('Neuer Client'); end;
procedure TForm1.ServerClientRead(Sender: TObject; Socket: TCustomWinSocket); var Stream: TStream; Text: String; Size: Integer; begin Log.Lines.Add(Socket.ReceiveText); Stream := TMemoryStream.Create; If bStream=False Then Begin SHOWMESSAGE('INCOMING'); Text := Socket.ReceiveText; If Pos('STREAM#',Text)>0 Then Begin Delete(Text,1,7); Size:=StrToInt(Copy(Text,1,Length(Text)-1)); bStream:=True; End; End Else Begin If SizeOf(STREAM)<Size Then Begin Socket.ReceiveBuf(Stream,Size); End Else Begin Image1.Picture.Bitmap.LoadFromStream(Stream); End; End; end; |
Sorry Alf, was meinst du mit ich soll die Schreibweise korregieren?
Das mit dem {in} hab ich nicht verstanden.
Lieben Gruß und Danke für die Hilfe.
Robii
|
|
Muck
      
Beiträge: 98
Erhaltene Danke: 8
Win 8, Win 7, Vista, Win XP
Delphi XE3, Delphi 2009, Delphi 2007, Delphi 5
|
Verfasst: Mo 22.03.10 23:31
Hallo,
Problem 1 siehe Anmerkung
Delphi-Quelltext 1: 2:
| Client.Socket.SendText('STREAM#'+IntToStr(SizeOf(sBmp))+'#'); |
Problem 2
Du kannst nicht sicher sein, dass Dein BMP in einem Rutsch empfangen wird. Du musst also die ReceiveBuf Procedure auf einen existierenden Stream anwenden bis SIZE erreicht ist. Also wenn Du im Server den Text STREAM# findest einen Stream anlegen, jedoch nicht local, den musst Du anders speichern z.B. ein Object und Socket.Data als Pointer nutzen damit Du wenn der naechste Datenblock eintrifft, den Stream und andere Daten auch wiederfindest.
Besser jedoch ein Protokoll benutzen, da gibt es schon viele Beispiele hier im Forum, denn streng genommen kannst Du Dir ja noch nicht einmal sicher sein, dass der String "STREAM#145554#" in einem Stueck am anderen Ende ankommt. Dieser kann ja auch in 2 Aufrufen als "STRE" und "AM#145554#" ankommen.
Markus
Zuletzt bearbeitet von Muck am Mo 22.03.10 23:50, insgesamt 1-mal bearbeitet
|
|
ALF
      
Beiträge: 1085
Erhaltene Danke: 53
WinXP, Win7, Win10
Delphi 7 Enterprise, XE
|
Verfasst: Mo 22.03.10 23:42
Ich meine, schreibe die if Anweisungen so, das man sie auch richtig lesen kann!
also z.B.:
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12:
| If Pos('SCREEN#', Text) > 0 Then Begin hBitmap := TBitmap.Create; sBmp := TMemoryStream.Create; Try CreateScreenshot(hBitmap); ..... ..... Finally hBitmap.Free; sBmp.Free; end; |
und richtiges einrücken. So sieht man wo der Anfang ist und das Ende und muss nicht erst suchen im Quelltext!
Das meinte ich auch mit diesem {in} "richtige Schreibweise".
Felermeldungen liefern meist auch ne Zeilennummer, evtl wird die Stelle auch markiert!
Wenn vorher alles gefunct hatt, ausser das im Server, wieso tauchen jetzt Fehler im Clienten auf????
bisschen merkwürdig
Gruss ALf
_________________ Wenn jeder alles kann oder wüsste und keiner hätt' ne Frage mehr, omg, währe dieses Forum leer!
|
|
Robii 
      
Beiträge: 236
|
Verfasst: Mo 22.03.10 23:44
Muck hat folgendes geschrieben : | Hallo,
Problem 2
Du kannst nicht sicher sein, dass Dein BMP in einem Rutsch empfangen wird. Du musst also die ReceiveBuf auf einen existierenden Stream anwenden bis SIZE erreicht ist. Also wenn Du im Server den Text STREAM# findest ein Stream anlegen, jedoch nicht local, musst Du anders speichern und Socket.Data als Pointer nutzen damit Du wenn der naechste Datenblock eintrifft, den Stream und andere Daten auch wiederfindest.
Besser jedoch ein Protokoll benutzen, da gibt es schon viele Beispiele hier im Forum.
Markus |
Hey Markus, danke für deine Hilfe erstmal. Das mit dem Protokoll hab ich beim Suchen schon oft gelesen, allerdings glaube ich ist das doch eher für große Programme geeignet, mit vielen Funktionen oder? Ich möchte lediglich Screens verschicken können.
E:/
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10:
| procedure TForm1.FormCreate(Sender: TObject); begin bStream:=False; Stream := TMemoryStream.Create; Server.Socket.Data := @stream; end;
[..]
Socket.ReceiveBuf(Socket.Data,Size); |
Wobei Stream: TStream global definiert ist?
Fehlermeldung:
[DCC Fehler] Unit1.pas(7 : E2197 Konstantenobjekt kann nicht als Var-Parameter weitergegeben werden
Lieben Gruß & Danke.
Robii
|
|
Narses
      

Beiträge: 10184
Erhaltene Danke: 1259
W11x64
TP3 .. D7pro .. D10.2CE
|
Verfasst: Mo 22.03.10 23:56
Moin!
Robii hat folgendes geschrieben : | Muck hat folgendes geschrieben : | | Besser jedoch ein Protokoll benutzen | Das mit dem Protokoll hab ich beim Suchen schon oft gelesen, allerdings glaube ich ist das doch eher für große Programme geeignet, mit vielen Funktionen oder? Ich möchte lediglich Screens verschicken können. |
Da hat er einfach recht, die einzig brauchbare Lösung ist ein Protokoll, egal wie "groß" dein Programm ist. Auch wenn dein Programm "nur" ein Bild versenden/empfangen soll, das soll es doch aber wohl fehlerfrei tun können, oder?
Was du da machst, wird nie richtig funktionieren, weil du keine brauchbare Verarbeitung der eingehenden Daten hast. Standard-FAQs:
www.delphi-library.d...derhalten_56194.html
www.delphi-library.d...+Objekten_60793.html
www.delphi-library.d...n+Sockets_65367.html
Und ich schätze mal, es soll nachher sowas dabei rauskommen, oder?
cu
Narses
_________________ There are 10 types of people - those who understand binary and those who don´t.
|
|
Robii 
      
Beiträge: 236
|
Verfasst: Di 23.03.10 00:10
Hallo Narses, irgendwie wußte ich das du dich hier zu Wort melden wirst, da du ja quasi der 'Fachmann' in diesem Bereich bist. Dein Tutorial habe ich mir schon runtergeladen usw. und angeguckt, allerdings, erschien mir das immer als recht umfangreich und die Code-Schnipsel die man für das versenden von Bildern benötigt, habe ich nicht herraussuchen können. Ich muss zugeben ich habe mich mit deinem Tutorial nicht 100%ig beschäftigt, aber ich dachte, das es vielleicht für das blosse versenden eines Bildes auf Knopf-Druck eine einfachere Lösung gibt
Vielleicht kannst du dir ja den Code den ich bis jetzt gepostet habe nochmal anschauen, ich schaue mir dein Tutorial mal intensiv an.
Lieben Gruß.
Robii
|
|
Muck
      
Beiträge: 98
Erhaltene Danke: 8
Win 8, Win 7, Vista, Win XP
Delphi XE3, Delphi 2009, Delphi 2007, Delphi 5
|
Verfasst: Di 23.03.10 01:05
Hi,
Socket.Data benutze ich in meinen Server Programmen um einen Pointer auf Variablen fuer diese Session zu haben. Erzeuge Dir dafuer eine Klasse oder Object wo der Stream oder AnsiString oder was immer Du nutzen willst ein Member ist. Im Connect Ergeignis des Socket erzeugst Du diese Struktur mit Create und speicherst dort in Socket.Data einen Pointer auf das Object. Im Read Ereignis kannst Du dann mit Socket.Data einen Pointer auf dieses Object bilden und die ankommenden Daten zum Buffer addieren. Im Disconnect kannst Du das Object freigeben.
Falls Du jedoch sicher weisst, dass niemals mehr als ein Client mit dem Server verbunden ist, kannst Du Dir das alles sparen und einfach mit einem Public Stream arbeiten, ist aber nicht ganz fein.
|
|
Robii 
      
Beiträge: 236
|
Verfasst: Di 23.03.10 01:20
Habe mir jetzt den ersten Teil des Protokoll-Tutorials von Narses durchgelesen und mir ist so Einiges klar geworden. Versuche das beim schlafen jetzt mal zu verarbeiten und zeige euch dann morgen was ich geschafft habe, in diesem Sinne eine gute Nacht.
Grüße, Robii.
|
|
Robii 
      
Beiträge: 236
|
Verfasst: Di 23.03.10 23:34
Guten Abend, ich bin es noch einmal.
Also ich hab jetzt folgendes versucht:
Client
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:
| const SERVER_PORT = XXXX; SERVER_ADDR = 'XX.XX.XXX.XXX'; cmdSCR = 'SCREEN';
[..]
var Form1: TForm1;
implementation
{$R *.dfm} procedure TForm1.Auswerten; var Data: TStringList; hBitmap: TBitmap; ImgData: TStringStream; begin Data := TStringList.Create; hBitmap := TBitMap.Create; ImgData := TStringStream.Create; try Data.Text := ReceiveBuffer; If Data.Strings[0]= cmdSCR Then Begin CreateScreenshot(hBitmap); Image1.Picture.Assign(hBitmap); ImgData := TStringStream.Create(''); Image1.Picture.Bitmap.SaveToStream(ImgData); Client.Socket.SendText(cmdSCR+#13+ImgData.DataString+#13); End; finally ImgData.Free; Data.Free; hBitmap.Free; end; end;
procedure TForm1.CreateScreenshot(var Bitmap: TBitmap); var dc: THandle; begin If Assigned(Bitmap) then begin dc := GetDC(0); try with Bitmap do begin Width := Screen.Width; Height:= Screen.Height; BitBlt(Canvas.Handle,0,0,Screen.Width,Screen.Height,dc,0,0,SrcCopy); end; finally ReleaseDC(0, dc); end; end; end;
procedure TForm1.FormCreate(Sender: TObject); begin Client.Port := SERVER_PORT; Client.Address:= SERVER_ADDR; Client.Open; end;
procedure TForm1.ClientRead(Sender: TObject; Socket: TCustomWinSocket); begin ReceiveBuffer := ReceiveBuffer + Socket.ReceiveText; Auswerten; end; end. |
Server:
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:
| const SERVER_PORT = 6112; cmdSCR = 'SCREEN';
[..]
implementation
{$R *.dfm}
procedure TForm1.Auswerten; var Data: TStringList; hBitmap: TBitmap; ImgData: TStringStream; begin Data := TStringList.Create; hBitmap := TBitMap.Create; ImgData := TStringStream.Create; try Data.Text := ReceiveBuffer; If Data.Strings[0]= cmdSCR Then Begin ImgData := TStringStream.Create(Data.Strings[1]); ShowMessage('Lade von Stream'); Image1.Picture.Bitmap.LoadFromStream(ImgData); End; finally ImgData.Free; Data.Free; hBitmap.Free; end; end;
procedure TForm1.btScrClick(Sender: TObject); var i: Integer; begin for i := 0 to Server.Socket.ActiveConnections - 1 do Server.Socket.Connections[i].SendText(cmdSCR+#13); end;
procedure TForm1.FormCreate(Sender: TObject); begin Server.Port := SERVER_PORT; Server.Open; end;
procedure TForm1.ServerClientConnect(Sender: TObject; Socket: TCustomWinSocket); begin ShowMessage('Client Connected'); end;
procedure TForm1.ServerClientRead(Sender: TObject; Socket: TCustomWinSocket); begin ReceiveBuffer := ReceiveBuffer + Socket.ReceiveText; Auswerten; end;
end. |
Wenn ich jetzt im Server den Screen-Knopf drücke, wird im Client ein Screen erzeugt und anscheinend auch verschickt, allerdings hängt sich der Server dann auf. Eine Endlos-Schleife oder so etwas in der Richtung, denn es reagiert nicht mehr und zeigt als Cursor die ganze Zeit den 'ARBEITEN'-Cursor.
Narses ich hab mir dein Tutorial durchgelesen, aber irgendwie finde ich, das das zuviel ist. Ich möchte ja nur ein Programm haben, das ein Screen auf Knopf-Druck verschickt.
Was ich in deinem Tutorial nicht verstehe, du sagst, das man den STREAM des Bildes ja bearbeiten muss, damit die Trennzeichen '#13' die wir normalerweise benutzen um das Ende eines Pakets zu makieren ersetzen müssen. Dazu verwendest du folgende Funktion:
Delphi-Quelltext 1: 2:
| function MaskTermChar(const S: String; const TermChar: Char = #13): String; function UnmaskTermChar(const S: String; const TermChar: Char = #13): String; |
Allerdings wird im gesamten Tutorial nicht der Inhalt der Funktionen erläutert, oder ich hab da etwas falsch verstanden. Kann mir auch gut vorstellen, das deshalb mein Gerüst (s.o.) nicht funktioniert.
Hoffe, ihr könnt mir helfen.
Lieben Gruß & Danke schonmal,
Robii.
|
|
Narses
      

Beiträge: 10184
Erhaltene Danke: 1259
W11x64
TP3 .. D7pro .. D10.2CE
|
Verfasst: Mi 24.03.10 00:10
Moin!
Robii hat folgendes geschrieben : | | Also ich hab jetzt folgendes versucht: |
Dein Code zeigt leider, dass du das Tutorial nicht verstanden hast, vermutlich weil es dir zuviel Arbeit ist, das mal ordentlich durchzuarbeiten, warum auch immer, dabei kann ich dir nicht helfen.
Da sind min. folgende, gravierende Fehler drin: - Du verwendest die TStringList, um die Pakete zu trennen, das wird aber bei hoher Datenrate (wie bei Bildern zu erwarten) zu dem im Tutorial angesprochenen Fehler führen, dass dir das letzte Datenpaket kaputt geht. Du brauchst hier die TParserStringList aus dem TermCharTut Teil 2.
- Du maskierst das Terminator-Zeichen nicht, also wird dein Bild-Paket ziemlich sicher kaputt gehen (das hast du ja bereits selbst erkannt).
- Im Server hast du offensichtlich nur einen gloablen Buffer für alle Clients, das gibt ganz sicher Datensalat.
Robii hat folgendes geschrieben : | | Narses ich hab mir dein Tutorial durchgelesen, aber irgendwie finde ich, das das zuviel ist. |
Was soll ich dazu sagen, ich habe mir doch nicht die Anforderung ausgedacht, die du da umsetzen willst.  Ich zeige im Tut lediglich, wie man das lösen kann. Du kannst es gerne anders machen, wenn du möchtest.
Robii hat folgendes geschrieben : | | Ich möchte ja nur ein Programm haben, das ein Screen auf Knopf-Druck verschickt. |
Und das scheint wohl nicht ganz so einfach zu sein, wie du mittlerweile selbst festgestellt haben müsstest...
Aber vielleicht solltest du dir mal diese Komponenten ansehen, damit ist das deutlich leicher umzusetzen.
Robii hat folgendes geschrieben : | Was ich in deinem Tutorial nicht verstehe, du sagst, das man den STREAM des Bildes ja bearbeiten muss, damit die Trennzeichen '#13' die wir normalerweise benutzen um das Ende eines Pakets zu makieren ersetzen müssen. Dazu verwendest du folgende Funktion:
Delphi-Quelltext 1: 2:
| function MaskTermChar(const S: String; const TermChar: Char = #13): String; function UnmaskTermChar(const S: String; const TermChar: Char = #13): String; |
Allerdings wird im gesamten Tutorial nicht der Inhalt der Funktionen erläutert, |
Ja, das ist richtig, die Funktionen liegen allerdings mit ausführlichen Kommentaren im Code-Archiv mit bei. Also einfach mal reinschauen, so schwer sind die nicht zu verstehen. Es ging mir im Tut zu weit, das auch noch im Detail auszuwalzen; vor allem, weil hier ein Binärprotokoll eh der bessere Ansatz ist.
cu
Narses
_________________ There are 10 types of people - those who understand binary and those who don´t.
|
|
Martok
      
Beiträge: 3661
Erhaltene Danke: 604
Win 8.1, Win 10 x64
Pascal: Lazarus Snapshot, Delphi 7,2007; PHP, JS: WebStorm
|
Verfasst: Mi 24.03.10 12:55
Wollt ihr dem armen Jungen nicht sagen, dass Indy auch HTTPServer etc mitbringt?
Gut, ich würde jetzt immer ICS vorziehen...
Da hätte man ein fertiges Protokoll und ganz brauchbare Handler, und du kannst einfach eine Abfrage bauen
Pseudocode 1: 2:
| WENN Anfrage.URL = "/screen.bmp" DANN Antwort.Stream:= Bitmap.AlsStream |
KISS... in dem Fall "don't write a protocol if you don't have to".
_________________ "The phoenix's price isn't inevitable. It's not part of some deep balance built into the universe. It's just the parts of the game where you haven't figured out yet how to cheat."
|
|
Narses
      

Beiträge: 10184
Erhaltene Danke: 1259
W11x64
TP3 .. D7pro .. D10.2CE
|
Verfasst: Mi 24.03.10 13:01
Moin!
Martok hat folgendes geschrieben : | | Wollt ihr dem armen Jungen nicht sagen, dass Indy auch HTTPServer etc mitbringt? |
Wenn du glaubst, dass er mit den Threads besser klar kommt...  (ist nicht persönlich gemeint  )
Klar kann man das machen, aber wer sagt, dass es wirklich "nur" ein Bild ist? Wenn das erstmal klappt, dann kommt noch hier was, und das könnte man auch noch...
Abgesehen davon bin ich der Meinung, dass man erstmal selbst ein Protokoll verstanden haben sollte, bevor man sich mit Protokoll-Standards rumschlägt, die man dann nicht korrekt anwendet...
cu
Narses
_________________ There are 10 types of people - those who understand binary and those who don´t.
|
|
Martok
      
Beiträge: 3661
Erhaltene Danke: 604
Win 8.1, Win 10 x64
Pascal: Lazarus Snapshot, Delphi 7,2007; PHP, JS: WebStorm
|
Verfasst: Mi 24.03.10 13:09
Narses hat folgendes geschrieben : | Wenn du glaubst, dass er mit den Threads besser klar kommt... (ist nicht persönlich gemeint ) |
(Auch) deswegen auch mein Hinweis auf ICS, die sind eventbasiert. Muss man allerdings noch mehr aufpassen, weil man ja die Verbindungen dann auseinanderhalten muss irgendwie.
Narses hat folgendes geschrieben : | | Klar kann man das machen, aber wer sagt, dass es wirklich "nur" ein Bild ist? |
Ja gut... ich antworte nur auf Fragen die auch da sind... das ist dann wohl doch "Kundenerfahrung", dass hinterher immer noch mehr kommt als das bestelle "kleine Tool"
Narses hat folgendes geschrieben : | Abgesehen davon bin ich der Meinung, dass man erstmal selbst ein Protokoll verstanden haben sollte, bevor man sich mit Protokoll-Standards rumschlägt, die man dann nicht korrekt anwendet...  |
Okay, das ist allerdings wahr. Man sollte zumindest grob wissen, was da warum passiert... und was nicht.
Und dazu sind deine Tutorials sicherlich gut geeignet, auch wenn ich das Terminatorzeichent. nur mal überflogen hab, sondern gleich Binär eingestiegen bin...
_________________ "The phoenix's price isn't inevitable. It's not part of some deep balance built into the universe. It's just the parts of the game where you haven't figured out yet how to cheat."
|
|
Robii 
      
Beiträge: 236
|
Verfasst: Mi 24.03.10 15:32
Guten Mittag zusammen,
@ Narses
Ich hab jetzt die beiden Units für TParserStringList & die Unit für das maskieren von Terminator-Zeichen eingebunden und verwende diese auch.
Ich wollte auf ein Protkoll verzichten, da ich ja im Prinzip nur auf Knopf-Druck vom Server aus den Befehl 'SCREEN' schicken möchte und dann der Client einen Screen zurück senden.
Es gibt sonst keine anderen Funktionen und es ist auch immer nur 1 Client mit dem Server verbunden [ -> globaler Buffer].
Wenn ich jetzt meinen SCREEN-Befehl abschicke, wird im Client ein Screen erzeugt und versendet. Doch der Server reagiert dann nicht mehr. Es kommt aber auch keine Fehlermeldung, scheint mir so, als würde da irgendeine Schleife laufen oder sowas.
Im Prinzip muss das Programm doch so ablaufen:
SERVER -> Befehl: Mach einen Screen
CLIENT -> Erzeugt Screen
CLIENT -> Speichert den Screen in einem String und verschickt diesen
SERVER -> Empfängt Stream und speichert diesen in einem Bild
Vielleicht könnt ihr mir da nochmal helfen?
@Martok
Ich würde gerne bei TClientSocket & TServerSocket bleiben, da weiß ich immerhin was ich machen muss usw.
Danke trotzdem.
Lieben Gruß.
|
|
|