您的位置:首页 > 其它

利用命名管道(Named Pipe)向Flash Player模拟Flash媒体文件

2005-03-14 23:43 453 查看
  多样、互动的WinForm UI设计与开发思路一文中,我提到过把Flash作为控件嵌入到WinForm程序中以提高软件的互动效果并降低开发难度这样一种思路。但这样一个系统,我们往往不希望随应用程序打包,或者让用户看到,很多很多的FLASH文件。其中一个办法就是把flash文件作为资源嵌入到系统中。但这样又出现一个问题,Flash Player只有一个Movie属性用于指定当前播放的媒体,而这个字符串属性只能是本地文件或者一个URL。我们可以在运行时把资源里的flash释放到一个临时目录,但这样一来失去了打包的意义,二来无法保护flash文件。

  我们希望最好的解决方案,就是Flash Player提供类似于DataSet.ReadXml()这样的方法,既可以从指定名字的Xml文件读取数据,又可以从一个数据流(Stream)读数据。但是找遍了Flash Player的所有参数,似乎只有MovieData这个属性有点接近,如果我们能直接把Flash文件的内容赋值给它就好了。不过目前我还没有找到关于这个属性的资料 -_-

  另外一个思路,就是在我们的程序运行的时候,动态建立一个自己的http服务器,可以直接从资源中读取内容。事实上,对于大部分要求文件或url形式的内容,都可以通过建立虚拟http服务器来模拟。但实现起来要费点功夫,而且http会在本机留下缓存,安全性不高。

  最后在whoo从内存播放Flash一文找到了另外一种方法,就是通过命名管道(Named Pipe)。

首先我们看看命名管道为什么能够解决这个问题。这要从它的运行机制讲起。当一个命名管道被建立起来后,它的服务端和客户端之间的数据交流,就完全是通过和操作文件一样的方式来进行,即CreateFile(),ReadFile()和WriteFile()三个函数。也就是说客户端可以像读取文件一样,来读取管道里的数据。

  我们通过调用Win32 API 既可创建管道。这里先简单讲一下服务器端的处理流程:

  1、通过CreateNamedPipe()函数创建一个命名管道,如果成功,会返回这个管道实例的句柄。

  2、管道创建成功后,调用ConnectNamedPipe()函数等到客户端连接。

  3、如果有客户端连接进来,可以通过对文件的操作来交换数据,例如ReadFile()和WriteFile()。

  在.NET里我们不必用这些Win32 API函数来读写文件,直接用System.IO命名空间下的类即可(将文件读写的内存指针指向管道句柄即可)。

  注:目前该方法只针对在Flash Player播放器打开 \\.\pipe\testPipe 才有效。如果您使用的是Flash Player 7.0,那么一定要用 \\?\pipe\testPipe才行。

  至于在html页面或WinForm里的Flash Player控件,指定其Movie属性为"\\.\pipe\testPipe",目前尚无效。

  以下是简单的例子:

using System;

using System.IO;

using System;

using System.Runtime.InteropServices;

namespace PipeServer 

    public class API 

        public const int INVALID_HANDLE_VALUE = -1;

        public const int PIPE_ACCESS_INBOUND = 0x1;

        public const int PIPE_ACCESS_OUTBOUND = 0x2;

        public const int PIPE_ACCESS_DUPLEX = 0x3;

        public const int PIPE_WAIT = 0x0;

        public const int PIPE_UNLIMITED_INSTANCES = 255;

        [DllImport("kernel32.dll", EntryPoint="CreateNamedPipe")]

        public static extern int CreateNamedPipe (

            string lpName,

            int dwOpenMode,

            int dwPipeMode,

            int nMaxInstances,

            int nOutBufferSize,

            int nInBufferSize,

            int nDefaultTimeOut,

            ref SECURITY_ATTRIBUTES lpSecurityAttributes

        );

        [StructLayout(LayoutKind.Sequential)]

            public struct SECURITY_ATTRIBUTES             public int nLength;

            public int lpSecurityDescriptor;

            public int bInheritHandle;

        }

        [DllImport("kernel32.dll", EntryPoint="ConnectNamedPipe")]

        public static extern int ConnectNamedPipe (

            int hNamedPipe,

            ref OVERLAPPED lpOverlapped

        );

        [StructLayout(LayoutKind.Sequential)]

            public struct OVERLAPPED             public int Internal;

            public int InternalHigh;

            public int offset;

            public int OffsetHigh;

            public int hEvent;

        }

        [DllImport("kernel32.dll", EntryPoint="CloseHandle")]

        public static extern int CloseHandle (

            int hObject

        );

        [DllImport("kernel32.dll", EntryPoint="DisconnectNamedPipe")]

        public static extern int DisconnectNamedPipe (

            int hNamedPipe

        );

    }

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: