Newsgroups : Borland : borland.public.delphi.internet.winsock : 2007 Sep : Re: File Transfers - Indy9

www.cryer.info
Managed Newsgroup Archive

Re: File Transfers - Indy9

Subject:Re: File Transfers - Indy9
Posted by:"Remy Lebeau (TeamB)" (no.spam@no.spam.com)
Date:Wed, 26 Sep 2007 22:14:45

"Jamie Dale" <jamie.dale@yahoo.com> wrote in message
news:46f58cfa@newsgroups.borland.com...

> Sounds simple enough, but when I send the entire file
> using SendStream() I'm stuffed!

Then you are using it wrong.  SendStream() works fine in the scenerio I have
described.

> Thats because SendStream doesnt break it down into blocks

Yes, it does.  I am guessing you have never looked at Indy's source code,
right?

But that is irrelevant, because the server does not need to know or care
about that.  TCP sockets are byte streams.  The server does not need to read
the data the same way it was sent.  If the sending client sends the file
size before the actual file data, then the server will know how many bytes
to expect ahead of time, and can read the data using its own blocks, reading
each one individually and forwarding it to the target as needed, for
example:

    procedure TForm1.TCPServerExecute(AThread: TIdPeerThread);
    var
        FileSize: Integer;
        BufSize: Integer;
        buffer: array[0..1023] of Byte;
    begin
        FileSize := AThread.Connection.ReadInteger;
        while FileSize > 0 do
        begin
            BufSize := min(FileSize, 1024);
            AThread.Connection.ReadBuffer(buffer[0], BufSize);
            // send buffer up to BufSize bytes to target client ...
            Dec(FileSize, BufSize);
        end;
    end;

Of course, you will have to expand on that logic in other to handle other
data from the sending client (commands, etc), but that will give you
something to start with.

> or at least it doesn't allow access to them

Yes, it does.  See above.

> unless I edit the Indy source.

You don't need to edit anything in the source.  You simply need to change
the way you are reading the data on the server side.

> Therefore, while the Senders AThread is recieving the file, how
> am I supposed to initiate another thread to send it?

You don't need to.

> The Tx'ing thread would need to read filestream data from
> the RX'ing thread which is still using the filestream!

Then don't try to forward it all at one time.  That way, the Rx'ing thread
can do other things in between each block.

If you really want everything to go through the server and not use secondary
sockets, then I suggest you give every packet, including the transfer
packets, a header that describe the type and size of each block.  That way,
the reading thread can then read a block, forward it to the appropriate
handler for processing, read the next block, adn so on.  That is the only
way you can reliably mix different types of communications (commands,
transfers, etc) over a single socket connection.

> When the main client receives a request for a file transfer, it opens
> another form which in turn has it's own client & thread to use it.

There is nothing wrong with doing that.

> Yes, I clearly understood this principle already. Thats why I want
> to relay the file through the server so that the clients literally only
need
> to make an outbound connection using TIdTCPClient.

That is not very efficient, though.  And besides, the more clients are
wanting to transfer through the server, the more overhead the server has.
Why do you think every modern IM system has adopted direct-client
communications?  It reduces the server's workload, and provides safer and
more efficient communications between clients.  The fewer points of
redirection you have, the better.

> That way I don't need to worry about firewalls, routers, etc.

You have to worry about those anyway.  They are too common nowadays to
ignore.  And the more data you try to push over a single connection, the
slower that connection is going to perform overall.  So it is better to keep
the server communications as simple as simple and do the client-to-client
communcations separate.

> True, but hear me out as there are ways of calculating the data!

Don't even go there.  Since you need access to the data anyway, and you
(should) know ahead of time what you need to read and how, then the OnWork
events are not going to gain you ANYTHING useful for your data handling.
They are only going to make your code more complicated than it needs to be,
so just ignore them on the server side.

> The idea was that the OnWork event could calculate how much
> data has been received and then, it could read that data from the
> FileStream and send it on to the other client.

That is not how the OnWork events operate.  And besides, as you can see in
the example above, it is completely unnecessary anyway because the code
already knows how much data was read - because it was the one reading it!

> Do you have any other suggestions please Remy?

Rethink your design.  Your are approaching everything all wrong.


Gambit

Replies:

none

In response to:

www.cryer.info
Managed Newsgroup Archive