我在 Windows 服务中有代码,当我通过测试工具在本地运行它时成功连接到 FTP 服务器(FTP 服务器位于本地网络上的另一台机器上)。
但是,当我在生产托管环境中安装它时,我得到了可怕的 WebException “无法连接到远程服务器”。ACTV
无论我使用的是 FTP还是PASV
FTP似乎都无关紧要,我都得到了这个 WebException。但是,如果我尝试从 Windows 命令行 FTP,它工作得非常好(所以不是防火墙有问题)。
我正在使用的代码(改编自How to List Directory Contents with FTP in C#?)内容如下:
private static readonly string __ftpSourceServer = "ftp://"
+ ConfigurationManager.AppSettings["FtpServer"] + "/";
private static readonly NetworkCredential __ftpCreds = new NetworkCredential(
ConfigurationManager.AppSettings["Username"],
ConfigurationManager.AppSettings["Password"]);
// And now the method MediaSyncDaemon.GetFilesToFetch:
bool usePassive = Boolean.TryParse(ConfigurationManager.AppSettings["UsePassive"]
, out usePassive) && usePassive;
Uri ftpSrv = new Uri(__ftpSourceServer + Uri.EscapeUriString(
ConfigurationManager.AppSettings["FtpPath"]));
Logger.Debug("Connecting to FTP server at " + ftpSrv + "; PASV? " + usePassive);
FtpWebRequest listRequest = (FtpWebRequest) WebRequest.Create(ftpSrv);
listRequest.Method = WebRequestMethods.Ftp.ListDirectory;
listRequest.Credentials = __ftpCreds;
listRequest.UsePassive = usePassive;
listRequest.UseBinary = false;
using (FtpWebResponse listResponse = (FtpWebResponse) listRequest.GetResponse())
{
// ReSharper disable AssignNullToNotNullAttribute
return new StreamReader(listResponse.GetResponseStream())
.ReadToEnd().Split(new[] { '\n', '\r' },
StringSplitOptions.RemoveEmptyEntries)
.Where(s => s.EndsWith(".zip", true, CultureInfo.InvariantCulture))
.ToList();
// ReSharper restore AssignNullToNotNullAttribute
}
异常在该行(语句之外)的FtpWebRequest.GetResponse()
调用中引发,堆栈跟踪中没有其他内容:using
return
System.Net.WebException
: 无法连接到远程服务器
atSystem.Net.FtpWebRequest.GetResponse()
(该文件中的行号)
我的测试工具(有效)和生产环境(无效)之间唯一真正的区别是生产环境中存在防火墙——所有四台服务器都位于稍微不同的子网上:
Dev client 10.16.6.155 subnet 255.255.255.128
Dev server 10.16.7.242 subnet 255.255.255.0
Prod client 192.168.102.107 subnet 255.255.255.0
Prod server 192.168.203.110 subnet 255.255.255.0
但防火墙不是问题,我可以交互地从 Prod 客户端 FTP 到 Prod 服务器,只是不能以编程方式。
我已经尝试更改bool
appSettings 的值,UsePassive
并且没有任何区别,并且在每种情况下,FTP 服务器日志中都没有显示任何内容(所以它没有走那么远)。
现在我不指望任何人能够调试我的托管环境的硬件基础设施,但我正在努力思考我可以改变什么来让它工作。我已经看到它在我的测试工具中本地工作,调用相同的方法。如果有帮助,测试工具代码如下所示:
[NUnit.Framework.Test]
public void FtpFileListTest()
{
ICollection<string> files = MediaSyncDaemon.GetFilesToFetch();
Assert.IsNotNull(files);
Assert.Greater(files.Count, 0);
}
请问有人知道我还能尝试什么吗?
谢谢!
更新
在评论中有一些可以查看的地方的建议后,我可以进一步更新一下:
问题似乎不是用户权限 - 该服务正在本地系统帐户的上下文中运行(该帐户比管理员拥有更多权限)
问题似乎不是代码访问安全性。我已经为这段代码添加了对 entry 方法的调用:
SocketPermission
.
Demand
System.Security.CodeAccessPermission socketPermission; socketPermission = new SocketPermission(NetworkAccess.Connect, TransportType.Tcp, ConfigurationManager.AppSettings["FtpServer"], 20); socketPermission.Demand(); socketPermission = new SocketPermission(NetworkAccess.Connect, TransportType.Tcp, ConfigurationManager.AppSettings["FtpServer"], 21); socketPermission.Demand();
而且我没有看到任何SecurityException被抛出;在相同代码位置的新行号处,我仍然得到相同的 WebException。
有人对我可以尝试什么有任何进一步的建议吗?