ftp diff between .net3.5 and .net4.0

来源:互联网 发布:苹果在线视频下载软件 编辑:程序博客网 时间:2024/06/06 07:27

symptoms:

When using System.Net.FtpWebRequest class on .Net Framework 4 to perform the FTP STOR/RETR command, the class throws a FTP error 5xx, for example: 

"501 Syntax error - sender/receiver missing".

However, this class works fine with .Net Framework 3.5 and does not throw the same error.



cause:

The cause of this issue is due to a behavior change in the System.Net.FtpWebRequest class in .Net Framework 4. There has been a change made to the System.Net.FtpWebRequest class from .Net Framework 3.5 to .Net Framework 4 to streamline the use of the CWD protocol commands. The new implementation of the System.Net.FtpWebRequest class prevents the send of extra CWD commands before issuing the actual command which the user requested and instead directly sends the requested command. For fully RFC compliant FTP servers, this should not be an issue, however for non-fully RFC compliant servers, you will see these types of errors.




resolution:

n order to resolve this issue, it is required to force the System.Net.FtpWebRequest command to revert back to the old behavior of how it used to work in .Net Framework 2.0/3.5 and issue the extra CWD command before issuing the actual command.

In order to do this, the following code needs to be placed before any instance of the System.Net.FtpWebRequest class is invoked. 
The code below only needs to be called once, since it changes the settings of the entire application domain.

private static void SetMethodRequiresCWD()
 {
            Type requestType = typeof(FtpWebRequest);
            FieldInfo methodInfoField = requestType.GetField("m_MethodInfo", BindingFlags.NonPublic | BindingFlags.Instance);
            Type methodInfoType = methodInfoField.FieldType;


            FieldInfo knownMethodsField = methodInfoType.GetField("KnownMethodInfo", BindingFlags.Static | BindingFlags.NonPublic);
            Array knownMethodsArray = (Array)knownMethodsField.GetValue(null);

            FieldInfo flagsField = methodInfoType.GetField("Flags", BindingFlags.NonPublic | BindingFlags.Instance);

            int MustChangeWorkingDirectoryToPath = 0x100;
            foreach (object knownMethod in knownMethodsArray)
            {
                int flags = (int)flagsField.GetValue(knownMethod);
                flags |= MustChangeWorkingDirectoryToPath;
                flagsField.SetValue(knownMethod, flags);
            }
 }




more:

The behavior of the System.Net.FtpWebRequest class has changed in .Net Framework 4 vs. .Net Framework 3.5. 
In .Net Framework 3.5, a file upload to a server using the System.Net.FtpWebRequest class followed a typical exchange of the following FTP commands:

a.) USER
b.) PASS
c.) OPTS
d.) PWD
e.) CWD 
f.) STOR

However, in .Net Framework 4, a typical file upload goes through the following command sequence:

a.) USER
b.) PASS
c.) OPTS
d.) PWD
e.) STOR

The difference between the 2 behaviors is that in the 3.5 version, the upload happens by performing a CWD command to change the current directory to the intended directory, followed by the STOR command with just the filename.

However, .Net Framework 4 implementation prevents the send of the additional CWD command, and sends the STOR command directly to the destination directory with the fully qualified directory structure.

For fully RFC compliant FTP servers, this would not be an issue, but for others, this behavior may break existing applications from working with .Net Framework 4.

For such server communication, you will see the server respond back with a FTP Error code: 5xx, such as "501 Syntax error - sender/receiver missing" whereas the same code will work for the System.Net.FtpWebRequest class when used with the .Net Framework 3.5.