![]() |
Befehle trennen
Moin,
ich bastel an einem Tool, mitdem 2 PC's über die Sockets kommunizieren (Indy war mir irgendwie komisch mit dem Writln und Readln da :P). Einer ist der Server, der andere der Client 8-). Jetzt habe ich ein ListView im Report-Modus, wo ein Paar Infos reinkommen. Name, des Clienten (sendet der Client natürlich), IP, Benutz welcher am Remote-PC sitz, Version des Clienten und Ping. Wenn sich der Client verbindet, soll er mir alles außer seiner IP und dem Ping senden (mache ich am Server mit Socket.RemoteAdress). Dafür habe ich mir folgendes überlegt:
Delphi-Quellcode:
'remoteinfo' ist der Befehl, dass das nachfolgende alles die Infos des Remotecomputers sind. '§' ist das Ende des Befehls und '#' grenzen die einzelnen Infos voneinander ab.
procedure TfrmMain.TCPClientConnect(Sender: TObject; Socket: TCustomWinSocket);
begin Socket.SendText('remoteinfo§' + Name + '#' + ComUser + '#' + APP_VERSION); end; Name = Name des Clienten ComUser = Name des Benutzers, der am PC angemeldet ist APP_VERSION = Eine konstante mit der Versiond es Clienten Aber ich weiß nicht wie ich alles voneinander trennen soll. Ich habe zwar ![]()
Delphi-Quellcode:
Hoffe ihr könnt mir auf die Sprünge helfen ... :)
procedure TfrmMain.TCPServerClientRead(Sender: TObject;
Socket: TCustomWinSocket); begin case Socket.ReceiveText of 'Befehl': {das mit dem trennen ist aber jetzt komisch, denn der ReceiveText ist ja nicht nur der Befehl, sonder auch die Info :/ Also muss ich erst Befehl und Info trennen... Irgendwie davor...}; end; end; [EDIT]: Zumindestens weiß ich, wie ich mit Pos mein Befehlszeichen ausmachen kann... Immerhin etwas :) |
AW: Befehle trennen
Beim Empfangen musst du vorsichtig sein: Das Ereignis wird aufgerufen, sobald Text empfangen wird. Du weißt nicht, ob die komplette Nachricht schon übertragen wurde oder aber ob vielleicht zwei Nachrichten im Buffer stecken.
Das heißt - das Event kann für eine Nachricht zwei mal aufgerufen werden - das Event kann kann zwei Nachrichten enthalten Darum musst du dir einen eigenen Buffer bauen, in den der empfangene Text landet, und wenn du darin eine komplette Nachricht entdeckst kannst du die da rausholen. Hier ein Beispiel, wie ich das damals gemacht habe:
Delphi-Quellcode:
Das bedeutet aber, dass du am Ende jeder Nachricht auch ein Zeichen mitsenden musst, dass die Nachricht zu Ende ist. Dann musst du natürlich auch dafür sorgen, dass dieses Zeichen in der eigentlichen Nachricht nicht vorkommt.
const
MessageDelimitter = '%%'; procedure TMyServer.OnServerClientRead(Sender: TObject; Socket: TCustomWinSocket); var msg : string; Client: TSClient; begin msg := Socket.ReceiveText; if Assigned(fOnRead) then fOnRead(self, msg, Socket.RemoteAddress, Socket.RemotePort); Client := GetClientByID(GetID(Socket.RemoteAddress, Socket.RemotePort)); if Assigned(Client) then begin Client.ReadBuffer := Client.ReadBuffer + msg; while Pos(MessageDelimitter, Client.ReadBuffer) > 0 do begin msg := copy(Client.ReadBuffer, 1, Pos(MessageDelimitter, Client.ReadBuffer) - 1); ServerExecute(Client, msg); Delete(Client.ReadBuffer, 1, Pos(MessageDelimitter, Client.ReadBuffer) + Length(MessageDelimitter) - 1); end; end; end; Zu deinem Trenner-Problem: Du kannst mit einer TStringList den Text zerlegen.
Delphi-Quellcode:
Ich würde dir aber empfehlen, das ganze zB mit JSON zu verpacken. Dann würde das ganze so aussehen:
var
List: TStringList; begin List := TStringList.Create; List.StrictDelimitter := True; List.Delimitter := '#'; List.DelimittedText := 'Wert 1#Wert 2#Banane'; showmessage(List.Text); List.Free; end;
Code:
Dann kannst du daraus leicht Objekte machen, zB mit
{command:'remoteinfo', body:[name:'Hans', ComUser:'Hans_Workstation', APP_VERSION:123]}
![]()
Delphi-Quellcode:
Und zurück ging das ganze dann so:
function TConverter.GetStr: string;
var Context: TSuperRttiContext; begin Context := TSuperRttiContext.Create; result := IntToStr(Integer(fType)) + Context.AsJson<TSession>(fObject).AsJSon + MessageDelimitter; Context.Free; end;
Delphi-Quellcode:
TNickChange etc sind Klassen von von TSession abgeleitet, damit kannst du dann zB dein Kommando steuern.
procedure TConverter.SetStr(const Value: string);
var Context : TSuperRttiContext; Obj : TSession; Identifier: TObjIdentifier; StrType : string; StrObj : string; begin Context := TSuperRttiContext.Create; StrType := copy(Value, 1, Pos('{', Value) - 1); StrObj := copy(Value, Pos('{', Value), MaxInt); Identifier := TObjIdentifier(StrToInt(StrType)); case Identifier of otNone : Obj := NIL; otSession : Obj := Context.AsType<TSession>(SO(StrObj)); otNickChange : Obj := Context.AsType<TNickChange>(SO(StrObj)); otNachricht : Obj := Context.AsType<TNachricht>(SO(StrObj)); otKickNachricht: Obj := Context.AsType<TKickNachricht>(SO(StrObj)); otUserList : Obj := Context.AsType<TUserList>(SO(StrObj)); otWelcome : Obj := Context.AsType<TWelcome>(SO(StrObj)); end; SetObject(Obj); Context.Free; end; Vielleicht hilfts dir :D |
AW: Befehle trennen
Ich habe es jetzt doch so gemacht, wie ich es erst nicht machen wollte... Mit
![]() |
Alle Zeitangaben in WEZ +1. Es ist jetzt 20:50 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz