/// <summary>
/// GPRS自动连接服务
/// </summary>
public class ConnectionBLL
{
private static ConnectionBLL _ConnectionBLL = null;
private bool _autoConnect = false;
private int _interval = 30000;
private ConnectState _connectState;
private ConnectionBLL()
{
}
public static ConnectionBLL Instance
{
get
{
if (_ConnectionBLL == null)
{
lock (typeof(ConnectionBLL))
{
if (_ConnectionBLL == null)
{
_ConnectionBLL = new ConnectionBLL();
}
}
}
return _ConnectionBLL;
}
}
/// <summary>
/// 连接状态
/// </summary>
public ConnectState ConnectState
{
get { return _connectState; }
}
/// <summary>
/// 是否自动连接
/// </summary>
public bool AutoConnect
{
get { return _autoConnect; }
}
/// <summary>
/// 监听频率
/// </summary>
public int Interval
{
get { return _interval; }
set { _interval = value; }
}
const int S_OK = 0;
const uint CONNMGR_PARAM_GUIDDESTNET = 0x1;
const uint CONNMGR_PRIORITY_USERINTERACTIVE = 0x08000;
const uint INFINITE = 0xffffffff;
const uint CONNMGR_STATUS_CONNECTED = 0x10;
const int CONNMGR_MAX_DESC = 128; // @constdefine Max size of a network description
const int CONNMGR_FLAG_PROXY_HTTP = 0x1; // @constdefine HTTP Proxy supported
const int CONNMGR_FLAG_PROXY_WAP = 0x2; // @constdefine WAP Proxy (gateway) supported
const int CONNMGR_FLAG_PROXY_SOCKS4 = 0x4; // @constdefine SOCKS4 Proxy supported
const int CONNMGR_FLAG_PROXY_SOCKS5 = 0x8; // @constdefine SOCKS5 Proxy supported
const UInt16 IDC_WAIT = 32514;
const UInt16 IDC_ARROW = 32512;
private IntPtr m_hConnection = IntPtr.Zero;
public enum ConnMgrStatus
{
AuthenticationFailed = 0x2b,
Connected = 0x10,
ConnectionCanceled = 0x22,
ConnectionDisabled = 0x23,
ConnectionFailed = 0x21,
ConnectionLinkFailed = 0x2a,
Disconnected = 0x20,
ExclusiveConflict = 40,
NoPathToDestination = 0x24,
NoPathWithProperty = 0x2c,
NoResources = 0x29,
PhoneOff = 0x27,
Suspended = 0x11,
Unknown = 0,
WaitingConnection = 0x40,
WaitingConnectionAbort = 0x81,
WaitingDisconnection = 0x80,
WaitingForNetwork = 0x42,
WaitingForPath = 0x25,
WaitingForPhone = 0x26,
WaitingForResource = 0x41
}
public ConnectionBLL()
{
}
~ConnectionBLL()
{
ReleaseConnection();
}
/// <summary>
/// 开始连接
/// </summary>
public void Start()
{
try
{
if (!_autoConnect)
{
_autoConnect = true;
ThreadPool.QueueUserWorkItem(new WaitCallback(Connect));
}
}
catch
{
}
}
/// <summary>
/// 停止
/// </summary>
public void Stop()
{
try
{
_autoConnect = false;
this.ReleaseConnection();
_connectState = ConnectState.DisConnect;
_ConnectionBLL = null;
}
catch { }
}
/// <summary>
/// 连接
/// </summary>
private void Connect(object obj)
{
while (this.AutoConnect)
{
uint status = 0;
bool result = false;
if (m_hConnection != IntPtr.Zero)
{
result = WaitForConnected(10, ref status);
}
if (!result)
{
_connectState = ConnectState.DisConnect;
//枚举连接
List<CONNMGR_DESTINATION_INFO> lst = EnumConnDestinations();
for (int i = 0; i < lst.Count; i++)
{
string str = lst[i].Description;
if (str.ToUpper().IndexOf("CMNET") > -1 || str.ToUpper().IndexOf("CMWAP") > -1)
{
if (EstablishConnection((uint)i))
{
_connectState = ConnectState.Connected;
break;
}
}
}
}
else
{
_connectState = ConnectState.Connected;
}
Thread.Sleep(_interval);
}
}
/// <summary>
/// 枚举网络标识符信息
/// </summary>
/// <param name="lstNetIdentifiers"></param>
public List<CONNMGR_DESTINATION_INFO> EnumConnDestinations()
{
List<CONNMGR_DESTINATION_INFO> lstNetIdentifiers = new List<CONNMGR_DESTINATION_INFO>();
// 得到网络列表
for (uint dwEnumIndex = 0; ; dwEnumIndex++)
{
CONNMGR_DESTINATION_INFO networkDestInfo = new CONNMGR_DESTINATION_INFO();
if (ConnMgrEnumDestinations((int)dwEnumIndex, ref networkDestInfo) != 0)
{
break;
}
lstNetIdentifiers.Add(networkDestInfo);
}
return lstNetIdentifiers;
}
/// <summary>
/// 建立连接
/// </summary>
/// <param name="nIndex"></param>
/// <returns></returns>
public bool EstablishConnection(uint nIndex)
{
ReleaseConnection();
// 得到正确的连接信息
CONNMGR_DESTINATION_INFO DestInfo = new CONNMGR_DESTINATION_INFO();
int hResult = ConnMgrEnumDestinations((int)nIndex, ref DestInfo);
if (hResult >= 0)
{
// 初始化连接结构
CONNMGR_CONNECTIONINFO ConnInfo = new CONNMGR_CONNECTIONINFO();
ConnInfo.cbSize = (uint)Marshal.SizeOf(ConnInfo);
ConnInfo.dwParams = CONNMGR_PARAM_GUIDDESTNET;
ConnInfo.dwFlags = CONNMGR_FLAG_PROXY_HTTP | CONNMGR_FLAG_PROXY_WAP | CONNMGR_FLAG_PROXY_SOCKS4 | CONNMGR_FLAG_PROXY_SOCKS5;
ConnInfo.dwPriority = CONNMGR_PRIORITY_USERINTERACTIVE;
ConnInfo.guidDestNet = DestInfo.DestID;
ConnInfo.bExclusive = 1;
ConnInfo.bDisabled = 0;
uint dwStatus = 0;
hResult = ConnMgrEstablishConnectionSync(ref ConnInfo, ref m_hConnection, 10 * 1000, ref dwStatus);
if (hResult < 0)
{
return false;
}
else
{
return true;
}
}
return false;
}
/// <summary>
/// 连接状态
/// </summary>
/// <param name="nTimeoutSec"></param>
/// <param name="pdwStatus"></param>
/// <returns></returns>
public bool WaitForConnected(int nTimeoutSec, ref uint pdwStatus)
{
uint dwStartTime = GetTickCount();
bool bRet = false;
while (GetTickCount() - dwStartTime < (uint)nTimeoutSec * 1000)
{
if (m_hConnection.ToInt32() != 0)
{
uint dwStatus = 0;
int hr = ConnMgrConnectionStatus(m_hConnection, ref dwStatus);
if (dwStatus != 0) pdwStatus = dwStatus;
if (hr >= 0)
{
if (dwStatus == CONNMGR_STATUS_CONNECTED)
{
bRet = true;
break;
}
}
}
Thread.Sleep(100);
}
return bRet;
}
/// <summary>
/// 释放所有连接
/// </summary>
public void ReleaseConnection()
{
if (m_hConnection.ToInt32() != 0)
{
ConnMgrReleaseConnection(m_hConnection, 0);
m_hConnection = IntPtr.Zero;
}
}
[StructLayout(LayoutKind.Sequential)]
public struct CONNMGR_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;
}
/// <summary>
/// 此结构的内容对应:注册表中:
/// </summary>
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct CONNMGR_DESTINATION_INFO
{
public GUID DestID; // @field GUID associated with network
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = CONNMGR_MAX_DESC)]
public string Description; // @field Description of network
public int Secure; // @field Is it OK to allow multi-homing on the network
}
public struct GUID
{ // size is 16
public uint Data1;
public UInt16 Data2;
public UInt16 Data3;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
public byte[] Data4;
}
[DllImport("coredll.dll")]
public static extern uint GetTickCount();
[DllImport("coredll.dll")]
public static extern uint WaitForSingleObject(IntPtr hHandle, uint dwMilliseconds);
[DllImport("cellcore.dll")]
public static extern int ConnMgrMapURL(string pwszURL, ref GUID pguid, ref uint pdwIndex);
[DllImport("cellcore.dll")]
public static extern int ConnMgrEstablishConnectionSync(ref CONNMGR_CONNECTIONINFO ci, ref IntPtr phConnection, uint dwTimeout, ref uint pdwStatus);
[DllImport("cellcore.dll")]
private static extern IntPtr ConnMgrApiReadyEvent();
[DllImport("cellcore.dll")]
public static extern int ConnMgrReleaseConnection(IntPtr hConnection, int bCache);
[DllImport("cellcore.dll")]
public static extern int ConnMgrEnumDestinations(int nIndex, ref CONNMGR_DESTINATION_INFO pDestInfo);
[DllImport("cellcore.dll")]
public static extern int ConnMgrConnectionStatus(IntPtr hConnection, // @parm Handle to connection, returned from ConnMgrEstablishConnection
ref uint pdwStatus // @parm Returns current connection status, one of CONNMGR_STATUS_*
);
[DllImport("coredll.dll")]
private static extern int CloseHandle(IntPtr hObject);
}
/// <summary>
/// 连接状态
/// </summary>
public enum ConnectState
{
/// <summary>
/// 断开
/// </summary>
DisConnect = 0,
/// <summary>
/// 已连接
/// </summary>
Connected = 2
}
注意:为了加快连接速度,这里指定了连接移动的CMNET和CMWAP,可以根据需要修改,也可以不指定。