如果每个applet都能在你的计算机上读写文件,浏览Web时就很容易感染病毒或受到其他攻击。所以,Sun Microsystems通过施加某些限制来解决这个安全问题。通常,applet主要有两方面的限制:
这些限制成功阻止了在两个applet之间传输文件吗?是的——如果它们直接传输文件的话。但是,假如有一个中间人提供帮助,就可避开这些限制。
我们的思路是让中间人从applet接收文件,再把它转发给其他applet。它就像文件通信中的一个路由器,所以我称之为文件路由器。
为文件传输设计程序时,需要适应两个applet安全限制。首先,两个applet之间不允许直接建立网络连接。文件路由器应该能与发送及接收applet交换指令。其次,applet和另一台计算机之间不应建立直接网络连接,除非后者是提供applet源代码的服务器。文件路由器也应该在服务器上。还必须考虑用于applet的网络连接和文件I/O的一些Java策略设置。
请下载示范代码,下面将详细说明每一段代码。
表A、B和C描述了代码中使用的类和方法,让你对“中间人”有一个大致的了解。
表A
类 | 说明 |
FileTransferCtlClass | 这个公共类处理数据交换,要由一个Applet类所有及使用。它从Thread扩展,以便能在后台执行文件传输。 |
TransferFrame | FileTransferCtlClass对象(显示Applet对象中的任何消息)将使用这个类。由于它的目标是为FileTransferCtlClass显示消息,所以是私有的,只能由一个FileTransferCtlClass对象访问。 |
表B
FileTransferCtlClass | |
方法 | 说明 |
FileTransferCtlClass(InputStream myInputStream, OutputStream myOutputStream, int myMode) | 这是FileTransferCtlClass的构造函数,由传输过程中无需任何显示的一个对象调用。myInputStream是一个InputStream对象,它负责接收数据。可用它接收来自一个文件发送者的数据,或读取一个本地文件。myOutStream是一个OutputStream对象,它负责发送数据。可用它将数据发送给一个文件接收者,或将数据写入本地文件。myMode指出FileTransferCtlClass对象要执行哪种工作。如果设为_SENDMODE,对象就从选中的本地文件读取数据,并将数据发送给接收者。如果设为_GETMODE,对象将从一个发送者接收数据,并将数据写到一个本地文件中。如果设为_ROUTEMODE,对象将从一个发送者接收数据,并将数据发送给接收者。 |
FileTransferCtlClass(InputStream myInputStream, OutputStream myOutputStream, int myMode, chatApplet myOwner) | 这是FileTransferCtlClass的另一个构造函数。如果对象需要在文件传输过程中显示,就应该调用这个构造函数。前三个参数和上一个构造函数的参数相同。myOwner引用一名所有者,它是一个chatApplet对象,将使用FileTransferCtlClass对象。由于示范代码是为从属于chatApplet的一个对象设计的,而chatApplet从一个Applet派生,所以myOwner的类型是chatApplet。 |
turnOff() | 该方法用于通知FileTransferCtlClass对象的所有者:文件传输已结束。FileTransferCtlClass对象不帮助它的所有者关闭其I/O Stream对象,这个工作将留给它的所有者进行,以期获得更好的灵活性。 |
run() | 发送者、接收者和File Router均已就绪后,调用该方法来执行文件传输。 |
long newTransferID() | 用这个方法获得一个新的TransferID,也就是用于文件传输的一个独一无二的标识符,它只是由开发者使用的一个引用。 |
long getTransferID() | 该方法获得当前TransferID。 |
boolean isCompleted() | 该方法检查在调用run()方法后,文件传输过程是否结束。 |
表C
TransferFrame | |
方法 | 说明 |
TransferFrame(FileTransferCtlClass myOwner) | 这个构造函数将创建一个Frame对象,以便显示来自FileTransferCtlClass对象myOwner的一条消息。 |
setEnabled(boolean myStatus) | 该方法指定TransferFrame对象是否能够显示。针对发送者或接收者(通常是一个Applet对象),TransferFrame对象被设为启用。但针对File Router,它被设为禁用,因为文件路由器可能不是Applet对象。 |
showMe() | 该方法要求TransferFrame对象显示自己。只有用setEnabled()方法设置了对象,允许它显示之后,showMe()方法才起作用。 |
setRate(float myRate) | FileTransferCtlClass对象用该方法显示文件传输完成百分比。 |
setMessage(String myMessage) | 该方法用于显示myMessage的一条消息。只有在成功调用了showMe()方法后,它才起作用。 |
close() | 该方法用于关闭TransferFrame对象。 |
由于本文重点在于说明两个applet之间不违反安全限制的文件传输机制,所以只准备解释FileTransferCtlClass::run()方法,它是执行文件传输的核心。但在此之前,需要看看如何在一个applet对象中使用类,以及如何使用中间人对象。