Coder Social home page Coder Social logo

Comments (36)

FanDjango avatar FanDjango commented on June 14, 2024 1

By the way, I don't want to complicate things, and I'm sure this has probably been discussed before, but is there a reason why Config.NoopInterval only runs during an active data transfer? Wouldn't it be better if it ran as a background thread, sending NOOPs every Config.NoopInterval milliseconds after any non-NOOP traffic on the control channel, whether there's a transfer in progress or not? It's entirely possible I'm missing something because, as I said, I'm really not familiar with the codebase.

This is on my TODO list, marked "major".

from fluentftp.

FanDjango avatar FanDjango commented on June 14, 2024 1

Ok. I like it too.

from fluentftp.

FanDjango avatar FanDjango commented on June 14, 2024

Unfortunately the FtpClient IsConnected and IsAuthenticated

I have noticed this too, in the course of testing and experimenting. The underlying socket layer on the client is simply not notified of tcp take-downs, sometimes even the server does not get the chance to FIN or RST the connection correctly (think: pulling the plug, for example). Firewalls are another example.

That's actually what socket.poll is for. You can only detect such non-connected states by an active attempt to send something and then to accept a possibly vexing long wait until timout.

We try not to poll to often. Perhaps we should include an option to poll before each and every command. And an intermediate method: poll before every command if the last command is longer than n minutes ago?

Your idea to externalise such a query is also certainly useful for those who like to keep full control in their own app.

from fluentftp.

FanDjango avatar FanDjango commented on June 14, 2024

Unfortunately the FtpClient IsConnected and IsAuthenticated properties fail to detect this state.

It is entirely the fault of "IsConnected". If this were "false", "IsAuthenticated" would also return "false".

An unreliable "IsConnected" causes a number of subsequent failures.

from fluentftp.

FanDjango avatar FanDjango commented on June 14, 2024

perhaps a method called TestConnectionHealth()

useful for those who like to keep full control in their own app.

You would put this into a regular timer based checker, under control of your app. FluenFTP as a library currently has no provision for spwaning a timer based task to do such things. Perhaps this would also be an idea. It would also simplify NOOP handling.

from fluentftp.

FanDjango avatar FanDjango commented on June 14, 2024

I have made a small preliminary modification where I would be curious as to your experience on "lost / unresponsive" control connections. Is there any way you might pick up the current master in this repo and play with that? And in the case of "connection in a sort-of half-open state" I would like to see a verbose log?

from fluentftp.

MisterSausage avatar MisterSausage commented on June 14, 2024

Thanks for looking into this so quickly! Yep, I'll certainly take the master and give it a try - I'll do my best to get back to you within about 36 hours.

from fluentftp.

robinrodricks avatar robinrodricks commented on June 14, 2024

I am in favour of an IsStillConnected method. Starting with Is to make it more discoverable via VS intellisense drop downs.

from fluentftp.

robinrodricks avatar robinrodricks commented on June 14, 2024

Committed an IsStillConnected into master and build given below, can you check @MisterSausage ? You will find @FanDjango 's latest changes here too.

Test build: FluentFTP.48.1.0-BETA1.zip

from fluentftp.

FanDjango avatar FanDjango commented on June 14, 2024

@robinrodricks

Cannot work. You are calling Noop(), which

  1. Will or will not issue a Noop command depending on NoopInterval and how long ago the last Noop was issued
  2. Does not get the reply for good reasons. ** I know you are calling GetReply, I wanted to mention this for completeness

I was working on this already.

This was a little too quick off the mark.

from fluentftp.

FanDjango avatar FanDjango commented on June 14, 2024

We could simply temporarily set the NoopInterval and reset the time, then restore the current NoopInterval, how about that?

from fluentftp.

FanDjango avatar FanDjango commented on June 14, 2024

I am currently testing this right now:

		public bool IsStillConnected() {
			bool connected = false;
			if (IsConnected && IsAuthenticated) {
				int saveNoopInterval = Config.NoopInterval;
				LastCommandTimestamp = DateTime.MinValue;
				Config.NoopInterval = 1;
				if (Noop()) {
					if (GetReply().Success) {
						connected = true;
					}
				}
				Config.NoopInterval = saveNoopInterval;
			}
			return connected;
		}

and it works. I'll commit this to master.

from fluentftp.

MisterSausage avatar MisterSausage commented on June 14, 2024

Thank you @FanDjango and @robinrodricks for your work on this, and so quickly too!

A few things to repond to, so I'll do them one at a time in different comments, to try to keep things tidy.

from fluentftp.

MisterSausage avatar MisterSausage commented on June 14, 2024

I have made a small preliminary modification where I would be curious as to your experience on "lost / unresponsive" control connections. Is there any way you might pick up the current master in this repo and play with that? And in the case of "connection in a sort-of half-open state" I would like to see a verbose log?

Using the latest master as of about an hour ago, I've not seen any changes referenced here. Here's the log (I couldn't find anything in the API to make it more verbose, so let me know if there's anything I can do in that regard):

# Connect(False)
Status:   FluentFTP 48.0.3.0(.NET 6.0)
Status:   Connecting to IP #1= ***:21
Status:   Waiting for a response
Response: 220---------- Welcome to Pure-FTPd [privsep] [TLS] ----------
Response: 220-You are user number 6 of 150 allowed.
Response: 220-Local time is now 01:53. Server port: 21.
Response: 220-This is a private system - No anonymous login
Response: 220-IPv6 connections are also welcome on this server.
Response: 220 You will be disconnected after 30 minutes of inactivity. [738869.412d]
Status:   Detected FTP server: PureFTPd
Command:  AUTH TLS
Status:   Waiting for response to: AUTH TLS
Response: 234 AUTH TLS OK. [157ms]
Warning:  SSL Buffering disabled because of .NET 5.0 and later
Status:   FTPS authentication successful, lib = .NET SslStream, cipher suite = Tls12 (Aes256, TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, 44550, 256) [347ms]
Command:  USER ***
Status:   Waiting for response to: USER ***
Response: 331 User *** OK. Password required [157ms]
Command:  PASS ***
Status:   Waiting for response to: PASS ***
Response: 230 OK. Current restricted directory is / [193ms]
Command:  PBSZ 0
Status:   Waiting for response to: PBSZ 0
Response: 200 PBSZ=0 [156ms]
Command:  PROT P
Status:   Waiting for response to: PROT P
Response: 200 Data protection level set to "private" [156ms]
Command:  FEAT
Status:   Waiting for response to: FEAT
Response: 211-Extensions supported:
Response: UTF8
Response: EPRT
Response: IDLE
Response: MDTM
Response: SIZE
Response: MFMT
Response: REST STREAM
Response: MLST type*;size*;sizd*;modify*;UNIX.mode*;UNIX.uid*;UNIX.gid*;unique*;
Response: MLSD
Response: PRET
Response: AUTH TLS
Response: PBSZ
Response: PROT
Response: TVFS
Response: ESTA
Response: PASV
Response: EPSV
Response: ESTP
Response: 211 End. [157ms]
Status:   Text encoding: System.Text.UTF8Encoding+UTF8EncodingSealed
Command:  OPTS UTF8 ON
Status:   Waiting for response to: OPTS UTF8 ON
Response: 504 Unknown command [157ms]
Command:  SYST
Status:   Waiting for response to: SYST
Response: 215 UNIX Type: L8 [157ms]
Status:   Listing parser set to: Machine
Command:  PWD
Status:   Waiting for response to: PWD
Response: 257 "/" is your current location [156ms]

# GetModifiedTime("<file>")
Command:  MDTM <file>
Status:   Waiting for response to: MDTM <file>
Response: 213 20231215205547 [157ms]

Time passes...

Status:   Testing connectivity using Socket.Poll()...
_***** IsConnected = True, IsAuthenticated = True_

# GetModifiedTime("<file>")
Command:  MDTM <file>
Status:   Waiting for response to: MDTM <file>

Then an exception:

Unhandled exception. System.IO.IOException: Unable to read data from the transport connection: A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond..
 ---> System.Net.Sockets.SocketException (10060): A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond.
   at System.Net.Sockets.NetworkStream.Read(Span`1 buffer)
   --- End of inner exception stack trace ---
   at System.Net.Sockets.NetworkStream.Read(Span`1 buffer)
   at System.Net.Security.SyncReadWriteAdapter.ReadAsync(Stream stream, Memory`1 buffer, CancellationToken cancellationToken)
   at System.Net.Security.SslStream.EnsureFullTlsFrameAsync[TIOAdapter](CancellationToken cancellationToken, Int32 estimatedSize)
   at System.Runtime.CompilerServices.PoolingAsyncValueTaskMethodBuilder`1.StateMachineBox`1.System.Threading.Tasks.Sources.IValueTaskSource<TResult>.GetResult(Int16 token)
   at System.Net.Security.SslStream.ReadAsyncInternal[TIOAdapter](Memory`1 buffer, CancellationToken cancellationToken)
   at System.Runtime.CompilerServices.PoolingAsyncValueTaskMethodBuilder`1.StateMachineBox`1.System.Threading.Tasks.Sources.IValueTaskSource<TResult>.GetResult(Int16 token)
   at FluentFTP.FtpSocketStream.Read(Byte[] buffer, Int32 offset, Int32 count)
   at FluentFTP.FtpSocketStream.ReadLine(Encoding encoding)
   at FluentFTP.Client.BaseClient.BaseFtpClient.GetReplyInternal(String command, Boolean exhaustNoop, Int32 timeOut)
   at FluentFTP.Client.BaseClient.BaseFtpClient.GetReplyInternal(String command)
   at FluentFTP.Client.BaseClient.BaseFtpClient.FluentFTP.IInternalFtpClient.ExecuteInternal(String command)
   at FluentFTP.FtpClient.Execute(String command)
   at FluentFTP.FtpClient.GetModifiedTime(String path)

from fluentftp.

FanDjango avatar FanDjango commented on June 14, 2024

Now I just want to think about the "GetReply()" call in IsStillConnected(). There are a number of options there. So it is not finished yet.

from fluentftp.

MisterSausage avatar MisterSausage commented on June 14, 2024

Committed an IsStillConnected into master and build given below, can you check @MisterSausage ? You will find @FanDjango 's latest changes here too.

Test build: FluentFTP.48.1.0-BETA1.zip

This was working as of the master about an hour ago. I'm not using Config.NoopInterval, so I don't know about any interactions with that.

IsStillConnected() returns false as expected in the situation I've been experiencing, and doesn't throw an exception. A couple of observations:

  • Even though it's discovered that the connection is dead, getting IsConnected and IsAuthenticated afterwards still returns true for both.
  • When using Connect() to reconnect, it still attempts to send (and waits for) a QUIT command to the server.

from fluentftp.

FanDjango avatar FanDjango commented on June 14, 2024

I'm not using Config.NoopInterval

So it is "0", zero. Which means no NOOP will be issued. It will never issue a "NOOP" command. I have modified this and will commit the change in a moment.

from fluentftp.

MisterSausage avatar MisterSausage commented on June 14, 2024

By the way, I don't want to complicate things, and I'm sure this has probably been discussed before, but is there a reason why Config.NoopInterval only runs during an active data transfer? Wouldn't it be better if it ran as a background thread, sending NOOPs every Config.NoopInterval milliseconds after any non-NOOP traffic on the control channel, whether there's a transfer in progress or not? It's entirely possible I'm missing something because, as I said, I'm really not familiar with the codebase.

from fluentftp.

FanDjango avatar FanDjango commented on June 14, 2024

Please get the newest master and redo.

I will answer your other concerns and posts step by step too, just like you

from fluentftp.

MisterSausage avatar MisterSausage commented on June 14, 2024

Please get the newest master and redo.

Will do - I'll do that right now and get back to you in about 15 minutes.

from fluentftp.

FanDjango avatar FanDjango commented on June 14, 2024

Even though it's discovered that the connection is dead, getting IsConnected and IsAuthenticated afterwards still returns true for both.

I'll fix this. We need to further modify "IsStillConnected()" to clean up and take down the connection if the NOOP fails.

I commited a further mod to handle this.

from fluentftp.

FanDjango avatar FanDjango commented on June 14, 2024

When using Connect() to reconnect, it still attempts to send (and waits for) a QUIT command to the server.

Need to see the log to understand this

from fluentftp.

MisterSausage avatar MisterSausage commented on June 14, 2024

As of commit 3bfbc74:

# Connect(False)
Status:   FluentFTP 48.0.3.0(.NET 6.0)
Status:   Connecting to IP #1= ***:21
Status:   Waiting for a response
Response: 220---------- Welcome to Pure-FTPd [privsep] [TLS] ----------
Response: 220-You are user number 5 of 150 allowed.
Response: 220-Local time is now 03:23. Server port: 21.
Response: 220-This is a private system - No anonymous login
Response: 220-IPv6 connections are also welcome on this server.
Response: 220 You will be disconnected after 30 minutes of inactivity. [738869.475d]
Status:   Detected FTP server: PureFTPd
Command:  AUTH TLS
Status:   Waiting for response to: AUTH TLS
Response: 234 AUTH TLS OK. [152ms]
Warning:  SSL Buffering disabled because of .NET 5.0 and later
Status:   FTPS authentication successful, lib = .NET SslStream, cipher suite = Tls12 (Aes256, TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, 44550, 256) [335ms]
Command:  USER ***
Status:   Waiting for response to: USER ***
Response: 331 User *** OK. Password required [151ms]
Command:  PASS ***
Status:   Waiting for response to: PASS ***
Response: 230 OK. Current restricted directory is / [184ms]
Command:  PBSZ 0
Status:   Waiting for response to: PBSZ 0
Response: 200 PBSZ=0 [151ms]
Command:  PROT P
Status:   Waiting for response to: PROT P
Response: 200 Data protection level set to "private" [151ms]
Command:  FEAT
Status:   Waiting for response to: FEAT
Response: 211-Extensions supported:
Response: UTF8
Response: EPRT
Response: IDLE
Response: MDTM
Response: SIZE
Response: MFMT
Response: REST STREAM
Response: MLST type*;size*;sizd*;modify*;UNIX.mode*;UNIX.uid*;UNIX.gid*;unique*;
Response: MLSD
Response: PRET
Response: AUTH TLS
Response: PBSZ
Response: PROT
Response: TVFS
Response: ESTA
Response: PASV
Response: EPSV
Response: ESTP
Response: 211 End. [152ms]
Status:   Text encoding: System.Text.UTF8Encoding+UTF8EncodingSealed
Command:  OPTS UTF8 ON
Status:   Waiting for response to: OPTS UTF8 ON
Response: 504 Unknown command [151ms]
Command:  SYST
Status:   Waiting for response to: SYST
Response: 215 UNIX Type: L8 [151ms]
Status:   Active ServerHandler is: PureFTPd
Status:   Listing parser set to: Machine
Command:  PWD
Status:   Waiting for response to: PWD
Response: 257 "/" is your current location [151ms]

# GetModifiedTime("<file>")
Command:  MDTM <file>
Status:   Waiting for response to: MDTM <file>
Response: 213 20231215205547 [151ms]

Time passes...

Status:   Testing connectivity using Socket.Poll()...
***** IsConnected = True, IsAuthenticated = True
***** Calling IsStillConnected()...
Command:  NOOP
Status:   Waiting for response to: NOOP
Unhandled exception. System.IO.IOException: Unable to read data from the transport connection: A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond..
 ---> System.Net.Sockets.SocketException (10060): A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond.
   at System.Net.Sockets.NetworkStream.Read(Span`1 buffer)
   --- End of inner exception stack trace ---
   at System.Net.Sockets.NetworkStream.Read(Span`1 buffer)
   at System.Net.Security.SyncReadWriteAdapter.ReadAsync(Stream stream, Memory`1 buffer, CancellationToken cancellationToken)
   at System.Net.Security.SslStream.EnsureFullTlsFrameAsync[TIOAdapter](CancellationToken cancellationToken, Int32 estimatedSize)
   at System.Runtime.CompilerServices.PoolingAsyncValueTaskMethodBuilder`1.StateMachineBox`1.System.Threading.Tasks.Sources.IValueTaskSource<TResult>.GetResult(Int16 token)
   at System.Net.Security.SslStream.ReadAsyncInternal[TIOAdapter](Memory`1 buffer, CancellationToken cancellationToken)
   at System.Runtime.CompilerServices.PoolingAsyncValueTaskMethodBuilder`1.StateMachineBox`1.System.Threading.Tasks.Sources.IValueTaskSource<TResult>.GetResult(Int16 token)
   at System.Net.Security.SslStream.Read(Byte[] buffer, Int32 offset, Int32 count)
   at FluentFTP.FtpSocketStream.Read(Byte[] buffer, Int32 offset, Int32 count) in <local directory>\Repos\FluentFTP\FluentFTP\Streams\FtpSocketStream.cs:line 543
   at FluentFTP.FtpSocketStream.ReadLine(Encoding encoding) in <local directory>\Repos\FluentFTP\FluentFTP\Streams\FtpSocketStream.cs:line 607
   at FluentFTP.Client.BaseClient.BaseFtpClient.GetReplyInternal(String command, Boolean exhaustNoop, Int32 timeOut) in <local directory>\Repos\FluentFTP\FluentFTP\Client\BaseClient\GetReply.cs:line 133

When using Connect() to reconnect, it still attempts to send (and waits for) a QUIT command to the server.

Need to see the log to understand this

This was happening in the first commit that introduced IsStillConnected(), so it's probably not worth worrying about at this point.

from fluentftp.

FanDjango avatar FanDjango commented on June 14, 2024

You see that now a NOOP command is actually issued, as opposed to the original version.

So now we need to catch failures of NOOP too. This will take me a small moment and I will commit again.

from fluentftp.

FanDjango avatar FanDjango commented on June 14, 2024

By the way: It is interesting to note that sending the NOOP actually worked without an exception. It is the reading of the reply that throws.

from fluentftp.

MisterSausage avatar MisterSausage commented on June 14, 2024

By the way: It is interesting to note that sending the NOOP actually worked without an exception. It is the reading of the reply that throws.

Yes, that's what I mentioned when I opened the issue - there's a firewall or something else in front of the server that keeps the TCP socket open, but closes its internal connection to the server, leaving it in a weird, semi-half-open state from the client's point of view. Very strange!

from fluentftp.

FanDjango avatar FanDjango commented on June 14, 2024

Ok, go again.

from fluentftp.

FanDjango avatar FanDjango commented on June 14, 2024

At least we will get IsStillConnected() to become as foolproof as possible. But from a nice tidy little routine we are moving towards a huge convulted ugly beast, as is usually the case when coding for TCP

from fluentftp.

MisterSausage avatar MisterSausage commented on June 14, 2024

Fantastic! As of commit e85a9dc:

# Connect(False)
Status:   FluentFTP 48.0.3.0(.NET 6.0)
Status:   Connecting to IP #1= ***:21
Status:   Waiting for a response
Response: 220---------- Welcome to Pure-FTPd [privsep] [TLS] ----------
Response: 220-You are user number 6 of 150 allowed.
Response: 220-Local time is now 03:57. Server port: 21.
Response: 220-This is a private system - No anonymous login
Response: 220-IPv6 connections are also welcome on this server.
Response: 220 You will be disconnected after 30 minutes of inactivity. [738869.498d]
Status:   Detected FTP server: PureFTPd
Command:  AUTH TLS
Status:   Waiting for response to: AUTH TLS
Response: 234 AUTH TLS OK. [154ms]
Warning:  SSL Buffering disabled because of .NET 5.0 and later
Status:   FTPS authentication successful, lib = .NET SslStream, cipher suite = Tls12 (Aes256, TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, 44550, 256) [339ms]
Command:  USER ***
Status:   Waiting for response to: USER ***
Response: 331 User *** OK. Password required [155ms]
Command:  PASS ***
Status:   Waiting for response to: PASS ***
Response: 230 OK. Current restricted directory is / [182ms]
Command:  PBSZ 0
Status:   Waiting for response to: PBSZ 0
Response: 200 PBSZ=0 [154ms]
Command:  PROT P
Status:   Waiting for response to: PROT P
Response: 200 Data protection level set to "private" [154ms]
Command:  FEAT
Status:   Waiting for response to: FEAT
Response: 211-Extensions supported:
Response: UTF8
Response: EPRT
Response: IDLE
Response: MDTM
Response: SIZE
Response: MFMT
Response: REST STREAM
Response: MLST type*;size*;sizd*;modify*;UNIX.mode*;UNIX.uid*;UNIX.gid*;unique*;
Response: MLSD
Response: PRET
Response: AUTH TLS
Response: PBSZ
Response: PROT
Response: TVFS
Response: ESTA
Response: PASV
Response: EPSV
Response: ESTP
Response: 211 End. [155ms]
Status:   Text encoding: System.Text.UTF8Encoding+UTF8EncodingSealed
Command:  OPTS UTF8 ON
Status:   Waiting for response to: OPTS UTF8 ON
Response: 504 Unknown command [154ms]
Command:  SYST
Status:   Waiting for response to: SYST
Response: 215 UNIX Type: L8 [154ms]
Status:   Active ServerHandler is: PureFTPd
Status:   Listing parser set to: Machine
Command:  PWD
Status:   Waiting for response to: PWD
Response: 257 "/" is your current location [154ms]

# GetModifiedTime("<file>")
Command:  MDTM <file>
Status:   Waiting for response to: MDTM <file>
Response: 213 20231215205547 [154ms]

Time passes...

Status:   Testing connectivity using Socket.Poll()...
***** IsConnected = True, IsAuthenticated = True
***** Calling IsStillConnected()...
Command:  NOOP
Status:   Waiting for response to: NOOP
Status:   Testing connectivity using Socket.Poll()...
Status:   Closing/Disposing FtpSocketStream(control connection)
***** IsStillConnected() = False
***** IsConnected = False, IsAuthenticated = False
***** No longer authenticated - reconnecting

# Connect(False)
Status:   FluentFTP 48.0.3.0(.NET 6.0)
Status:   Connecting to IP #1= ***:21
Status:   Waiting for a response
Response: 220---------- Welcome to Pure-FTPd [privsep] [TLS] ----------
Response: 220-You are user number 6 of 150 allowed.
Response: 220-Local time is now 04:07. Server port: 21.
Response: 220-This is a private system - No anonymous login
Response: 220-IPv6 connections are also welcome on this server.
Response: 220 You will be disconnected after 30 minutes of inactivity. [15.839s]
Status:   Detected FTP server: PureFTPd
Command:  AUTH TLS
Status:   Waiting for response to: AUTH TLS
Response: 234 AUTH TLS OK. [150ms]
Warning:  SSL Buffering disabled because of .NET 5.0 and later
Status:   FTPS authentication successful, lib = .NET SslStream, cipher suite = Tls12 (Aes256, TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, 44550, 256) [312ms]
Command:  USER ***
Status:   Waiting for response to: USER ***
Response: 331 User *** OK. Password required [150ms]
Command:  PASS ***
Status:   Waiting for response to: PASS ***
Response: 230 OK. Current restricted directory is / [185ms]
Command:  PBSZ 0
Status:   Waiting for response to: PBSZ 0
Response: 200 PBSZ=0 [151ms]
Command:  PROT P
Status:   Waiting for response to: PROT P
Response: 200 Data protection level set to "private" [151ms]
Command:  FEAT
Status:   Waiting for response to: FEAT
Response: 211-Extensions supported:
Response: UTF8
Response: EPRT
Response: IDLE
Response: MDTM
Response: SIZE
Response: MFMT
Response: REST STREAM
Response: MLST type*;size*;sizd*;modify*;UNIX.mode*;UNIX.uid*;UNIX.gid*;unique*;
Response: MLSD
Response: PRET
Response: AUTH TLS
Response: PBSZ
Response: PROT
Response: TVFS
Response: ESTA
Response: PASV
Response: EPSV
Response: ESTP
Response: 211 End. [152ms]
Status:   Text encoding: System.Text.UTF8Encoding+UTF8EncodingSealed
Command:  OPTS UTF8 ON
Status:   Waiting for response to: OPTS UTF8 ON
Response: 504 Unknown command [150ms]
Command:  SYST
Status:   Waiting for response to: SYST
Response: 215 UNIX Type: L8 [151ms]
Status:   Active ServerHandler is: PureFTPd
Status:   Listing parser set to: Machine
Command:  PWD
Status:   Waiting for response to: PWD
Response: 257 "/" is your current location [150ms]
***** IsConnected = True, IsAuthenticated = True
Command:  NOOP
Status:   Waiting for response to: NOOP
Response: 200 Zzz... [151ms]
***** IsStillConnected() = True
***** IsConnected = True, IsAuthenticated = True

# GetModifiedTime("<file>")
Command:  MDTM <file>
Status:   Waiting for response to: MDTM <file>
Response: 213 20231215205547 [151ms]
***** Last modified: 15/12/2023 20:55:47

# Dispose()
Status:   Disposing FtpClient object...
Command:  QUIT
Status:   Waiting for response to: QUIT
Response: 221-Goodbye. You uploaded 0 and downloaded 0 kbytes.
Response: 221 Logout. [151ms]
Status:   Closing/Disposing FtpSocketStream(control connection)
Status:   Closing/Disposing FtpSocketStream(control connection)

This is working really well now. Thank you for your effort!

from fluentftp.

FanDjango avatar FanDjango commented on June 14, 2024

Just made a last commit to do some logging also:

Status:   Closing/Disposing FtpSocketStream(data connection)
>         CloseDataStream()
Status:   Waiting for response to: MLSD
Response: 226 Transfer complete [40ms]
Status:   Closing/Disposing FtpSocketStream(data connection)

>         IsStillConnected(10000)
Command:  NOOP
Status:   Waiting for response to: NOOP
Status:   Exception: Unable to read data from the transport connection: Eine bestehende Verbindung wurde softwaregesteuert
durch den Hostcomputer abgebrochen..
Status:   Closing/Disposing FtpSocketStream(control connection)
Status:   Control connections is not connected
>         Dispose()
Status:   Disposing FtpClient object...
Status:   Closing/Disposing FtpSocketStream(control connection)
Finished

from fluentftp.

MisterSausage avatar MisterSausage commented on June 14, 2024

Closing as this issue is now resolved from my point of view. Thank you once again for your efficient hard work!

from fluentftp.

FanDjango avatar FanDjango commented on June 14, 2024

I just experimented with executing a NOOP command (in form of a IsStillActive()) in front of every command that FluenFTP issues, to catch disconnects "pro-actively". You see lots of NOOPs, of course, in the log, but it doesn't slow the stuff down noticeably.

...
...
>         IsStillConnected(10000)
Command:  NOOP
Status:   Waiting for response to: NOOP
Response: 200 NOOP command successful [1ms]
Command:  OPTS UTF8 ON
Status:   Waiting for response to: OPTS UTF8 ON
Response: 200 UTF8 set to on [1ms]
>         IsStillConnected(10000)
Command:  NOOP
Status:   Waiting for response to: NOOP
Response: 200 NOOP command successful [1ms]
Command:  SYST
Status:   Waiting for response to: SYST
Response: 215 UNIX Type: L8 [1ms]
...
...

from fluentftp.

robinrodricks avatar robinrodricks commented on June 14, 2024

We could simply temporarily set the NoopInterval and reset the time, then restore the current NoopInterval, how about that?

Yes please, yes I missed the intricacies of the NOOP handling.

This was a little too quick off the mark.

Yes I just jumped the gun to get something quick started/released. Just a prototype.

from fluentftp.

robinrodricks avatar robinrodricks commented on June 14, 2024

Closing as this issue is now resolved from my point of view. Thank you once again for your efficient hard work!

Thanks for closing, but we usually close after release, so that I remember to get the release done and then get that release verified by the user.

You're welcome, but this was an easy fix so well.

This is working really well now. Thank you for your effort!

Thanks @FanDjango for perfecting this!

from fluentftp.

FanDjango avatar FanDjango commented on June 14, 2024

@MisterSausage You might want to look at this, maybe:

#1419

Currently to be found at:

https://github.com/FanDjango/FluentFTP/tree/THREAD

from fluentftp.

MisterSausage avatar MisterSausage commented on June 14, 2024

@MisterSausage You might want to look at this, maybe:

Looks great! I'll download it and give it a test on the troublesome server overnight, and let you know.

from fluentftp.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.