epagos
asked on
How can i make a multithreaded app with TTcpServer on delphi?
Hello guys,
I have made an application on delphi using TTCPServer and TTCPClient without using vlc (just plain code).
I want to make it multithreaded but i dont have much idea how to do it. Can anyone show me an example of how to do it?
NOTE: Do not tell me about Indy or any of those components, i know they are exellent and they already comes with multithreading but they are much big in size that ttcpserver component and i need the exe file to be SMALL.
Thanks in advance,
Elias
I have made an application on delphi using TTCPServer and TTCPClient without using vlc (just plain code).
I want to make it multithreaded but i dont have much idea how to do it. Can anyone show me an example of how to do it?
NOTE: Do not tell me about Indy or any of those components, i know they are exellent and they already comes with multithreading but they are much big in size that ttcpserver component and i need the exe file to be SMALL.
Thanks in advance,
Elias
ASKER
hey ciuly,
Yes it makes sense, its basically what im trying to do. For what i can read on sockets.pas (TTcpServer and TTcpClient unit) it automatically destroy the thread after the client disconnect so i should not worry about that.
I have atached the code of the app. Right now it works like a proxy server, its the easiest way for testing the multithreading (i still didnt add the real functions for it).
I have 2 problems, the first one is the multithreading issue, and the second one is that sometimes it wont take new incoming connections, wich i think is because of the first issue.
Any help is welcome :)
Thanks,
Elias
Yes it makes sense, its basically what im trying to do. For what i can read on sockets.pas (TTcpServer and TTcpClient unit) it automatically destroy the thread after the client disconnect so i should not worry about that.
I have atached the code of the app. Right now it works like a proxy server, its the easiest way for testing the multithreading (i still didnt add the real functions for it).
I have 2 problems, the first one is the multithreading issue, and the second one is that sometimes it wont take new incoming connections, wich i think is because of the first issue.
Any help is welcome :)
Thanks,
Elias
program eclipse;
{$APPTYPE CONSOLE}
uses
sysutils,
sockets in 'sockets.pas';
type
Server = class(TTcpServer)
private
public
Procedure Start;
procedure FOnAccept(Sender: TObject; ClientSocket: TCustomIpClient);
Procedure FGetThread(Sender: TObject; var ClientSocketThread: TClientSocketThread);
end;
type
Client = class(TTcpClient)
end;
type
SocketClient = class(TClientSocketThread)
private
{ Private declarations }
public
procedure Execute(ClientSocket: TCustomIpClient);
end;
var Server1: Server;
Client1: array[0..100] of Client; // the program will just use 1 client, initially i made an array of 100 clients to test.
clients: integer;
//ServerThread: SocketClient;
procedure SocketClient.Execute (ClientSocket: TCustomIpClient);
begin
writeln('Thread Executed'); // This event is never executed, i dont know why.
end;
Procedure Server.FGetThread(Sender: TObject; var ClientSocketThread: TClientSocketThread);
begin
writeln('Creating Thread');
ClientSocketThread := SocketClient.Create(Server1.ServerSocketThread);
end;
Procedure Server.Start();
Begin
server1 := Server.Create(nil);
Server1.Active := False;
Server1.LocalPort := '1759';
Server1.Localhost := Server1.LocalHostName;
Server1.BlockMode := bmThreadBlocking;
Server1.OnAccept := Server1.FonAccept;
Server1.OnGetThread := Server1.FGetThread;
Server1.Active := True;
repeat
sleep(500);
until 1=2; // I make sure that the server wont stop
End;
procedure Server.FOnAccept(Sender: TObject; ClientSocket: TCustomIpClient);
var
s,x,y: string;
Rbuf: array[0..32768] of char;
RCount, counter, a: integer;
begin
s:=ClientSocket.Receiveln();
Repeat
if(pos('Host:',s) > 0) then
begin
y := StringReplace(s, 'Host:','', [rfReplaceAll, rfIgnoreCase ]);
y := StringReplace(y, ' ','', [rfReplaceAll, rfIgnoreCase ]);
end;
if(pos('Proxy-Connection:',s) > 0) then
begin
s := StringReplace(s, 'Proxy-Connection:','Connection:', [rfReplaceAll]);
end;
x:= x + s;
if(s<>'') then begin x:= x + #13 + #10; end;
s:=ClientSocket.Receiveln();
Until s='';
for a := 1 to clients do
begin
if Client1[a].Connected = False then counter := a;
end;
Client1[counter].RemoteHost := y;
while Client1[counter].Connected = True do begin
Client1[counter].WaitForData(100);
end;
try
Client1[counter].Active := True;
if Client1[counter].Connect then
begin
Client1[counter].Sendln(x);
Client1[counter].Sendln('');
end;
finally
end;
RCount := Client1[counter].ReceiveBuf(Rbuf, 1024);
ClientSocket.SendBuf(Rbuf,RCount);
sleep(100);
while Client1[counter].WaitforData(1000) AND Client1[counter].connected do
begin
RCount := Client1[counter].ReceiveBuf(Rbuf, 4092);
if ClientSocket.Connected = True then
ClientSocket.SendBuf(Rbuf,RCount)
else begin client1[counter].Disconnect; break; end;
sleep(100);
end;
Client1[counter].Disconnect;
writeln('Client Disconecting');
end;
// CLIENT START
var cc : integer;
begin
clients := 100;
for cc := 0 to clients do
begin
Client1[cc] := Client.Create(nil);
Client1[cc].BlockMode := bmBlocking;
Client1[cc].RemotePort := '80';
end;
Server1.start();
end.
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
sprry about the madexcept stuff. you can remove the first mad* units :)
ASKER
Thanks a LOT for all those info. As u can see im a real noob on delphi :)
I will check your code and let u know if i have any other question. About all those clients they are not for connecting to the server, initially i wanted to do a very simple proxy server, so when the server received a connections it will order the clients to get the requested url. (thats the correct method?)
Elias
I will check your code and let u know if i have any other question. About all those clients they are not for connecting to the server, initially i wanted to do a very simple proxy server, so when the server received a connections it will order the clients to get the requested url. (thats the correct method?)
Elias
not exactly. a proxy is somethign that intermediates.
so if the client says:
GET something
the proxy will get that something and then send it back to the client.
soi, either you don't want a "proxy" but something else, or you miss-explained the behaviour.
so if the client says:
GET something
the proxy will get that something and then send it back to the client.
soi, either you don't want a "proxy" but something else, or you miss-explained the behaviour.
ASKER
thats what the app is doing, when the server1.accept is executed it will get the header of the request and then it will GET that website through the client components and then it will return it through clientsocket on Server1.Accept
ASKER
oh i forgot...
Im trying to connect to this app from other diferent pcs on diferent networks... sometimes it works and it receives the remote connection and sometimes it just do not receive it. Do u see any problem on the code wich can be causing that?
Just from my pc i connect from my own machine i can connect about 80-90% of the times.
Im trying to connect to this app from other diferent pcs on diferent networks... sometimes it works and it receives the remote connection and sometimes it just do not receive it. Do u see any problem on the code wich can be causing that?
Just from my pc i connect from my own machine i can connect about 80-90% of the times.
I see. well, I'm not sure how to test the behaviour you are saying. what are you using? a browser is ok?
as I said, you will have problems with not synchronizing the resources accessed by many threads. for one axample: the clients array. plus that warning I mentioned. etc.
so, try to put all my suggestions into practice in your code and I'll continue on it tomorrow. (I'm off to bed now)
as I said, you will have problems with not synchronizing the resources accessed by many threads. for one axample: the clients array. plus that warning I mentioned. etc.
so, try to put all my suggestions into practice in your code and I'll continue on it tomorrow. (I'm off to bed now)
2nd: I don't remember seeing such an example, but the idea behind it is really simple.
- when a client connects (in the onaccept), you create a new thread. that thread will have a member that holds the connection (so it can keep reading from it). you should put that thread in a list (TObjectLsit for example) os that you can manage the connections.
- when a client disconnects, search for that thread in the list (you know the disconnecting client and each threads connection) and remove it from list and destroy it
the server can expose an event, like onexecute, similar to indy and the threads will call that event when they have some data to be read.
let me know if that does not make sense for you