Psylord
asked on
ICS Sockets, Buffering and numerics.
Baically what I aim to do with the following code is to use command prefixes (numerics) to allow easy handling of incoming data to both clients and servers. I'm looking to do this in an IRC style way. The problem that arises is that I know nothing about doing it. Plainly hehe.
My question is really a request for code completion/improvement here. Preferably, the person answering this has done quite a bit of work with ICS, and handled buffering and numeric style command/response handling. This code is only a base model, I'm very open here.
Here's how it should work...
When the data is recieved, I want to make sure I have all of it, before I do anything with it. I also want to avoid having peices from the NEXT command (which can happen I've been told).
bacially I guess if you can see what I'm trying to do below and can improve it and make it work fully, you're the person for the answer hehe. I'll let my code do the talking...
procedure TForm1.SendCommand(Numeric : Integer; Length: Integer; Content: String);
var
Temp: TStringList;
begin
Data:= TStringList.Create;
Data.Insert(0, IntToStr(Numeric));
Data.Insert(1, IntToStr(Length));
Temp := TStringList.Create;
Temp.Text := Content;
Data.Insert(2, Temp.CommaText);
TextClient.Send(Data.Comma Text); {Error on this line}
end;
procedure TForm1.TextServerDataAvail able(Sende r: TObject; Error: Word);
var
ReciveBuffer: String;
FCurrentlyReciving: Boolean;
begin
Data:= TStringList.Create;
ReciveBuffer := ReciveBuffer + TextServer.ReceiveStr;
Data.CommaText := ReciveBuffer;
if Data.Count < 3 then
begin
FCurrentlyReciving := True;
exit;
if Length(Data[2]) < StrToInt(Data[1]) then
begin
FCurrentlyReciving := True;
exit;
end else
begin
FCurrentlyReciving := False;
Data.CommaText:= TextServer.ReceiveStr;
Echo(Data.CommaText);
ParseCommand(StrToInt(Data [0]), Data[2]);
end;
end;
end;
procedure TForm1.ParseCommand(Numeri c: Integer; Content: String);
begin
{This is where I'll be parsing all commands}
end;
Thanks!
Psylord
My question is really a request for code completion/improvement here. Preferably, the person answering this has done quite a bit of work with ICS, and handled buffering and numeric style command/response handling. This code is only a base model, I'm very open here.
Here's how it should work...
When the data is recieved, I want to make sure I have all of it, before I do anything with it. I also want to avoid having peices from the NEXT command (which can happen I've been told).
bacially I guess if you can see what I'm trying to do below and can improve it and make it work fully, you're the person for the answer hehe. I'll let my code do the talking...
procedure TForm1.SendCommand(Numeric
var
Temp: TStringList;
begin
Data:= TStringList.Create;
Data.Insert(0, IntToStr(Numeric));
Data.Insert(1, IntToStr(Length));
Temp := TStringList.Create;
Temp.Text := Content;
Data.Insert(2, Temp.CommaText);
TextClient.Send(Data.Comma
end;
procedure TForm1.TextServerDataAvail
var
ReciveBuffer: String;
FCurrentlyReciving: Boolean;
begin
Data:= TStringList.Create;
ReciveBuffer := ReciveBuffer + TextServer.ReceiveStr;
Data.CommaText := ReciveBuffer;
if Data.Count < 3 then
begin
FCurrentlyReciving := True;
exit;
if Length(Data[2]) < StrToInt(Data[1]) then
begin
FCurrentlyReciving := True;
exit;
end else
begin
FCurrentlyReciving := False;
Data.CommaText:= TextServer.ReceiveStr;
Echo(Data.CommaText);
ParseCommand(StrToInt(Data
end;
end;
end;
procedure TForm1.ParseCommand(Numeri
begin
{This is where I'll be parsing all commands}
end;
Thanks!
Psylord
Oops. Damn copy-paste... ;-)
Should be like this of yourse:
procedure TForm1.SendCommand(Numeric : Integer; const Content: String);
begin
TextClient.Send(Format('%d %s',[Numeric,StringReplace (StringRep lace(Conte nt,'\','\\ ',[rfRepla ceAll]),#1 3,'\n',[rf ReplaceAll ])]));
end;
Should be like this of yourse:
procedure TForm1.SendCommand(Numeric
begin
TextClient.Send(Format('%d
end;
ASKER
Ok don't get upset yet... I've decided to use the borland sockets, as they're much easier... Especially when sending to specific clients...
Is there any way you can change the code around to just use '#13#10' as the end of the command? It think I might understand it a little better... In other words, instead of everything else I said, just wait until #13#10 is recieved and BOOM! we have the command.
Your code might (and probably does) have the same effect, but it's just a little confusing to me and I couldn't get it working with ICS because ICS SUCKS! So, if you would, with the normal Borland internete client/server...
If you can I'll increase the points 50 more. <:D
Here's what the recieve events look like for the sockets I'm using now:
{Server}
procedure TForm1.ClientRead(Sender: TObject; Socket: TCustomWinSocket);
begin
end;
{Client}
procedure TForm1.ServerClientRead(Se nder: TObject;
Socket: TCustomWinSocket);
begin
end;
When I parse these, I'll need to send the socket along with it so I know who to reply to when I parse the command, so my parsecommand will look like this:
procedure TForm1.ParseCommand(Socket : TCustomWinSocket; Numeric: Integer; Content: String);
begin
case Numeric of
100:
begin
{The numeric was "100"!}
end;
end; {Case}
end; {Proc}
Stupid comments and example code provided. :)
So basically I'll be sending my commands like this:
Client.Socket.SendText(Int ToStr(Nume ric) + ' ' + Content);
Server.Socket.SendText(Int ToStr(Nume ric) + ' ' + Content);
Appreciate the help,
Psylord
Is there any way you can change the code around to just use '#13#10' as the end of the command? It think I might understand it a little better... In other words, instead of everything else I said, just wait until #13#10 is recieved and BOOM! we have the command.
Your code might (and probably does) have the same effect, but it's just a little confusing to me and I couldn't get it working with ICS because ICS SUCKS! So, if you would, with the normal Borland internete client/server...
If you can I'll increase the points 50 more. <:D
Here's what the recieve events look like for the sockets I'm using now:
{Server}
procedure TForm1.ClientRead(Sender: TObject; Socket: TCustomWinSocket);
begin
end;
{Client}
procedure TForm1.ServerClientRead(Se
Socket: TCustomWinSocket);
begin
end;
When I parse these, I'll need to send the socket along with it so I know who to reply to when I parse the command, so my parsecommand will look like this:
procedure TForm1.ParseCommand(Socket
begin
case Numeric of
100:
begin
{The numeric was "100"!}
end;
end; {Case}
end; {Proc}
Stupid comments and example code provided. :)
So basically I'll be sending my commands like this:
Client.Socket.SendText(Int
Server.Socket.SendText(Int
Appreciate the help,
Psylord
ASKER
Ok don't get upset yet... I've decided to use the borland sockets, as they're much easier... Especially when sending to specific clients...
Is there any way you can change the code around to just use '#13#10' as the end of the command? It think I might understand it a little better... In other words, instead of everything else I said, just wait until #13#10 is recieved and BOOM! we have the command.
Your code might (and probably does) have the same effect, but it's just a little confusing to me and I couldn't get it working with ICS because ICS SUCKS! So, if you would, with the normal Borland internete client/server...
If you can I'll increase the points 50 more. <:D
Here's what the recieve events look like for the sockets I'm using now:
{Server}
procedure TForm1.ClientRead(Sender: TObject; Socket: TCustomWinSocket);
begin
end;
{Client}
procedure TForm1.ServerClientRead(Se nder: TObject;
Socket: TCustomWinSocket);
begin
end;
When I parse these, I'll need to send the socket along with it so I know who to reply to when I parse the command, so my parsecommand will look like this:
procedure TForm1.ParseCommand(Socket : TCustomWinSocket; Numeric: Integer; Content: String);
begin
case Numeric of
100:
begin
{The numeric was "100"!}
end;
end; {Case}
end; {Proc}
Stupid comments and example code provided. :)
So basically I'll be sending my commands like this:
Client.Socket.SendText(Int ToStr(Nume ric) + ' ' + Content);
Server.Socket.SendText(Int ToStr(Nume ric) + ' ' + Content);
Appreciate the help,
Psylord
Is there any way you can change the code around to just use '#13#10' as the end of the command? It think I might understand it a little better... In other words, instead of everything else I said, just wait until #13#10 is recieved and BOOM! we have the command.
Your code might (and probably does) have the same effect, but it's just a little confusing to me and I couldn't get it working with ICS because ICS SUCKS! So, if you would, with the normal Borland internete client/server...
If you can I'll increase the points 50 more. <:D
Here's what the recieve events look like for the sockets I'm using now:
{Server}
procedure TForm1.ClientRead(Sender: TObject; Socket: TCustomWinSocket);
begin
end;
{Client}
procedure TForm1.ServerClientRead(Se
Socket: TCustomWinSocket);
begin
end;
When I parse these, I'll need to send the socket along with it so I know who to reply to when I parse the command, so my parsecommand will look like this:
procedure TForm1.ParseCommand(Socket
begin
case Numeric of
100:
begin
{The numeric was "100"!}
end;
end; {Case}
end; {Proc}
Stupid comments and example code provided. :)
So basically I'll be sending my commands like this:
Client.Socket.SendText(Int
Server.Socket.SendText(Int
Appreciate the help,
Psylord
ASKER
Ok don't get upset yet... I've decided to use the borland sockets, as they're much easier... Especially when sending to specific clients...
Is there any way you can change the code around to just use '#13#10' as the end of the command? It think I might understand it a little better... In other words, instead of everything else I said, just wait until #13#10 is recieved and BOOM! we have the command.
Your code might (and probably does) have the same effect, but it's just a little confusing to me and I couldn't get it working with ICS because ICS SUCKS! So, if you would, with the normal Borland internete client/server...
If you can I'll increase the points 50 more. <:D
Here's what the recieve events look like for the sockets I'm using now:
{Server}
procedure TForm1.ClientRead(Sender: TObject; Socket: TCustomWinSocket);
begin
end;
{Client}
procedure TForm1.ServerClientRead(Se nder: TObject;
Socket: TCustomWinSocket);
begin
end;
When I parse these, I'll need to send the socket along with it so I know who to reply to when I parse the command, so my parsecommand will look like this:
procedure TForm1.ParseCommand(Socket : TCustomWinSocket; Numeric: Integer; Content: String);
begin
case Numeric of
100:
begin
{The numeric was "100"!}
end;
end; {Case}
end; {Proc}
Stupid comments and example code provided. :)
So basically I'll be sending my commands like this:
Client.Socket.SendText(Int ToStr(Nume ric) + ' ' + Content);
Server.Socket.SendText(Int ToStr(Nume ric) + ' ' + Content);
Appreciate the help,
Psylord
Is there any way you can change the code around to just use '#13#10' as the end of the command? It think I might understand it a little better... In other words, instead of everything else I said, just wait until #13#10 is recieved and BOOM! we have the command.
Your code might (and probably does) have the same effect, but it's just a little confusing to me and I couldn't get it working with ICS because ICS SUCKS! So, if you would, with the normal Borland internete client/server...
If you can I'll increase the points 50 more. <:D
Here's what the recieve events look like for the sockets I'm using now:
{Server}
procedure TForm1.ClientRead(Sender: TObject; Socket: TCustomWinSocket);
begin
end;
{Client}
procedure TForm1.ServerClientRead(Se
Socket: TCustomWinSocket);
begin
end;
When I parse these, I'll need to send the socket along with it so I know who to reply to when I parse the command, so my parsecommand will look like this:
procedure TForm1.ParseCommand(Socket
begin
case Numeric of
100:
begin
{The numeric was "100"!}
end;
end; {Case}
end; {Proc}
Stupid comments and example code provided. :)
So basically I'll be sending my commands like this:
Client.Socket.SendText(Int
Server.Socket.SendText(Int
Appreciate the help,
Psylord
ASKER
Holy crap, it posted 3 times. Whoops. :)
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
*Sigh* I will be specific in my qeustions from now on. Reviewing the code now. By the way, I have YET to get that winsock question's code to work...
ASKER
Still doesn't work. but ok.
ASKER
still can't seem to get it working but YEAH. Here's your points.
Psylord, what does not work?
You need to add a buffer which is kept across your TextServerDataAvailable; to do this, just add a "FReceiveBuffer: string" to your TForm1 private declaration. Then work like this:
procedure TForm1.SendCommand(Numeric
begin
TextClient.Send(Format('%d
end;
procedure TForm1.TextServerDataAvail
var
Line: string;
I: Integer;
begin
FReciveBuffer:=FReciveBuff
I:=Pos(#13,FReceiveBuffer)
while I>0 do begin
Line:=Copy(FReceiveBuffer,
Delete(FReceiveBuffer,1,I)
Line:=StringReplace(String
I:=Pos(' ',Line);
ParseCommand(StrToInt(Copy
I:=Pos(#13,FReceiveBuffer)
end;
end;
Of course, the code is made so that it will handle #13 in the data alright. BTW, in your code, you careate tons of TStringLists - but you never free them. That is called a memory leak and makes an application use more and more memory until the app is terminated or the available memory is exhausted. Try to free the mem you allocate, Delphi does *not* destroy class instances automatically!