【发布时间】:2011-11-04 22:02:41
【问题描述】:
我已经打包了大部分 wininet 没有问题,但现在我被卡住了。我正在尝试从 wininet.dll p/invoke 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 接收的句柄,但如果我这样做,应用程序只会退出而没有错误。
编辑 2
我正在使用 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:
【问题讨论】:
-
@Daniel。是的,我也这么认为。我已经稍微更改了函数,以便根据命令,它可能会或可能不会期望数据套接字。我可以成功发送 PASV 命令,但是当我尝试从 FtpCommand 调用返回的 dataSocket 句柄中读取时,我得到了相同的结果。
-
最坏的情况你可以使用 PORT 命令和 TcpListener 的组合;它看起来不那么漂亮,但它确实有效。