BorlandTalk.com Forum Index BorlandTalk.com
Borland discussion newsgroups
 
Archives   FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

Writing to an ServerClientThread ?

 
Post new topic   Reply to topic    BorlandTalk.com Forum Index -> Delphi Internet Winsock
View previous topic :: View next topic  
Author Message
Johnny Hansen
Guest





PostPosted: Mon Dec 29, 2003 9:12 am    Post subject: Writing to an ServerClientThread ? Reply with quote



Hi,



I have made a program that act as server and every time a client connects,
the server creates a new thread for the communication.



The client can send to the server and by means of a postmessage can I send
the data received from the client to the servers main-thread, and this works
just fine. My question is now, how do I send/write to the client.

I have create a TwinSocketStream for holding the data received in the thread
and as fare I understand is the right way of writing to the client by using
the TwinSocketStream write metode, but have do I get my data to the right
thread if more than one thread has been created (more than one client
connected).



Hope for some help.



Best regards



Johnny


Back to top
Martin James
Guest





PostPosted: Mon Dec 29, 2003 9:22 am    Post subject: Re: Writing to an ServerClientThread ? Reply with quote




Quote:
I have create a TwinSocketStream for holding the data received in the
thread
and as fare I understand is the right way of writing to the client by
using
the TwinSocketStream write metode, but have do I get my data to the right
thread if more than one thread has been created (more than one client
connected).

You could pass the TwinSocketStream in the message, either directly or as a
field of some 'communication object' that contains the incoming data from
the client & write methods that hide the TwinSocketStream from the main
thread. You could pass the whole ServerClientThread in the message, but you
probably don't want all the thread gunge accessible from your main form.

Writing directly from the main thread like this is fine as long as the
serverClientThread is only reading. If the ServerClientThread also writes,
(eg. echoing input chars), the write method will need a CS to prevent the
main thread and SC thread writing at the same time.

Rgds,
Martin



Back to top
Johnny Hansen
Guest





PostPosted: Mon Dec 29, 2003 9:50 am    Post subject: Re: Writing to an ServerClientThread ? Reply with quote



Hi



I have this idea that I can make a procedure in the thread link this one



procedure SendData(var DataTilClient: string);

begin

TxData := DataTilClient;

end;



Where TxData is of type string define in the thread, from my main-thread I
can call this procedure with the "message" I want to as a parameter.



In the ClientExecute must I then have the following code



while (not Terminated) and ClientSocket.Connected do

begin

if SockStream.WaitForData(FClientTimeOut) then

begin

try

SetLength(RequestBuf,BlockSize);

try

LenReceived := SockStream.Read(RequestBuf[1], Length(RequestBuf));

except

break;

end;

if length(TxData) > 0 then

SockStream.Write(TxData[1],length(TxData)); // write data to the
client

if (LenReceived > 0) then

begin

inc(ReqPerSec);

SetLength(RequestBuf, LenReceived );

postmessage(main.Handle,WM_USER + 1,WM_USER +
2,integer(PChar(RequestBuf)));

end

else

BREAK; // client has send zero data

except

BREAK; // stream read error, unexpected disconnect, ...

end;

end

else

BREAK; // client did not send data within timeout limit

end;



But if I use this way, I must be sure that all thread has send the data to
the clients before I change the TxData and that's why I must be sure of
which thread has been called.



Is this a dead approach ?.



"Martin James" <mjames_falcon (AT) dial (DOT) pipex.com> skrev i en meddelelse
news:3feff236 (AT) newsgroups (DOT) borland.com...
Quote:

I have create a TwinSocketStream for holding the data received in the
thread
and as fare I understand is the right way of writing to the client by
using
the TwinSocketStream write metode, but have do I get my data to the
right
thread if more than one thread has been created (more than one client
connected).

You could pass the TwinSocketStream in the message, either directly or as
a
field of some 'communication object' that contains the incoming data from
the client & write methods that hide the TwinSocketStream from the main
thread. You could pass the whole ServerClientThread in the message, but
you
probably don't want all the thread gunge accessible from your main form.

Writing directly from the main thread like this is fine as long as the
serverClientThread is only reading. If the ServerClientThread also
writes,
(eg. echoing input chars), the write method will need a CS to prevent the
main thread and SC thread writing at the same time.

Rgds,
Martin





Back to top
Martin James
Guest





PostPosted: Mon Dec 29, 2003 11:19 am    Post subject: Re: Writing to an ServerClientThread ? Reply with quote

"Johnny Hansen" <johnny (AT) jokiha (DOT) dk> wrote

Quote:
Hi



I have this idea that I can make a procedure in the thread link this one


<snip poor polling code>

Quote:

Is this a dead approach ?.


Well, it's not dead but it has a poor quality of life. Any polling approach
is just a bad idea if it can be avoided. Not only is it a waste of CPU, but
there is inevitable latency - waiting for the rx timeout before sending is
just not necessary.

Post off your data and send method to the main thread - it's so much easier.
You could use an object like:

TcommsObject=class(Tobject)
private
inputBuffer:array[0.255] of char;
ioStream:TwinSocketStream;
public
procedure send(outStr:string);
end;

Create one at the top of your 'clientExecute' loop, load data into the
buffer as it is received until your EOL char, (or whatever your protocol
uses to define 'end of message'), load up the ioStream field with your
thread TwinSocketStream and then post it off to the main thread:

postMessage(MainThreadHandle,WM_INDATA,integer(thisCommsObject),0);

The thread can then immediately create another commsObject & start receiving
stuff while the previous one is on its way to the main thread or being
processed there. There is no need for anything to wait or poll under
'normal' loadings.

The send method need do no more than write to the private socket stream. Of
course, you could add more methods to the comms object - if you have a
special protocol to check, you could have a 'doProtocol(inChar:char)' method
that does all that stuff on a character-by-character basis & loads up fields
in the commsObject with commands, data etc. extracted from the input stream.

When the main thread is finished with a comms object, it can simply free it.
If the data being transferred is large and/or bursty, there are more complex
schemes where a pool of comms objects can be shared by all the serverClient
threads, so eliminating the overhead of memory-management calls, but this is
not really essential unless you really need high performance.

Rgds,
Martin









Back to top
Remy Lebeau (TeamB)
Guest





PostPosted: Mon Dec 29, 2003 6:10 pm    Post subject: Re: Writing to an ServerClientThread ? Reply with quote


"Martin James" <mjames_falcon (AT) dial (DOT) pipex.com> wrote


Quote:
Writing directly from the main thread like this is fine as long as the
serverClientThread is only reading. If the ServerClientThread also
writes, (eg. echoing input chars), the write method will need a CS
to prevent the main thread and SC thread writing at the same time.

TWinSocketStream already does that internally, by calling the Socket's
Lock() and Unlock() methods when you call Read() and Write().


Gambit



Back to top
Martin James
Guest





PostPosted: Mon Dec 29, 2003 6:14 pm    Post subject: Re: Writing to an ServerClientThread ? Reply with quote

Quote:

TWinSocketStream already does that internally, by calling the Socket's
Lock() and Unlock() methods when you call Read() and Write().


OK I never had the source for these units & so always put in a CS.when 2+
threads were writing. Obviously a redundant op!

Rgds,
Martin



Back to top
Remy Lebeau (TeamB)
Guest





PostPosted: Mon Dec 29, 2003 6:23 pm    Post subject: Re: Writing to an ServerClientThread ? Reply with quote

"Johnny Hansen" <johnny (AT) jokiha (DOT) dk> wrote


Quote:
The client can send to the server and by means of a postmessage can
I send the data received from the client to the servers main-thread, and
this works just fine. My question is now, how do I send/write to the
client.


One way would be to simply pass the thread's TWinSocketStream in the message
itself, ie:

void __fastcall TMyThread::ClientExecute()
{
TWinSocketStream *Strm = new TWinSocketStream(ClientSocket, 5000);
//...
PostMessage(Application->MainForm->Handle, WM_SOMEMSG, 0,
reinterpret_cast<LPARAM>(Strm));
//...
delete Strm;
}

void __fastcall TForm1::WndProc(TMessage &Message)
{
if( Message.Msg == case WM_SOMEMSG )
{
//...
TWinSocketStream *Strm =
reinterpret_cast<TWinSocketStream*>(Message.LParam);
try
{
Strm->Write(YourData, YourDataize);
}
catch(const Exception&)
{
}
}
}

Alternatively, you can pass the ClientSocket pointer in the message itself,
and Then when the main thread needs to send data, it can pass that pointer
to the TServerSocket's GetClientThread() method to ensure that the socket is
still valid at the time, and if so then write to it with another
TWinSocketStream. For example:

void __fastcall TMyThread::ClientExecute()
{
//...
PostMessage(Application->MainForm->Handle, WM_SOMEMSG, 0,
reinterpret_cast<LPARAM>(ClientSocket));
//...
}

void __fastcall TForm1::WndProc(TMessage &Message)
{
if( Message.Msg == case WM_SOMEMSG )
{
//...
TServerClientWinSocket *Socket =
reinterpret_cast<TServerClientWinSocket*>(Message.LParam);
TServerClientThread *Thread =
ServerSocket1->Socket->GetClientThread(Socket);
if( Thread )
{
try
{
TWinSocketStream *Strm = new
TWinSocketStream(Thread->ClientSocket, 5000);
try {
Strm->Write(YourData, YourDataize);
}
__finally {
delete Strm;
}
}
catch(const Exception&)
{
}
}
}
}

Alternatively, you could expose a public Write() method in your thread class
that accesses the thread's own TWinSocketStream internally, and then simply
call that method when needed, ie:

class TMyThread : public TServerClientThread
{
private:
TWinSocketStream *Strm;
//...
public:
//...
int __fastcall WriteData(void *Buffer, int BufSize);
};

void __fastcall TMyThread::ClientExecute()
{
Strm = new TWinSocketStream(ClientSocket, 5000);
//...
PostMessage(Application->MainForm->Handle, WM_SOMEMSG, 0,
reinterpret_cast<LPARAM>(ClientSocket));
//...
delete Strm;
Strm = NULL;
}

int __fastcall TMyThread::WriteData(void *Buffer, int BufSize)
{
if( Strm )
return Strm->Write(Buffer, BufSize);
return -1;
}

void __fastcall TForm1::WndProc(TMessage &Message)
{
if( Message.Msg == case WM_SOMEMSG )
{
//...
TServerClientWinSocket *Socket =
reinterpret_cast<TServerClientWinSocket*>(Message.LParam);
TMyThread *Thread =
static_cast<TMyThread*>(ServerSocket1->Socket->GetClientThread(Socket));
if( Thread )
{
try {
Thread->WriteData(YourData, YourDataize);
}
catch(const Exception&)
{
}
}
}
}


Gambit



Back to top
Remy Lebeau (TeamB)
Guest





PostPosted: Mon Dec 29, 2003 6:24 pm    Post subject: Re: Writing to an ServerClientThread ? Reply with quote


"Martin James" <mjames_falcon (AT) dial (DOT) pipex.com> wrote


Quote:
OK I never had the source for these units & so always put in a
CS.when 2+ threads were writing. Obviously a redundant op!

TCustomWinSocket has its own internal CS.


Gambit



Back to top
Markku Uttula
Guest





PostPosted: Mon Dec 29, 2003 9:39 pm    Post subject: Re: Writing to an ServerClientThread ? Reply with quote

Martin James wrote:
Quote:
TWinSocketStream already does that internally, by calling the
Socket's Lock() and Unlock() methods when you call Read() and
Write().

OK I never had the source for these units & so always put in a
CS.when 2+ threads were writing. Obviously a redundant op!

Hmm. I could be totally wrong (I usually am), but that sounds not only
unneeded (as was stated that TWinSocketStream already has a
criticalsection) but also a possible lockup-point. Was there not
something seriously wicked about introducing two criticalsections at
the same time for the same job or have I just dreamt this once again
and it has nothing in it after all?

--
Markku Uttula



Back to top
Display posts from previous:   
Post new topic   Reply to topic    BorlandTalk.com Forum Index -> Delphi Internet Winsock All times are GMT
Page 1 of 1

 
Jump to:  
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


Powered by phpBB © 2001, 2006 phpBB Group
SEO toolkit © 2004-2006 webmedic.