我把大部分的wininet包裹起来没有问题,但现在我被卡住了。我试图从wininet.dll调用FtpCommand,但我运行的每个命令都返回“500语法错误”。甚至像dir或ls这样的简单命令。如果我使用ftp.exe连接到同一服务器,则命令可以正常工作并返回预期结果。
以下是方法定义:
[DllImport("wininet.dll", CharSet = CharSet.Auto, SetLastError=true)]
extern public static int FtpCommand(
[In] IntPtr hConnect,
[In] bool fExpectResponse,
[In] int dwFlags,
[In] string command,
[In] IntPtr dwContext,
[In][Out] ref int ftpCommand);
我在调用它的代码:
public string SendCommand(string cmd)
{
int result;
IntPtr dataSocket = new IntPtr();
switch(cmd)
{
case "PASV":
result = WININET.FtpCommand(_hConnect, false, WININET.FTP_TRANSFER_TYPE_ASCII, cmd, IntPtr.Zero, ref dataSocket);
break;
default:
result = WININET.FtpCommand(_hConnect, true, WININET.FTP_TRANSFER_TYPE_ASCII, cmd, IntPtr.Zero, ref dataSocket);
break;
}
Console.WriteLine(InternetLastResponseInfo());
int BUFFER_SIZE = 8192;
if(result == 0){
Error();
}
else if(dataSocket != IntPtr.Zero)
{
StringBuilder buffer = new StringBuilder(BUFFER_SIZE);
int bytesRead = 0;
do
{
result = WININET.InternetReadFile(dataSocket, buffer, BUFFER_SIZE, ref bytesRead);
} while (result == 1 && bytesRead > 1);
return buffer.ToString();
}
return "";
}
其他一切正常,我可以使用FtpFindFirstFile()下载文件,上传文件和模仿dir命令,但我似乎无法使用上述方法发送命令。
我的SendCommand代码刚刚是SendCommand(“DIR”)或SendCommand(“LS”)。在阅读其中一个答案(在我编辑时看不到谁)后,我将其更改为SendCommand(“LIST”)并成功返回。
但是,我的问题是如何读取结果,我用什么来读取LIST命令返回的数据,以便我可以以可读的格式输出?
我已经更新了SendCommand方法,以显示我计划如何读取返回的数据,但是对于bytesRead我总是得到0。我也尝试在FtpCommand调用中传递dataSocket接收到的句柄,但是如果我这样做,应用程序就会退出而没有错误。
我正在使用InternetReadFile从我调用FtpCommand时返回的数据套接字的句柄中读取数据。我正在使用的InternetReadFile的方法签名是:
[DllImport("wininet.dll", CharSet = CharSet.Ansi, SetLastError = true)]
extern public static int InternetReadFile(
[In] IntPtr hConnect,
[In][Out] StringBuilder buffer,
[In] int buffCount,
[In][Out] ref int bytesRead);
我发布了这个code on codeplex:
答案 0 :(得分:4)
您为什么会收到500 Syntax error
?
请注意,与FTP客户端(例如ftp.exe
)不同,实际FTP protocol不会使用ls
之类的命令,它会执行LIST
和{{1}等命令}
有关FTP接受的命令列表,请参阅Raw FTP Command List或RFC 959
如何获得NLST
或LIST
命令的结果?
FtpCommand
的最后一个参数是
指向创建的句柄的指针 如果打开了有效的数据套接字。该 必须设置
NLST
参数fExpectResponse
填写TRUE
。
您可以使用此句柄通过InternetReadFile
读出列表。
备注:强>
phFtpCommand
发送的实际网络流量,并将其与您的代码发送的内容进行比较答案 1 :(得分:1)
纠正我的问题的关键是确保发送原始FTP命令,而不是诸如“DIR”之类的命令,传递true(我期望数据套接字),并且方法声明中的CharSet是CharSet。 ANSI。如果我用CharSet.Auto或CharSet.Unicode替换CharSet.Ansi,我只会得到一堆乱码。
我已更新问题中的代码示例,以反映有效的方法。