🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Article View: borland.public.cppbuilder.internet.socket
Article #2905

Re: TWinSocketStream Read in BYTE buffer

#2905
From: Remy Lebeau (TeamB)
Date: Fri, 06 Jan 2006 19:42
184 lines
8432 bytes
"Maurice Anderson" <mauriceanderson@hotmail.com> wrote in message
news:43be3aac@newsgroups.borland.com...

> What chunk sizes does TClientSocket and TServerSocket use to
> send/receive bytes over the network? 4K, 8K, 16K, etc?

That is managed by the socket internally, and by the network hardware.  The
VCL does not control that.

> What is the transfer speed on say a 100 /mbits LAN?

That is entirely dependant on the speed of your code when sending/reading
data, as well as the amount of other traffic on the network at the time.
Speed will vary.

> What is the limit size in terms of Byes that that the Stream can hold?

TWinSocketStream does not hold any data.  It is just a passthrough to the
socket.  The socket itself has separate internal buffers for incoming and
outgoing data.  The VCL does not control those sizes, but you can use the
Win32 API getsockopt() function to retreive the sizes, and setsockopt() to
change the sizes.

> And once this limit is reached, what happens if I don't do a
> ClientSocket1->Socket->SendBuf(..);

The data remains buffered inside the socket.  Eventually, the inbound buffer
will fill up and the socket will not be able to accept any further data
until buffer space is cleared.  While the buffer is full, the sender will
likely receive an error, such as WSAENOBUFS (10055) or
WSAEWOULDBLOCK(10035).

> Using your ReadBuf/writeBuf methods at what point is the data
> considered transfered?

Inbound data is "transferred" as soon as it appears in your target buffer.
As soon as decide not to read any more data, you have finished transferring
everything.

Outbound data is "transferred" as soon as the socket accepts it.  The socket
will buffer the data internally and then transmit it over the network at its
leisure.  TWinSocketStream::Write() will return how many bytes the socket
accepted into its buffer.  There is no way to know when the data is actually
transmitted over the network.  The only thing you can do is assume that it
will be transmitted *at some point in time* if the socket accepted it, and
move on.

> For example on the Client end we have: ClientSocket1->Socket->SendBuf(..)
> and on the server we have: NumRead = Stream->Read(pBuf, BufSize);
> Once Socket->SendBuf returns, is the data considered 'sent' over or is it
> considered sent when we read from the Stream in: Stream->Read(pBuf...)?

On the client side, it is considered "sent" when SendBuf() returns,
indicating that the socket accepted the data into its internal buffer.

On the server side, it is considered "received" when the data appears in
pBuf.

> Does the whole 25 MB file already exists in the stream ready to be
> written to pBuf (and by extension fully copied from the client)

The buffers inside a socket are not large enough to hold that much data at
one time.

> is the ClientSocket holding it's horses ready to transmit another
> chunk as soon as NumRead = Stream->Read(pBuf, BufSize) is completed?

Yes.

> Pertaining to the sending/receiving of bytes in #4, how can I
> count said bytes transferred

That is what the return value of the stream's Read/Write() methods is for,
as are the return value of the socket's SendBuf/ReceiveBuf() methods.  The
return value is the number of bytes actually received/accepted at that
particular moment.

> What is the most efficient BYTE buffer size to allocate for the
> reading and writing functions for small, medium and large files?

That is entirely up to you to choose.  Like I told you earlier, the code I
gave you does not care what sizes are used.  What you can do, however, is
use get/setsockopt() to have your buffer sizes match the socket's internal
buffer sizes.

> Currently, I have BYTE rbuf[256];, what happens if I set it to
> say: BYTE rbuf[1024], etc?

All that does is lets more data be buffered in memory at a time.  Of course,
the larger the buffer, the more space that is available when receiving data
from a socket, which will likely allow the socket to clear its incoming
buffer more quickly.  But the size of the buffer for outgoing data is  still
limited to the size of the socket's internal outgoing buffer.

> How can I get the Client to open its own thread for sending data?

TClientSocket is not a threaded component at all.  You will have to manage
the thread yourself manually.  Derive a class from TThread and override its
Execute() method.  Pass the TClientSocket's Socket property to the thread,
such as a parameter to the thread's constructor:

    class TClientThread : public TThread
    {
    private:
        TCustomWinSocket *FSocket;
        TWinSocketStream *FStream;
    protected;
        virtual void __fastcall AfterConstruction();
        virtual void __fastcall Execute();
    public:
        __fastcall TClientThread(TCustomWinSocket *ASocket);
        __fastcall ~TClientThread();
    };

    __fastcall TClientThread::TClientThread(TCustomWinSocket *ASocket)
        : TThread(true)
    {
        FSocket = ASocket;
        FStream = new TWinSocketStream(FSocket, 5000);
    }

    void __fastcall TClientThread::AfterConstruction()
    {
        Resume();
    }

    __fastcall TClientThread::~TClientThread()
    {
        delete FStream;
    }

    void __fastcall TClientThread::Execute()
    {
        while( (!Terminated) && (FSocket->Connected) )
        {
            // use FStream as needed ...
        }
    }

Then you can start the thread after you have connected the TClientSocket to
the server:

    TClientThread *FThread = NULL;

    void __fastcall TForm1::ClientSocket1Connect(TObject *Sender,
TCustomWinSocket *Socket)
    {
        FThread = new TClientThread(Socket);
    }

    void __fastcall TForm1::ClientSocket1Disconnect(TObject *Sender,
TCustomWinSocket *Socket)
    {
        if( FThread )
        {
            FThread->Terminate();
            FThread->WaitFor();
            delete FThread;
            FThread = NULL;
        }
    }

> I use TServerClientThread to receive connections, but how can
> I use it to open a connection to a server and use it to transmit?

You cannot use TServerClientThread on the client side.  It only works on the
server side.  Use TThread instead on the client side, as shown above.

> How can I track each individual connection received on the server
> to say get the source IP address?

TServerSocket has ActiveConnections and Connections[] properties available.
Or else you can maintain your own list manually, such as by grabbing the IP
address at the beginning of the TServerClientThread's ClientExecute() method
and then add it to your own thread-safe list somewhere, and then remove the
address at the end of ClientExecute().

> How an I convert a BYTE to binary 1s and 0s?

It is already stored in a binary format.  Everything in memory is binary.


Gambit
Technical Details
Message-ID: <43bec7f0$1@newsgroups.borland.com>
Path: arc1-ca.pugleaf.net!g2news1.google.com!news2.google.com!news4.google.com!border1.nntp.dca.giganews.com!nntp.giganews.com!nx01.iad01.newshosting.com!newshosting.com!news-out.newsfeeds.com!propagator2-sterling.newsfeeds.com!in.nntp.be!caladan.landsraad.net!newsgroups.borland.com!not-for-mail
References: <43ac3d34$1@newsgroups.borland.com> <43ac6028$1@newsgroups.borland.com> <43acc4c5$1@newsgroups.borland.com> <43ae5b51$1@newsgroups.borland.com> <43aeebe1$1@newsgroups.borland.com> <43aef70e$1@newsgroups.borland.com> <43af06d7$1@newsgroups.borland.com> <43b252fa$1@newsgroups.borland.com> <43b43a5a$1@newsgroups.borland.com> <43b45550$1@newsgroups.borland.com> <43b5a868$1@newsgroups.borland.com> <43b9b1b0$2@newsgroups.borland.com> <43bcedb2$1@newsgroups.borland.com> <43bd69da$1@newsgroups.borland.com> <43be3aac@newsgroups.borland.com>

Show Full Headers
Complete Article Headers
X-Google-Thread: 11508e,74cdc31c66b3abd9
X-Google-Attributes: gid11508e,public
X-Google-Language: ENGLISH,ASCII-7-bit
From: "Remy Lebeau \(TeamB\)" <no.spam@no.spam.com>
Newsgroups: borland.public.cppbuilder.internet.socket
References: <43ac3d34$1@newsgroups.borland.com> <43ac6028$1@newsgroups.borland.com> <43acc4c5$1@newsgroups.borland.com> <43ae5b51$1@newsgroups.borland.com> <43aeebe1$1@newsgroups.borland.com> <43aef70e$1@newsgroups.borland.com> <43af06d7$1@newsgroups.borland.com> <43b252fa$1@newsgroups.borland.com> <43b43a5a$1@newsgroups.borland.com> <43b45550$1@newsgroups.borland.com> <43b5a868$1@newsgroups.borland.com> <43b9b1b0$2@newsgroups.borland.com> <43bcedb2$1@newsgroups.borland.com> <43bd69da$1@newsgroups.borland.com> <43be3aac@newsgroups.borland.com>
Subject: Re: TWinSocketStream Read in BYTE buffer
Date: Fri, 6 Jan 2006 11:42:21 -0800
Lines: 186
X-Priority: 3
X-MSMail-Priority: Normal
X-Newsreader: Microsoft Outlook Express 6.00.2800.1409
X-MimeOLE: Produced By Microsoft MimeOLE V6.00.2800.1409
NNTP-Posting-Host: 68.69.17.41
Message-ID: <43bec7f0$1@newsgroups.borland.com>
X-Trace: newsgroups.borland.com 1136576496 68.69.17.41 (6 Jan 2006 11:41:36 -0700)
Path: arc1-ca.pugleaf.net!g2news1.google.com!news2.google.com!news4.google.com!border1.nntp.dca.giganews.com!nntp.giganews.com!nx01.iad01.newshosting.com!newshosting.com!news-out.newsfeeds.com!propagator2-sterling.newsfeeds.com!in.nntp.be!caladan.landsraad.net!newsgroups.borland.com!not-for-mail