Delphi - 在共享环境中写入/读取文件

5

我在局域网中的文件上遇到了一些问题:有一个单独的Delphi程序(服务器),应该写入一些文件,这些文件只能被多个Delphi程序(客户端)读取。

我在服务器上使用以下简单指令进行写入(DataList是TStrings):

Stream:=TFileStream.Create(filePath,fmOpenWrite or fmShareDenyWrite);
try
 DataList.SaveToStream(Stream);
finally
 Stream.Free;
end;

客户端每5秒钟检查以上文件是否被修改(通过检查FileAge),如果发生了修改,它们以以下方式加载DataList:
try
 Stream:=TFileStream.Create(filePath,fmOpenRead or fmShareDenyNone);
 DataList.LoadFromStream(Stream);
finally
 Stream.Free;
end;

通常情况下一切都能完美运行,但有时服务器或客户端会因为“文件正在被其他进程使用”而引发异常。我不明白问题出在哪里:我尝试了很多替代方法,但即使只有服务器和一个客户端实例运行,这种情况也可能发生。有什么想法吗?谢谢!

1
尝试找出哪个进程锁定了文件。可能是另一个进程,例如防病毒软件、备份或索引服务。 - Ondrej Kelle
我不这么认为:文件所在的计算机运行的是Windows 2008服务器,但没有安装任何杀毒软件,并且备份是在晚上进行的。而且,最重要的是,如果我单独运行服务器或客户端程序,就不会有任何问题,但如果两者一起运行,就总是会发生冲突。 - Bosch
我曾经遇到过完全相同的问题。在服务器上,这可能是因为两个服务器实例尝试同时写入而发生的。在客户端上,我不知道,我只是小心地捕获并优雅地忽略异常,在代码中加上一个深思熟虑的注释,说“它永远不应该发生,但它确实发生了”。 - PA.
不要让客户端直接访问服务器上的文件。通过 Web 服务器公开文件怎么样? - Hendra
1个回答

3

从设计上来说,网络文件系统是不可信任的。至少在Linux中的NFS和Windows中的SMB没有被证明具有锁定功能:并发访问不安全。

您需要使用客户端-服务器协议来确保共享数据的安全性。您可以使用TCP/IP、HTTP或任何其他方式。

我建议使用真正的服务实现,例如DataSnap、RemObjects或我们的开源mORMot


我想我会使用TCP/IP协议(我已经在同一程序中用于其他数据交换);唯一的不好之处是我发现TCP/IP比直接文件访问慢。谢谢大家! - Bosch
TCP/IP为什么比文件访问慢?网络文件系统运行在TCP/IP之上。 - David Heffernan
也许你是对的,但我发现从Windows Server 2008计算机的共享目录中读取小文本文件(通过Indy组件通过TCP/IP发送给客户端程序)比直接由客户端计算机读取相同的文件要慢得多。对此有什么想法吗? - Bosch
热点新闻!我尝试在本地目录中测试相同的情况(服务器和客户端程序都在同一台Win 7 64位PC上运行,使用同一台PC中的文件,没有网络),并发现相同的结果:有时会在文件写入服务器或文件读取客户端中出现“文件被其他进程使用”的异常。因此,Arnaud Bouchez的答案并不能解释这种情况。我正在使用Delphi Light Edition 7.3.4.3(构建8.1)。 - Bosch
  1. 网络文件夹使用缓存(这是其锁定失败的原因之一),因此它比始终通过TCP/IP发送内容更快。您可以通过在客户端级别实现一些聪明的TCP/IP协议来实现更好的速度,并带有缓存。
  2. 关于您本地目录的问题,这表明您的实现甚至比预期的还要糟糕。在这种情况下,您可以使用file locking API。但是在网络上,即使使用此API也不安全
- Arnaud Bouchez

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接