🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Thread View: borland.public.cppbuilder.internet.socket
11 messages
11 total messages Started by Paul at NCF Sun, 11 Feb 2007 09:50
Indy 9 TrivialFTP Questions:
#1350
Author: Paul at NCF
Date: Sun, 11 Feb 2007 09:50
67 lines
2906 bytes
Hi,

I'm trying to get Trivial FTP working and there are a few questions I have:

1)  I presume the transfer only uses the standard UDP checksum to check the 
integrity of the payload?

2)  It cannot continue (resume) from a previous transfer

3)  This is a bit of a general question?  What is the server bindings 
property for, and where can I find more info or examples on its use?

4)  I've got a sample server and client working yesterday (local test 
127.0.0.1), but I noticed that there seems to be a problem with file access 
on the server side when putting files - clicking button 1 twice too quickly. 
I figured it must be timing in that the server still has the file open when 
the next request comes in for the same file.  So I put in a 'delay' by 
putting two files instead, and disabled the button whilst doing the puts. 
But I still get the exception if I press too quickly after its re-enabled. 
Any clues or guidence?

Regards,

Paul

void __fastcall TForm1::Button1Click(TObject *Sender)
{
    try
    {
        CopyFile( "CopyClientFile.Txt", "Client1File.Txt", false );
        CopyFile( "CopyClientFile.Txt", "Client2File.Txt", false );

        Button1->Enabled = false;
        IdTrivialFTP->Put("Client1File.Txt", "Server1File.Txt" );
        IdTrivialFTP->Put("Client2File.Txt", "Server2File.Txt" );
        Button1->Enabled = true;
    }
    catch (...)
    {
    }
}

void __fastcall TForm1::IdTrivialFTPServerWriteFile(TObject *Sender,
      AnsiString &FileName, const TPeerInfo &PeerInfo, bool &GrantAccess,
      TStream *&AStream, bool &FreeStreamOnComplete)
{
    bool freeon = false;
    bool access = false;

    // [TBD]
    // check Peer in known list
    // check File access
    // etc
    access = true;

    // set up requirements
    if (access)
    {
        TFileStream * f = new TFileStream(FileName, fmCreate | 
fmShareExclusive);
        AStream = f;
        freeon = true;
    }

    FreeStreamOnComplete = freeon;
    GrantAccess = access;
}
Re: Indy 9 TrivialFTP Questions:
#1352
Author: Remy Lebeau (TeamB)
Date: Sun, 11 Feb 2007 21:57
27 lines
1900 bytes
"Paul at NCF" <notplmacca@clara.co.uk> wrote in message
news:45cee6cb@newsgroups.borland.com...

> I presume the transfer only uses the standard UDP checksum to
> check the integrity of the payload?

TIdTrivialFTP does not perform any checksum validations.

> It cannot continue (resume) from a previous transfer

There are no resume capabilities available in the TFTP protocol in the
first place.  When uploading a file, the transfer fails if the file
already exists.  When downloading a file, the transfer always begins
at the beginning of the file.  If you need resuming capabilities, then
you need to use the TCP-based FTP protocol instead of the UDP-based
TFTP protocol.  TFTP is designed for simplicity, not features.

> What is the server bindings property for

The same as in TIdTCPServer.  Each Binding tells the server which
local IP/Port to listen on.  If there are multiple NIC adapters
installed, the server can work with clients on multiple networks at a
time.


Gambit
Re: Indy 9 TrivialFTP Questions:
#1361
Author: Paul at NCF
Date: Mon, 12 Feb 2007 08:51
13 lines
1501 bytes
Thanks for the clarifications.  Any ideas on the last question as to why the 
2nd iteration of the put operation fails?

In my tests so far I haven't added anything to bindings and it seems to 
work.  Is it an optional field? Does it mean that it uses the default 
network adaptor if unspecified?

Paul

> The same as in TIdTCPServer.  Each Binding tells the server which
> local IP/Port to listen on.  If there are multiple NIC adapters
> installed, the server can work with clients on multiple networks at a
> time.
Re: Indy 9 TrivialFTP Questions:
#1362
Author: Remy Lebeau (TeamB)
Date: Mon, 12 Feb 2007 09:02
21 lines
1624 bytes
"Paul at NCF" <notplmacca@clara.co.uk> wrote in message
news:45d02a9b@newsgroups.borland.com...

> Any ideas on the last question as to why the 2nd iteration
> of the put operation fails?

I cannot answer that.  If I had any ideas, I would have mentioned
them.

> In my tests so far I haven't added anything to bindings and it seems
> to work.  Is it an optional field? Does it mean that it uses the
default
> network adaptor if unspecified?

If no bindings are provided, a default one is created when the server
is activated.  The default binding uses an empty IP, which means it
listening on all available adapters.


Gambit
Re: Indy 9 TrivialFTP Questions:
#1364
Author: Paul at NCF
Date: Mon, 12 Feb 2007 22:11
7 lines
1249 bytes
Thanks.

> If no bindings are provided, a default one is created when the server
> is activated.  The default binding uses an empty IP, which means it
> listening on all available adapters.
>
> Gambit
Re: Indy 9 TrivialFTP Questions:
#1365
Author: Paul at NCF
Date: Tue, 13 Feb 2007 08:09
18 lines
1749 bytes
Hi Remy,

Two further questions, hopefully quick for someone in the know:

1)  Is the PUT client operation asyncronous?  I've create a client app and 
server app, and in my example I have the client do two calls for Put, back 
to back.  On the server, the logging shows two Write File events, followed 
by two transfer complete events?  I have the server property set to 
threaded.

2)  What type of thread safe access do I need to put in the server event 
handles for read, write, transfer complete (for multiple client 
connections)?  ie, just for my handling of the component and other misc 
data, or to help the server component itself.

Thanks

Paul 
Re: Indy 9 TrivialFTP Questions:
#1366
Author: Remy Lebeau (TeamB)
Date: Tue, 13 Feb 2007 09:59
34 lines
2338 bytes
"Paul at NCF" <notplmacca@clara.co.uk> wrote in message
news:45d17236@newsgroups.borland.com...

> Is the PUT client operation asyncronous?

No, just like most everything else in Indy.  Put() does not exit until
the transfer is fully completed, or an error occurs.

> I've create a client app and server app, and in my example I
> have the client do two calls for Put, back to back.  On the server,
> the logging shows two Write File events, followed by two transfer
> complete events?

And the problem is...?  That is how it is supposed to work.  When
TIdTrivialFTPServer receives a request for a file, it triggers the
OnReadFile or OnWriteFile event to obtain the appropriate TStream
object for the file, and then reads/writes all of the file data until
finished, at which time the OnTransferComplete event is triggered.

> What type of thread safe access do I need to put in the server event
> handles for read, write, transfer complete (for multiple client
> connections)?

That depends on how you are accessing the local files to begin with.
You have to make sure that you are providing your TStream objects in a
thread-safe manner.  If you have two clients accessing the same file
at the same time, that would be bad.

And in any case, the OnTransferComplete event handler is always
synchronized with the main thread.


Gambit
Re: Indy 9 TrivialFTP Questions:
#1370
Author: Paul at NCF
Date: Tue, 13 Feb 2007 20:25
26 lines
2083 bytes
Hi,

If syncronous, and my client app has put("f1.tx") followed by put("f2.txt"), 
then I would expect the server log to show:
"write", "transfer complete"
"write", "transfer complete"
but I get
"write", "write",
"transfer complete", "transfer complete"

eg.
2007-02-13 08:01:24:0554 : IdTrivialFTPServerWriteFile
2007-02-13 08:01:24:0995 : IdTrivialFTPServerWriteFile
2007-02-13 08:01:26:0497 : IdTrivialFTPServerTransferComplete
2007-02-13 08:01:26:0968 : IdTrivialFTPServerTransferComplete

Paul


"Remy Lebeau (TeamB)" <no.spam@no.spam.com> wrote in message 
news:45d18c50$1@newsgroups.borland.com...
> And the problem is...?  That is how it is supposed to work.  When
> TIdTrivialFTPServer receives a request for a file, it triggers the
> OnReadFile or OnWriteFile event to obtain the appropriate TStream
> object for the file, and then reads/writes all of the file data until
> finished, at which time the OnTransferComplete event is triggered.
Re: Indy 9 TrivialFTP Questions:
#1371
Author: Remy Lebeau (TeamB)
Date: Tue, 13 Feb 2007 21:05
25 lines
1841 bytes
"Paul at NCF" <notplmacca@clara.co.uk> wrote in message
news:45d21eae@newsgroups.borland.com...

> If syncronous, and my client app has put("f1.tx") followed by
put("f2.txt"),
> then I would expect the server log to show:
> "write", "transfer complete"
> "write", "transfer complete"

That is exactly what happens.  It can't happen any other way, as the
data for the second file is not transmitted until the first file
finishes.  Also, each UDP packet receives an acknowledgement packet in
reply, so the packets for the two transfers cannot be transmitted out
of order, either.

> but I get
> "write", "write",
> "transfer complete", "transfer complete"

The only way that is possible is if you have two separate clients
uploading at the same time.


Gambit
Re: Indy 9 TrivialFTP Questions:
#1378
Author: Paul at NCF
Date: Wed, 14 Feb 2007 09:01
72 lines
4104 bytes
Hi

> That depends on how you are accessing the local files to begin with.
> You have to make sure that you are providing your TStream objects in a
> thread-safe manner.  If you have two clients accessing the same file
> at the same time, that would be bad.


Yes, I will put exclusive access on write and read, so client retries will 
be required if this happens.

> And in any case, the OnTransferComplete event handler is always
> synchronized with the main thread.


From your other email, no there is only one (test) client  I haven't got to 
running multiples yet, keeping it simple until I understand how it all 
works.

Maybe the syncronize is why the sequence looks strange in the log.  But see 
the overlapped the trace log from the two applications.  The lines with 
"IdTrivialFTPServer" are the server app trace, the others from the client 
trace.  The put completes, but the server end seems to respond with transfer 
complete some time after the write has finished (1.5s), which seems a long 
time, and this probably explains why my client repeat 'put' sequence fails 
if it happens too quickly after the last.

2007-02-14 08:12:36:0067 : Client1File Write
2007-02-14 08:12:36:0067 : Begin Event
2007-02-14 08:12:36:0077 : IdTrivialFTPServerWriteFile (Client1File)
2007-02-14 08:12:36:0077 : Work Event
....
2007-02-14 08:12:37:0940 : Work Event
2007-02-14 08:12:37:0940 : End Event
2007-02-14 08:12:37:0940 : Client2File Write
2007-02-14 08:12:37:0940 : IdTrivialFTPServerWriteFile (Client2File)
2007-02-14 08:12:37:0940 : Begin Event
2007-02-14 08:12:37:0950 : Work Event
.....
2007-02-14 08:12:39:0432 : Work Event
2007-02-14 08:12:39:0442 : IdTrivialFTPServerTransferComplete (Client1File)
2007-02-14 08:12:39:0442 : Work Event
....
2007-02-14 08:12:39:0822 : Work Event
2007-02-14 08:12:39:0822 : End Event
2007-02-14 08:12:41:0324 : IdTrivialFTPServerTransferComplete (Client2File)



However, just looked at the code for TFTP server (keep forgetting I have 
it!).  The transfer complete is done when the file write thread is 
destroyed.  The file write thread has a default receive timeout of 1.5s.  So 
it looks like the server is timing out on the write operation.  Reading 
further, the rfc1350 says:

   The end of a transfer is marked by a DATA packet that contains
   between 0 and 511 bytes of data (i.e., Datagram length < 516).  This
   packet is acknowledged by an ACK packet like all other DATA packets.
   The host acknowledging the final DATA packet may terminate its side
   of the connection on sending the final ACK.  On the other hand,
   delaying is encouraged.  This means that the host sending the final
   ACK will wait for a while before terminating in order to retransmit
   the final ACK if it has been lost.

So looks like normal behaviour!  So perhaps the client response to a write 
failure is to wait 1.5s (or so) before retrying the file again.

Thanks.

Regards,

Paul
Re: Indy 9 TrivialFTP Questions:
#1288
Author: Paul at NCF
Date: Fri, 16 Feb 2007 08:50
40 lines
2928 bytes
Hi Remy,

> The transfer complete is done when the file write thread is destroyed. 
> The file write thread has a default receive timeout of 1.5s.  So it looks 
> like the server is timing out on the write operation.  Reading

I've been looking through the code for the server and client for these 
components in Indy9.  Do you think it would be better for the server to 
release the file handle when the last block has been read/written, and for 
the server to just keep re-transmitting the last block, or process the last 
ack?  This way the file handle is released early for use, not sure if the 
transfer complete should also be called then too?  Any impacts?

I've determined the following behaviour from the code:

Server:

1)  The receive timeout is the same regardless of buffer size (1.5s).  The 
server has a three retry receive timeout limit.
2)  The server waits 4.5s in total if nothing is received (if not processing 
last block).  Otherwise its 1.5s.
3)  The server retransmits the previous DATA or ACK block if it receive 
timeouts.
4)  If the client misbehaves when reading and sends an ACK with the wrong 
block, the server will continuously re-transmit the previous block. Or if 
the server and client get out of sync (eg. due to buggy implementations).
5)  If the client misbehaves when writing and sends a block with an 
unexpected block number, the server will continuously re-transmit the 
previous ACK. Or if the server and client get out of sync (eg. due to buggy 
implementations).

Client:

1)  Any receive timeout terminates transfer.
2)  Only the server checks the block sequences, the client assumes the 
server block numbers are always correct, and only checks that they increase.

Regards,

Paul
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