随着大家对数据传书安全性的重视,越来越多的用户在建设自己企业的无线解决方案时,选择APN作为数据传输通道,是应用程序采用自己专有的通道进行数据传出,这样,其他非企业内部用户便无法访问企业架构的服务器,大大提供企业无线方案本身的安全性。
专有通道是不可以连接到Internet公网上的。而用户本身,花了几K的MONEY,不可能只用来办公,用户对设备连接公网具有强烈的需求。然而,在技术角度,很难将应用程序绑定到固定的通道上,特别是使用C#语言连接WEB SERVICE进行通讯时,该程序便解决了这个问题。
当然,如果使用底层API很容易达到这个效果,但,当前做Windows Mobile开发的人,很少有即懂得EVC又懂得C#的人,如果您刚好是这种人才,您不需要对本人的文章进行任何参考,可以直接封装底层API中的四个方法为一个DLL,然后进行调用。
在底层API中,包含以下四个方法
[DllImport("cellcore.dll", EntryPoint = "ConnMgrReleaseConnection", SetLastError = true)]
internal static extern int ConnMgrReleaseConnection(IntPtr hConnection, int bCache);
[DllImport("cellcore.dll", EntryPoint = "ConnMgrEstablishConnection", SetLastError = true)]
internal static extern int ConnMgrEstablishConnection(IntPtr pConnInfo, out IntPtr phConnection);
[DllImport("cellcore.dll", EntryPoint = "ConnMgrEstablishConnectionSync", SetLastError = true)]
internal static extern int ConnMgrEstablishConnectionSync(IntPtr pConnInfo, out IntPtr phConnection, int dwTimeout, out int dwStatus);
[DllImport("cellcore.dll", EntryPoint = "ConnMgrEnumDestinations", SetLastError = true)]
internal static extern int ConnMgrEnumDestinations(int nIndex, IntPtr pDestinationInfo);
[DllImport("cellcore.dll", EntryPoint = "ConnMgrMapURL", SetLastError = true)]
internal static extern int ConnMgrMapURL(string pwszUrl, ref Guid pguid, ref int pdwIndex);
[DllImport("cellcore.dll", EntryPoint = "ConnMgrConnectionStatus", SetLastError = true)]
internal static extern int ConnMgrConnectionStatus(IntPtr hConnection, out int pdwStatus);
这四个方法的具体含义,这里不做详细介绍,大家可以在MSDN中查到,如果查不到,可以找高人请教一下。
本模块首先要导入这四个方法,如上面的代码片段,然后就是对连接对象DestinationInfo的封装了,该对象的原型,这里不再列举,下面为封装好的结构
public class DestinationInfo
{
private object syncRoot = new object();
/// <summary>
/// Size of the DestinationInfo structure in unmanaged memory.
/// </summary>
public static int NativeSize = 272;
/// <summary>
/// The destination's GUID identifier.
/// </summary>
public Guid guid;
/// <summary>
/// The destination's description.
/// </summary>
public string description = null;
/// <summary>
/// Default constructor.
/// </summary>
public DestinationInfo()
{
}
public override string ToString()
{
return description;
}
/// <summary>
/// Creates a new instance of DestinationInfo at the specific memory address.
/// </summary>
/// <param name="baseAddr">Memory address where the DestinationInfo object should be created.</param>
public DestinationInfo(IntPtr baseAddr)
{
lock (syncRoot)
{
guid = new Guid(MarshalEx.ReadByteArray(baseAddr, 0, 16));
description = MarshalEx.PtrToStringUni(baseAddr, 16, 256);
}
}
}
接下来封装ConnectionInfo结构
internal struct ConnectionInfo
{
public int cbSize;
public int dwParams;
public int dwFlags;
public int dwPriority;
public bool bExclusive;
public bool bDisabled;
public Guid guidDestNet;
public IntPtr hWnd;
public int uMsg;
public int lParam;
int ulMaxCost;
int ulMinRcvBw;
int ulMaxConnLatency;
internal IntPtr handle;
/// <summary>
/// Writes the ConnectionInfo data to unmanaged memory.
/// </summary>
/// <returns>A pointer to the unmanaged memory block storing the ConnectionInfo data</returns>
public IntPtr ToPtr()
{
// ulMaxCost = 0;
// ulMinRcvBw = 0;
// ulMaxConnLatency = 0;
IntPtr p = MarshalEx.AllocHLocal((uint)Marshal.SizeOf(typeof(ConnectionInfo)));
MarshalEx.WriteInt32(p, 0, this.cbSize);
MarshalEx.WriteInt32(p, 4, this.dwParams);
MarshalEx.WriteInt32(p, 8, this.dwFlags);
MarshalEx.WriteInt32(p, 12, this.dwPriority);
MarshalEx.WriteBool(p, 16, this.bExclusive);
MarshalEx.WriteBool(p, 20, this.bDisabled);
MarshalEx.WriteByteArray(p, 24, this.guidDestNet.ToByteArray());
MarshalEx.WriteIntPtr(p, 40, this.hWnd);
MarshalEx.WriteInt32(p, 44, this.uMsg);
MarshalEx.WriteInt32(p, 48, this.lParam);
MarshalEx.WriteInt32(p, 52, this.ulMaxCost);
MarshalEx.WriteInt32(p, 56, this.ulMinRcvBw);
MarshalEx.WriteInt32(p, 60, this.ulMaxConnLatency);
// Marshal.WriteByte(p,
handle = p;
return p;
}
/// <summary>
/// Disposes of the ConnectionInfo object.
/// </summary>
public void Dispose()
{
this.hWnd = IntPtr.Zero;
if (handle != IntPtr.Zero)
MarshalEx.FreeHLocal(handle);
}
};
这样,所有的准备工作都已经做好,就剩下封装一个对外的方法了,起名为ConnectionManager,代码如下
该对象负责对外提供枚举连接个数、选择某个连接进行连接、断开当前连接,以及在连接开始、连接成功、连接断开、连接报错时提供对外的事件通知,由于代码过多,在这里不粘贴。OK,一起准备完成。
在WINDOWS MOBILE 2003SE,Windows Mobile5.0 以及Windows Mobile6.0中测试通过。