Windows Mobile上的GPRS连接(基于TcpClient)
在有线的连接和WIFI都不可用的时候, .NET CF的HttpWebRequest会由于web requests/web services 而自动设置GPRS连接。所以实际上当你发起一个Web请求或者连接Webservice的时候,并不需要开发者编码处理GPRS的连接问题。不过对于更低层的通信,如使用TcpClient 和 UdpClient的时候,则需要使用 Connection Manager API来建立和释放连接。
(本文英文原文见:)
以下托管类是对Connection Manager 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); }
使用GPRSConnection class的时候, 先调用Setup方法创建连接,见以下代码:
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"); } }
Enjoy,
黄季冬