issue with Active Mode, cannot reuse the ActivePorts, then throw exception
See original GitHub issueFluentFTP Version: reproduced on v40/v39/v38 Framework: reproduced on .NET4 and .NET6 FTP Server: reproduced on build-in FTP From Microsoft IIS and FileZilla Server FTP Client OS: reproduced on Microsoft Window 7 and Ubuntu 18.04 FTP Server OS: reproduced on Microsoft Windows Server 2016
Dear team,
Hello. Passive Mode is used in many situations, as far as we know.
However, in the recent projects, we have to use the Acive Mode and limit the usage with ports rang.
Simple source code to reproduce this issue:
var ftpClient = new FluentFTP.FtpClient();
ftpClient.Host = "[[replace your ftp server ip here pls]]";
ftpClient.Port = 21;
ftpClient.Config.DataConnectionType = FluentFTP.FtpDataConnectionType.PORT;
ftpClient.Config.ActivePorts = new int[] { 8082 };
ftpClient.UploadFile(@"D:\0.jpg", "/0.jpg", FluentFTP.FtpRemoteExists.Overwrite, true);
ftpClient.UploadFile(@"D:\1.jpg", "/1.jpg", FluentFTP.FtpRemoteExists.Overwrite, true);
ftpClient.UploadFile(@"D:\2.jpg", "/2.jpg", FluentFTP.FtpRemoteExists.Overwrite, true);
Only the 0.jpg
would be uploaded successfully. The subsequent files would throw the excpetion:
No valid active data port available!
This exception was originally thrown at this call stack:
FluentFTP.FtpClient.StartListeningOnPort(FluentFTP.FtpDataStream)
FluentFTP.FtpClient.OpenActiveDataStream(FluentFTP.FtpDataConnectionType, string, long)
FluentFTP.FtpClient.OpenDataStream(string, long)
FluentFTP.FtpClient.OpenWrite(string, FluentFTP.FtpDataType, long)
Logs from FluentFTP:
# Connect()
Status: Connecting to ***:21
Response: 220-FileZilla Server 0.9.60 beta
Response: 220-written by Tim Kosse (tim.kosse@filezilla-project.org)
Response: 220 Please visit https://filezilla-project.org/
Status: Detected FTP server: FileZilla
Command: USER ***
Response: 331 Password required for ***
Command: PASS ***
Response: 230 Logged on
Command: FEAT
Response: 211-Features:
Response: MDTM
Response: REST STREAM
Response: SIZE
Response: MLST type*;size*;modify*;
Response: MLSD
Response: UTF8
Response: CLNT
Response: MFMT
Response: EPSV
Response: EPRT
Response: 211 End
Status: Text encoding: System.Text.UTF8Encoding+UTF8EncodingSealed
Command: OPTS UTF8 ON
Response: 202 UTF8 mode is always enabled. No need to send this command.
Command: SYST
Response: 215 UNIX emulated by FileZilla
Status: Listing parser set to: Machine
# UploadFile("D:\0.jpg", "/0.jpg", Overwrite, True, None)
# FileExists("/0.jpg")
Command: SIZE /0.jpg
Response: 550 File not found
# DirectoryExists("/")
# OpenWrite("/0.jpg", Binary)
# GetFileSize("/0.jpg")
Command: SIZE /0.jpg
Response: 550 File not found
Command: TYPE I
Response: 200 Type set to I
# OpenActiveDataStream(PORT, "STOR /0.jpg", 0)
Command: PORT 127,0,0,1,31,146
Response: 200 Port command successful
Command: STOR /0.jpg
Response: 150 Opening data channel for file upload to server of "/0.jpg"
Status: Disposing FtpSocketStream...
Response: 226 Successfully transferred "/0.jpg"
# UploadFile("D:\1.jpg", "/1.jpg", Overwrite, True, None)
# FileExists("/1.jpg")
Command: SIZE /1.jpg
Response: 550 File not found
# DirectoryExists("/")
# OpenWrite("/1.jpg", Binary)
# GetFileSize("/1.jpg")
Command: SIZE /1.jpg
Response: 550 File not found
# OpenActiveDataStream(PORT, "STOR /1.jpg", 0)
Unhandled exception. FluentFTP.FtpException: Error while uploading the file to the server. See InnerException for more info.
---> System.Exception: No valid active data port available!
Then, if we change the code (add one more port)
From Config.ActivePorts = new int[] { 8082 };
To Config.ActivePorts = new int[] { 8082, 8081 };
and restart the application, the first file 0.jpg
and second file 1.jpg
would be uploaded successfully but subsequent files.
Therefore, we can call UploadFile times as count(Config.ActivePorts) only.
As you see, each time we call UploadFile
method, FluentFTP would bind and listen to a new port. Due to cannot reuse old one , and then the ports set by the Config.ActivePorts
will be used up soon.
What other things that we’ve tried already and have no luck:
- change
Config.SocketKeepAlive
- change
Config.DisconnectWithShutdown
- change
Config.DisconnectWithQuit
- call
Disconnect
afterUploadFile
andConnect
again - call
Disconnect
andDispose
afterUploadFile
and recreate and reconnect again - try to add code
m_socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
to FtpSocketStream::Listen method.
Looking forward your reply and ideas. Thanks so much 😃
Issue Analytics
- State:
- Created a year ago
- Comments:8 (1 by maintainers)
Dear @FanDjango and @robinrodricks , It now work under both .Net Framewrok and .Net Core runtime. Cheer!
Thanks again for you && Have a good day 😃
Thanks once again for the excellent diagnosis.
I found the place:
private void CheckResult(SocketAsyncEventArgs args) {...}
Added the needed
.Close()
and tested it with .NET 6.Once it is merged, you can test it too.