基于 Web 的拨号上网应用程序






4.91/5 (34投票s)
2003 年 6 月 30 日
2分钟阅读

204875

3579
一个用于连接和断开拨号上网会话的 Web 应用程序
引言
我最近更改了我的家庭网络,基本上是添加了一个服务器来将网络连接到互联网。不幸的是,我住的地方无法使用宽带互联网,因此互联网连接服务器需要拨号连接到我们的 ISP。我需要一种简单的方法来连接、断开连接并查看连接持续了多长时间。通常我会使用终端服务来建立和查看连接,但是由于我的妻子也使用互联网,所以我需要另一种更简单的方法,一种甚至我的妻子也可以使用的方法。我构建了这个 Web 应用程序,它显示当前连接的统计信息或显示电话簿条目,以便用户可以连接。
使用代码
我封装了一些 RAS API,以便我可以将它们与 P/Invoke 一起使用。 它们是
RasEnumConnections
RasGetConnectionStatistics
RasHangUp
RasEnumEntries
InternetDial
我还必须创建一些这些 API 可以使用的结构
RASCONN
RasEntryName
RasStats
我创建了一个简单的类,名为 RASDisplay
,它具有以下方法和属性
方法
int Connect(string Connection)
void Disconnect()
属性
bool IsConnected
string ConnectionName
double BytesReceived
double BytesTransmitted
string[] Connections
string Duration
RASDisplay
类负责使用 RAS API 的所有复杂性。 如果您不熟悉使用 RAS API,则必须传入结构大小,以便 API 知道您正在使用的版本。 此类的构造函数使用以下代码来设置上述属性
private string m_duration;
private string m_ConnectionName;
private string[] m_ConnectionNames;
private double m_TX;
private double m_RX;
private bool m_connected;
private IntPtr m_ConnectedRasHandle;
public RASDisplay()
{
m_connected = true;
RAS lpras = new RAS();
RASCONN lprasConn = new RASCONN();
lprasConn.dwSize = Marshal.SizeOf(typeof(RASCONN));
lprasConn.hrasconn = IntPtr.Zero;
int lpcb = 0;
int lpcConnections = 0;
int nRet = 0;
lpcb = Marshal.SizeOf(typeof(RASCONN));
nRet = RAS.RasEnumConnections(ref lprasConn, ref lpcb,
ref lpcConnections);
if(nRet != 0)
{
m_connected = false;
return;
}
if(lpcConnections > 0)
{
RasStats stats = new RasStats();
m_ConnectedRasHandle = lprasConn.hrasconn;
RAS.RasGetConnectionStatistics(lprasConn.hrasconn, stats);
m_ConnectionName = lprasConn.szEntryName;
//Work out our duration
int Hours = 0;
int Minutes = 0;
int Seconds = 0;
//The RasStats duration is in milliseconds
Hours = ((stats.dwConnectDuration /1000) /3600);
Minutes = ((stats.dwConnectDuration /1000) /60) -
(Hours * 60);
Seconds = ((stats.dwConnectDuration /1000)) -
(Minutes * 60) - (Hours * 3600);
m_duration = Hours + " hours " + Minutes +
" minutes " + Seconds + " secs";
//set the bytes transferred and received
m_TX = stats.dwBytesXmited;
m_RX = stats.dwBytesRcved;
}
else
{
//we aren't connected
m_connected = false;
}
//Find the names of the connections we could dial
int lpNames = 1;
int entryNameSize=Marshal.SizeOf(typeof(RasEntryName));
int lpSize=lpNames*entryNameSize;
RasEntryName[] names=new RasEntryName[lpNames];
for(int i=0;i<names.Length;i++)
{
names[i].dwSize=entryNameSize;
}
uint retval = RAS.RasEnumEntries(null,null,names,
ref lpSize,out lpNames);
m_ConnectionNames = new string[lpNames];
if(lpNames>0)
{
for(int i=0;i<lpNames;i++)
{
m_ConnectionNames[i] = names[i].szEntryName;
}
}
}
连接到互联网的代码使用 InternetDial WinInet API
public int Connect(string sConnection)
{
int intConnection = 0;
uint INTERNET_AUTO_DIAL_UNATTENDED = 2;
int retVal = RAS.InternetDial(IntPtr.Zero, sConnection,
INTERNET_AUTO_DIAL_UNATTENDED,ref intConnection,0);
return retVal;
}
断开连接的代码也非常简单
public void Disconnect()
{
RAS.RasHangUp(m_ConnectedRasHandle);
}
使用 RASDisplay
类的 Web 应用程序如下所示
protected System.Web.UI.WebControls.Label lblName;
protected System.Web.UI.WebControls.Label lblDuration;
protected System.Web.UI.WebControls.Label lblTransmitted;
protected System.Web.UI.WebControls.DataGrid dgAllConnections;
protected System.Web.UI.HtmlControls.HtmlTable tblCurrentConnection;
protected System.Web.UI.WebControls.Button btnDisconnect;
protected System.Web.UI.WebControls.Label lblRecieved;
private void Page_Load(object sender, System.EventArgs e)
{
if(!IsPostBack)
{
BindData();
}
}
private void BindData()
{
try
{
RASDisplay display = new RASDisplay();
lblName.Text = display.ConnectionName;
lblDuration.Text = display.Duration;
lblRecieved.Text = display.BytesReceived.ToString();
lblTransmitted.Text = display.BytesTransmitted.ToString();
if(!display.IsConnected)
{
//show the table with stats
tblCurrentConnection.Visible = false;
}
else
{
//show the tables with available connections
dgAllConnections.Visible = false;
}
//bind the data
dgAllConnections.DataSource = display.Connections;
dgAllConnections.DataBind();
}
catch(Exception e){
Response.Write(e.Message);
}
}
protected void btnConnect_Click(object sender, EventArgs e)
{
RASDisplay rasDisplay = new RASDisplay();
//need to find the text in the first column of the datagrid
Button btnSender = (Button) sender;
DataGridItem ob = (DataGridItem) btnSender.Parent.Parent;
int ErrorVal = rasDisplay.Connect(ob.Cells[1].Text);
if(ErrorVal != 0)
{
Response.Write(ErrorVal);
}
else
{
//redirect to the same page, so the display
//is refreshed with stats
Response.Redirect("Default.aspx");
}
}
protected void btnDisConnect_Click(object sender, EventArgs e)
{
RASDisplay rasDisplay = new RASDisplay();
rasDisplay.Disconnect();
//redirect to the same page, so the display is
//refreshed with available connections
Response.Redirect("Default.aspx");
}
Web 应用程序具有一个 DataGrid
,它显示机器上的所有连接,只有在计算机未连接到互联网时才会显示此 DataGrid
。 否则,将显示包含连接统计信息的表格。 网页有一个 meta refresh 标签,以保持统计信息最新。
已知问题
目前,Connect
方法调用 InternetDial,此方法采用连接的名称。 如果此连接没有保存密码,则调用将失败。 在未来的版本中,我想更改应用程序连接到互联网的方式,也许使用 RASDial
并让应用程序存储用户的用户名和密码(或者要求他们输入?)
历史
- 文章创建时间:2003 年 6 月 30 日
- 更新于 2003 年 7 月 7 日 -只是一个 Bug 修复,如果用户有多个拨号上网电话簿,他们可能会遇到一些问题。