我有一个.NET Compact Framework 3.5程序,用作“偶尔连接”的业务线(LOB)应用程序。如果它可以看到在线Web服务,它将使用它进行数据访问,但如果网络连接丢失,它将使用本地缓存。
处理所有连接选项和状态更改的最佳方法是什么?
如何理解WiFi,Cradle和GPRS之间的区别并使用最佳方法?
有人对此有任何指导吗?
答案 0 :(得分: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
还建议您使用后台线程轮询连接状态,然后在状态更改时将事件激活回主应用程序线程。这是详细的文章:
Testing for and responding to network connections in the .NET Compact Framework
修改强>
现在,对于 GPRS 支持:
如果您使用Web请求或Web服务,框架将为您处理连接。如果你深入研究TCPClient或UDPClient,你需要自己使用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);
}
要使用它,请执行以下操作:
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的博客:
请记住,您只需要更低级别的TCP或UDP内容。 HTTPRequests不需要这个。
答案 1 :(得分:1)
在Microsoft.WindowsMobile.Status命名空间中使用SystemState类怎么样?当状态发生变化时,您可以监视系统的当前状态并获取通知。有关一些代码,请参阅此post。
SystemState仅与连接状态有关。您可以通过ConnectionManager使用特定连接。我建议你阅读article。如果您使用的是.NET Compact Framework 3.5,则会包含托管API。您也可以使用OpenNetCF ConnectionManager。
答案 2 :(得分:1)
我尝试编写移动应用程序,因此他们甚至不知道有涉及的网络。我在本地保留了足够好的验证数据,然后将事务写入本地队列,该队列在连接时清除;队列读取器包括一个未连接时重试的计时器。队列消息是双向的,因此也可以提供本地刷新。基本消息队列模式。
这允许我以最简单的方式处理网络连接,使用高度可移植的基本套接字打开/关闭/读/写/ ioctl逻辑;并且您的连接不需要持续任何重要的时间。 (我不想想在过去几年中与所有MS架构变化保持同步所需要的东西 - 这仍然没有解决恕我直言。)
答案 3 :(得分:1)
我发现Microsoft.WindowsMobile.State.SystemState报告的网络连接不可靠。这是6.0及更早。我没有进行详尽的测试,但是当它出现时没有连接就被放弃了。