 |
BorlandTalk.com Borland discussion newsgroups
|
| View previous topic :: View next topic |
| Author |
Message |
cks Guest
|
Posted: Thu Oct 23, 2003 5:01 am Post subject: Give me some idea. |
|
|
i need to create a Server & Client with Indy component.
My server will need to send command to Client to order it to performance
some job.
Example. Send 'shutdown' to client, then Client will shutdown the PC.
or another way, Send 99, to client to do the same things. (let say 99 means
shut down)
Question 1. Can someone tell me which method is suitable, or any other
method is the best choice?
Question 2. How if sometimes i need to send command 99, 88, 11, and
sometimes the certain command
are passed with parameters in string.
Example: command 88 will show a message dialog, but we need to pass 88 with
'Hi, this is testing' string
or just send everything in string, and extract the meanings from the string?
Question 3. Performance issues on different methods?
thanks in advance
|
|
| Back to top |
|
 |
Remy Lebeau (TeamB) Guest
|
Posted: Thu Oct 23, 2003 5:31 am Post subject: Re: Give me some idea. |
|
|
"cks" <chuaks (AT) dynabook (DOT) com.my> wrote
| Quote: | Question 1. Can someone tell me which method is suitable,
or any other method is the best choice?
|
That depends on what kind of data you want to send with each command, if
any. If all you want is simple commands with no data, then
Read/WriteInteger() or Read/WriteLn() will work fine.
| Quote: | Question 2. How if sometimes i need to send command 99, 88, 11,
and sometimes the certain command are passed with parameters in string.
|
One way would be to just put everything into a single string and use
Read/WriteLn(). Anotehr way is to use Read/WriteStrings(), with each string
being a different parameter. Another way would be to put everything into a
structure and then use Read/WriteBuffer(). Another alternative is to use
Read/WriteRFCReply().
It really comes down to what exactly you need to send for each commands, so
that you can come up with some kind of common formatting for all of them.
| Quote: | Question 3. Performance issues on different methods?
|
Again, it depends on what exactly you are sending.
Gambit
|
|
| Back to top |
|
 |
Ioan Ghip Guest
|
Posted: Thu Oct 23, 2003 5:31 am Post subject: Re: Give me some idea. |
|
|
| Quote: | Question 2. How if sometimes i need to send command 99, 88, 11, and
sometimes the certain command
are passed with parameters in string.
Example: command 88 will show a message dialog, but we need to pass 88
with
'Hi, this is testing' string
or just send everything in string, and extract the meanings from the
string? |
type
{the Communication Block used in both parts (Server+Client)}
TCommBlock = record
Command: integer;
DESTINATIONSERVER: string[128];
end;
const
_SHUTDOWN_ = 88;
{if the client send the command}
procedure TForm1.Button1Click(Sender: TObject);
var
client: TIdTCPClient;
SndCmd: TCommBlock;
begin
FillChar(SndCmd, sizeof(RecCmd), #0);
client := TIdTCPClient.Create(nil);
try
{set the connection prop.}
client.Host := '127.0.0.1';
client.Port := 8090;
client.Connect(5000);
{send informations}
SndCmd.Text := 'bye bye';
SndCmd.Command := _SHUTDOWN_;
client.WriteBuffer(SndCmd, SizeOf(SndCmd));
client.Disconnect;
finally
client.Free;
end;
end;
and on the server side (in the OnExecute event of IdTCPServer):
procedure TForm1.IdTCPServer1Execute(AThread: TIdPeerThread);
var
RecCmd: TCommBlock;
begin
try
if not AThread.Terminated and AThread.Connection.Connected then
begin
FillChar(RecCmd, sizeof(RecCmd), #0);
AThread.Connection.ReadBuffer(RecCmd, SizeOf(RecCmd));
if RecCmd.Command = _SHUTDOWN_ then
begin
// do the shut down
end;
end;
except
on e: EIdConnClosedGracefully do
exit; // obvious..
on e: Exception do
begin
if e is EIdSocketError then
raise;
end;
end;
end;
-ioan
|
|
| Back to top |
|
 |
Ioan Ghip Guest
|
Posted: Thu Oct 23, 2003 5:33 am Post subject: Re: Give me some idea. |
|
|
| Quote: | type
{the Communication Block used in both parts (Server+Client)}
TCommBlock = record
Command: integer;
DESTINATIONSERVER: string[128];
end;
|
"DESTINATIONSERVER" change that with "Text" <g>
-i
|
|
| Back to top |
|
 |
Colonel Tony Guest
|
Posted: Thu Oct 23, 2003 5:58 am Post subject: use a tstringlist |
|
|
use a tstringlist, then send the commatext with writeln
i.e.
mystringlist.values['command']:= '88';
mystringlist.values['msgstr']:=''Hi, this is testing string';
to send to the server do
myclient.writeln(mystringlist.commatext);
what gets sent across the wire is:
command=88,msgstr="Hi, this is testing string"
if you need to send a multi line message use another tstringlist or
descendent and assign it's commatext to the msgstr value of the first.
mystringlist.values['msgstr']:= memo1.lines.commatext;
Then on the other side create a recieving stringlist and set the commatext
commandlist.commatext:= athread.connection.readln('',5000);
if commandlist.values['command'] = '88' then
begin
//do something with the message
end;
or you could just use readinteger and writeinteger to send just the bytes
for the command.
Either way it's all very easy to do with blocking sockets.
Performance for the stringlist method is good and it is easy to understand
and read the code. Also using stringlists has much less bloat than some xml
based protocols, and you could easily compress your stringlist and stream it
over if you have alot of params/text :-)
Hope this helps you out.
Tony
|
|
| Back to top |
|
 |
Remy Lebeau (TeamB) Guest
|
Posted: Thu Oct 23, 2003 6:04 am Post subject: Re: Give me some idea. |
|
|
"Ioan Ghip" <aaabbb (AT) ccc (DOT) com> wrote
(Typo aside) Rather than forcing every packet to include a fixed sized text
field that may or may not be used at all let alone filled to capacity, you
could use a dynamic-sized field instead. For example:
type
TCommHeader = packed record
Command: Integer;
DataSize: Integer;
end;
TCommBlock = packed record
Header: TCommHeader;
Data: String;
end;
const
CMD_MSGBOX = 88;
--- Client ---
procedure SendCommBlock(AConn: TIdTCPConnection; var SndCmd:
TCommBlock);
begin
AConn.WriteBuffer(SndCmd.Header, SizeOf(SndCmd.Header));
if SndCmd.Header.DataSize > 0 then AConn.Write(SndCmd.Data);
end;
procedure TForm1.Button1Click(Sender: TObject);
var
SendCmd: TCommBlock;
begin
//...
SndCmd.Data := 'bye bye';
SndCmd.Header.Command := CMD_MSGBOX;
SndCmd.Header.DataSize := Length(SndCmd.Data);
SendCommBlock(IdTCPClient1, SndCmd);
//..
end;
--- Server ---
procedure ReadCommBlock(AConn: TIdTCPConnection; var RecCmd:
TCommBlock);
begin
AConn.ReadBuffer(RecCmd.Header, SizeOf(RecCmd.Header));
if RecCmd.Header.DataSize > 0 then RecCmd.Data :=
AConn.ReadString(RecCmd.Header.DataSize);
end;
procedure TForm1.IdTCPServer1Execute(AThread: TIdPeerThread);
var
RecCmd: TCommBlock;
begin
//...
ReadCommBlock(Athread.Connection, RecCmd);
if RecCmd.Command = CMD_MSGBOX then
begin
Windows.MessageBox(nil, PChar(RecCmd.Data), 'Client Message',
MB_OK);
end;
//...
end;
Gambit
|
|
| Back to top |
|
 |
Remy Lebeau (TeamB) Guest
|
Posted: Thu Oct 23, 2003 6:18 am Post subject: Re: use a tstringlist |
|
|
"Colonel Tony" <tcaduto (AT) amsoftwaredesign (DOT) com> wrote
| Quote: | use a tstringlist, then send the commatext with writeln
|
The alternative is use Read/WriteStrings() instead of ReadWriteLn().
Gambit
|
|
| Back to top |
|
 |
cks Guest
|
Posted: Thu Oct 23, 2003 7:04 am Post subject: Another questions |
|
|
if i have many commands need to be identify,
is it good to code everything inside the IdTCPServer1Execute
means inside the IdTCPServer1Execute will have a lot of if (or case)
if cmd = '88'
...
if cmd = '89'
...
if cmd = '90'
if msg = 'xxxxx'
....
if msg = 'yyyy'
...
...
...
...
just to figure out whether this is the normal way people doing ALL the
'processess' inside Execute ?
or is there any other way of doing ?
|
|
| Back to top |
|
 |
Remy Lebeau (TeamB) Guest
|
Posted: Thu Oct 23, 2003 8:17 am Post subject: Re: Another questions |
|
|
"cks" <chuaks (AT) dynabook (DOT) com.my> wrote
| Quote: | if i have many commands need to be identify,
is it good to code everything inside the
IdTCPServer1Execute
|
You have to anyway, since that the place where the data will be available
for reading.
| Quote: | means inside the IdTCPServer1Execute will have a lot of if (or case)
|
Better to use a case statement, but yes:
Case cmd of
88: ...
89: ...
90:
if msg = 'xxxxx' ...
if msg = 'yyyy'
end;
Gambit
|
|
| Back to top |
|
 |
Tony Caduto Guest
|
Posted: Fri Oct 24, 2003 1:36 am Post subject: Re: use a tstringlist |
|
|
Remy Lebeau (TeamB) wrote:
| Quote: |
"Colonel Tony" <tcaduto (AT) amsoftwaredesign (DOT) com> wrote in message
news:3f977018$1 (AT) newsgroups (DOT) borland.com...
use a tstringlist, then send the commatext with writeln
The alternative is use Read/WriteStrings() instead of ReadWriteLn().
Gambit
|
Yes, you could sent the stringlist that way as well
I just did it that way and stuck with it.
|
|
| Back to top |
|
 |
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
|