在Windows Mobile中管理网络状态的最佳方法是什么?

6
我有一个.NET Compact Framework 3.5程序,用作“偶尔连接”业务(LOB)应用程序。如果它能看到在线的网络服务,它将使用该服务进行数据访问,但如果网络连接丢失,则会使用本地缓存。
如何处理所有连接选项和状态更改是最好的方式?
  • OpenNetCF的ConnectionManager类?
  • Microsoft.WindowsBile.State.SystemState?
  • API调用?
如何让它理解WiFi、Cradle和GPRS之间的区别,并使用可用的最佳方法?
是否有任何指导意见?
4个回答

2
我刚刚创建了一个简单的共享类,可以像这样调用它:
If MyConnectionClass.IsConnected then
     'Do connected stuff
Else
     'Do local save
End If

我的所有实际业务类/函数都可以使用此功能将其隐藏,以免UI代码受到影响。

MyConnectionClass的IsConnected属性可能会像这样:

Public ReadOnly Property IsConnected As Boolean
   Get
    Try

        Dim HostName As String = Dns.GetHostName()
        Dim thisHost As IPHostEntry = Dns.GetHostByName(HostName)
        Dim thisIpAddr As String = thisHost.AddressList(0).ToString

        return (thisIpAddr <> Net.IPAddress.Parse("127.0.0.1").ToString())

    Catch ex As Exception
        Return False
    End Try
   End Get
End Property

建议您使用后台线程轮询连接状态,并在状态改变时向主应用程序线程发送事件。以下是详细的撰写内容:在.NET Compact Framework中测试和响应网络连接
编辑:现在,对于GPRS支持:
如果您正在使用Web请求或Web服务,则框架将为您处理连接。如果您更深入地使用TCPClient或UDPClient,则需要自己使用连接管理器API处理连接。
public class GPRSConnection
{
    const int S_OK = 0;
    const uint CONNMGR_PARAM_GUIDDESTNET = 0x1;
    const uint CONNMGR_FLAG_PROXY_HTTP = 0x1;
    const uint CONNMGR_PRIORITY_USERINTERACTIVE = 0x08000;
    const uint INFINITE = 0xffffffff;
    const uint CONNMGR_STATUS_CONNECTED = 0x10;
    static Hashtable ht = new Hashtable();

    static GPRSConnection()
    {
        ManualResetEvent mre = new ManualResetEvent(false);
        mre.Handle = ConnMgrApiReadyEvent();
        mre.WaitOne();
        CloseHandle(mre.Handle);
    }

    ~GPRSConnection()
    {
        ReleaseAll();
    }

    public static bool Setup(Uri url)
    {
        return Setup(url.ToString());
    }

    public static bool Setup(string urlStr)
    {
        ConnectionInfo ci = new ConnectionInfo();
        IntPtr phConnection = IntPtr.Zero;
        uint status = 0;

        if (ht[urlStr] != null)
            return true;

        if (ConnMgrMapURL(urlStr, ref ci.guidDestNet, IntPtr.Zero) != S_OK)
            return false;

        ci.cbSize = (uint) Marshal.SizeOf(ci);
        ci.dwParams = CONNMGR_PARAM_GUIDDESTNET;
        ci.dwFlags = CONNMGR_FLAG_PROXY_HTTP;
        ci.dwPriority = CONNMGR_PRIORITY_USERINTERACTIVE;
        ci.bExclusive = 0;
        ci.bDisabled = 0;
        ci.hWnd = IntPtr.Zero;
        ci.uMsg = 0;
        ci.lParam = 0;

        if (ConnMgrEstablishConnectionSync(ref ci, ref phConnection, INFINITE, ref status) != S_OK &&
            status != CONNMGR_STATUS_CONNECTED)
            return false;

        ht[urlStr] = phConnection;
        return true;
    }

    public static bool Release(Uri url)
    {
        return Release(url.ToString());
    }

    public static bool Release(string urlStr)
    {
        return Release(urlStr, true);
    }

    private static bool Release(string urlStr, bool removeNode)
    {
        bool res = true;
        IntPtr ph = IntPtr.Zero;
        if (ht[urlStr] == null)
            return true;
        ph = (IntPtr)ht[urlStr];
        if (ConnMgrReleaseConnection(ph, 1) != S_OK)
            res = false;
        CloseHandle(ph);
        if (removeNode)
            ht.Remove(urlStr);
        return res;
    }

    public static void ReleaseAll()
    {
       foreach(DictionaryEntry de in ht)
       {
           Release((string)de.Key, false);
       }
       ht.Clear();
    }

    [StructLayout(LayoutKind.Sequential)]
    public struct ConnectionInfo
    {
        public uint cbSize;
        public uint dwParams;
        public uint dwFlags;
        public uint dwPriority;
        public int bExclusive;
        public int bDisabled;
        public Guid guidDestNet;
        public IntPtr hWnd;
        public uint uMsg;
        public uint lParam;
        public uint ulMaxCost;
        public uint ulMinRcvBw;
        public uint ulMaxConnLatency;
    }

    [DllImport("cellcore.dll")]
    private static extern int ConnMgrMapURL(string pwszURL, ref Guid pguid, IntPtr pdwIndex);

    [DllImport("cellcore.dll")]
    private static extern int ConnMgrEstablishConnectionSync(ref ConnectionInfo ci, ref IntPtr phConnection, uint dwTimeout, ref uint pdwStatus);

    [DllImport("cellcore.dll")]
    private static extern IntPtr ConnMgrApiReadyEvent();

    [DllImport("cellcore.dll")]
    private static extern int ConnMgrReleaseConnection(IntPtr hConnection, int bCache);

    [DllImport("coredll.dll")]
    private static extern int CloseHandle(IntPtr hObject);
}

使用它,只需执行以下操作:

public void DoTcpConnection()
    {
        string url = "www.msn.com";
        bool res = GPRSConnection.Setup("http://" + url + "/");
        if (res)
        {
            TcpClient tc = new TcpClient(url, 80);
            NetworkStream ns = tc.GetStream();
            byte[] buf = new byte[100];
            ns.Write(buf, 0, 100);
            tc.Client.Shutdown(SocketShutdown.Both);
            ns.Close();
            tc.Close();
            MessageBox.Show("Wrote 100 bytes");
        }
        else
        {
            MessageBox.Show("Connection establishment failed");
        }
    }

这是来自Anthony Wong的博客:Anthony Wong。请记住,只有在涉及较低级别的TCP或UDP内容时才需要使用此方法。HTTP请求不需要这样做。

我该如何告诉它尝试连接(即在可用情况下启动GPRS)?发布的方法(和链接)似乎只适用于WiFi,其中连接只有开或关的状态。 - JasonRShaver

1

你考虑过在Microsoft.WindowsMobile.Status命名空间使用SystemState类吗? 你可以监视系统的当前状态并在状态更改时获取通知。 查看此文章以获取一些代码。

SystemState仅涉及连接状态。 你可以通过ConnectionManager使用特定的连接。 我建议阅读此文章。 如果你正在使用.NET Compact Framework 3.5,则已包含托管API。 你也可以使用OpenNetCF ConnectionManager。


我该如何使用SystemState来告诉它尝试连接(即如果可用则启动GPRS)? - JasonRShaver

1

我尝试编写移动应用程序,使它们甚至不知道有网络参与其中。我在本地保留足够好的验证数据,然后将事务写入本地队列,该队列在连接时清除;队列读取器包括一个计时器,在未连接时重试。队列消息是双向的,因此也可以提供本地刷新。基本的消息队列模式。

这使我能够以最简单的方式处理网络连接,使用基本的套接字打开/关闭/读取/写入/ioctl逻辑,这些逻辑高度可移植;您的连接根本不需要持续任何显着的时间。(我不敢想象在过去几年中与所有MS架构变化保持同步所需的工作量 - 在我看来,这仍然没有解决。)


我非常赞同你所写的,我曾经有一个移动应用程序,当没有WiFi时,将切换到使用SMS协议。由于我在CE的CLSA中构建了一个基于“消息队列”的传输系统,这很容易实现。我希望我仍然可以使用它,但该项目放弃了电话选项 =( - JasonRShaver

1

我发现Microsoft.WindowsMobile.State.SystemState报告网络连接的可靠性不高,这是在6.0及之前版本出现的情况。虽然我没有进行详尽的测试,但当它显示没有连接时实际上已经连接了,因此我放弃了使用它。


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