🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Thread View: borland.public.cppbuilder.internet.socket
6 messages
6 total messages Started by Maurice Anderson Mon, 19 Dec 2005 22:50
TWinSocketStream and threading
#3014
Author: Maurice Anderson
Date: Mon, 19 Dec 2005 22:50
42 lines
2396 bytes
I am able to send data to a test server across the network using the code
below from the help file.  My Question is, (1) how can I modify the server
code below to use pStream->ReadBuffer(Buffer, x) instead of
pStream->Read(Buffer, 10). (2) If I want to send binary data such as a file,
can I still use Read or must I use ReadBuffer?  (3) How can I modify it to
send data to a client? (4) Once the data is read on the server, how can I
send it over to the main thread for processing(I know I should use
sycnhronize some way, but how)? Is that even wise? (5) Is it wise or
necesarry to use a seperate thread on the client side to send and receive
data as well?

  while (!Terminated && ClientSocket->Connected)
  {
    try
    {
      pStream = new TWinSocketStream(ClientSocket, 60000);

      try
      {
        memset(Buffer, 0, 10); // initialize the buffer
        // give the client 60 seconds to start writing
        if (pStream->WaitForData(60000))
        {
          test = sizeof(pStream);
          if (pStream->Read(Buffer, 10) == 0)
            ClientSocket->Close();           // close the connection
          // now process the request  ...
           Form1->Memo1->Lines->Add((char *)Buffer);
        }
        else
          ClientSocket->Close(); // if client doesn't start, close
      }
      __finally
      {
        delete pStream;
      }
    }
    catch (Exception &E)
    {
      HandleException();
    }
  }
Re: TWinSocketStream and threading
#3015
Author: Remy Lebeau (TeamB)
Date: Tue, 20 Dec 2005 00:29
83 lines
4203 bytes
"Maurice Anderson" <mauriceanderson@hotmail.com> wrote in message
news:43a738ea$1@newsgroups.borland.com...

> how can I modify the server code below to use
> pStream->ReadBuffer(Buffer, x) instead of
> pStream->Read(Buffer, 10).

For what purpose exactly?  What exactly do you want the code to do?  Please
be more specific.

> If I want to send binary data such as a file, can I still use
> Read or must I use ReadBuffer?

The stream's ReadBuffer() method calls the Read() method internally.
Everything ultimately goes through Read().  The only thing ReadBuffer() does
extra is to throw an exception if the amount of data received is not the
same as the amount that was requested.  If you continue to use Read()
directly, then you have to check the return value to know how much data was
actually received.

> How can I modify it to send data to a client?

Simply call the stream's Write() or WriteBuffer() method when desired.

> Once the data is read on the server, how can I send it over to the
> main thread for processing

That is up to you.  There are many techniques available for inter-thread
communication - window/thread messages, shared memory protected with a
synchronization object, etc.  What you use is up to you based on your chosen
code design.

> I know I should use sycnhronize some way, but how? Is that even wise?

Using the TThread::Synchronize() method is one possible way to do it, yes.

> Is it wise or necesarry to use a seperate thread on the client side to
> send and receive data as well?

That depends on the client's particular design, but it is not a requirement.
The server has no concept of how the client accesses its local endpoint for
the socket, and vice versa.  The decision whether or not to use threads has
nothing to do with the underlying communication over the socket, only in how
the socket is managed from a higher-level application perspective.

>   while (!Terminated && ClientSocket->Connected)
>   {
>     try
>     {
>       pStream = new TWinSocketStream(ClientSocket, 60000);

I would suggest moving the creation of the stream outside of the while()
block so that the stream instance can be re-used over and over for the
lifetime of the thread.  There's no point in creating and destroying
resources repeatedly.

>           test = sizeof(pStream);

Why are you doing that?  You are retreiving the compiled size of a memory
pointer, not the run-time size of the stream contents.  A memory pointer is
always 4 bytes on a 32-bit system.

>           // now process the request  ...
>            Form1->Memo1->Lines->Add((char *)Buffer);

That is not thread-safe.  You need to use TThread::Synchronize() in order to
access the GUI safely.  Either directly, or via the TIdSync class of Indy.

>     catch (Exception &E)

You should always catch exceptions by 'const' references:

    catch (const Exception &E)

>       HandleException();

I do not recommend using that.  All it basically does is displays a popup
message for the exception.  Not only does that block the worker thread but
the main thread as well.  You should handle the exception in your own code.


Gambit
Re: TWinSocketStream and threading
#3016
Author: Maurice Anderson
Date: Tue, 20 Dec 2005 01:43
23 lines
1814 bytes
>For what purpose exactly?  What exactly do you want the code to do?  Please
be more specific.

I am trying to create a simple chat server that can send both text and
files.

> I would suggest moving the creation of the stream outside of the while()

Good point.

>  test = sizeof(pStream); > Why are you doing that?

I mis-understood the nature of the Count option in ReadBuffer.  I thought
doing a sizeof would somehow give me the the number of bytes received.  On
that note, (1)how can I determine how many bytes are being receieved from
the client?  (2)How can I tell the server whether the data is simple text
being received or binary data such as a jpg file?

> You should always catch exceptions by 'const' references:

What's the difference?

Thanks
Re: TWinSocketStream and threading
#3017
Author: Remy Lebeau (TeamB)
Date: Tue, 20 Dec 2005 03:27
50 lines
3466 bytes
"Maurice Anderson" <mauriceanderson@hotmail.com> wrote in message
news:43a7619b$1@newsgroups.borland.com...

> I am trying to create a simple chat server that can send
> both text and files.

The code you have shown so far is much too simplictic for that.  You need to
beef up your communication quite a bit in order for the client and server to
actually tell each other what to do and when.

> how can I determine how many bytes are being receieved from the client?

There are a number of ways to do that.  At its most basic, you can use the
ClientSocket->ReceiveLength() method.  That will tell you how much data has
actually been received into the socket's internal buffer that can be read
without blocking.  But that is not reliable enough.  For starters, it does
not tell you how much data you should be expecting to arrive in the first
place.  For that, you have two additional options:

1) prefix the data with its length.  Read the length first, then you know
how many more bytes to read.  Keep reading until that many, and only that
many, bytes have actually been read.  Then you can process what you have
read.

2) append a unique byte/sequence to the end of the data.  Use a
byte/sequence that is quaranteed to never appear in the data.  Then you
continuous read until that byte/sequence is encontered.  Then you can
process what you have read, and buffer what is remaining and attach it to
the next reading.

> How can I tell the server whether the data is simple text
> being received or binary data such as a jpg file?

Prefix the data with a fixed-length header that describes what the data is.
At the very least, include a value that specifies whether the data is text
or file data.  The data can then include multiple values inside of it, each
with a fixed or specified length, that provide parameters (username,
password, text message, file name, etc) for the various commands that you
then implement by using the header.  Only then can you decide what to do
with the data.  This plays into #1 above, where you could include the data
length as part of the header.  So, you would read the header first, then
read the specified number of bytes and process the overall data based on the
rest of the header values.

Go to http://www.deja.com and do a search through the newsgroup archives.
Numerous discussions and examples on this topic have been posted before.


Gambit
Re: TWinSocketStream and threading
#3024
Author: Maurice Anderson
Date: Wed, 21 Dec 2005 08:58
14 lines
1555 bytes
> Go to http://www.deja.com and do a search through the newsgroup archives.
> Numerous discussions and examples on this topic have been posted before.
>
>
> Gambit

Thanks Remy, for the insight.  One last question:  how could I send a simple
PUT command with HTTP using TWinSocketStream?  As in sending a simple HTTP
command with the header, version, etc/  I have been looking around on the
web but it's still not clear to me.  Lets say I wanted to PUT a file.txt
anywhere on webserver www.nowhere.com.  I know how to prepare the buffer,
etc.  I just need the format or fields..

Thanks
Re: TWinSocketStream and threading
#3025
Author: Remy Lebeau (TeamB)
Date: Wed, 21 Dec 2005 18:24
22 lines
1832 bytes
"Maurice Anderson" <mauriceanderson@hotmail.com> wrote in message
news:43a91921$1@newsgroups.borland.com...

> how could I send a simple PUT command with HTTP using TWinSocketStream?

HTTP is a complex protocol to implement manually.  I strongly suggest that
you switch over to a real HTTP component, such as the HTTP client in either
Indy (http://www.indyproject.org) or ICS (http://www.overbyte.be).

> I have been looking around on the web but it's still not clear to me.

Did you try reading the official specifications for the HTTP protocol yet?

    Hypertext Transfer Protocol - HTTP/1.0
    http://www.ietf.org/rfc/rfc1945.txt

    Hypertext Transfer Protocol - HTTP/1.1
    http://www.ietf.org/rfc/rfc2616.txt


Gambit
Thread Navigation

This is a paginated view of messages in the thread with full content displayed inline.

Messages are displayed in chronological order, with the original post highlighted in green.

Use pagination controls to navigate through all messages in large threads.

Back to All Threads