65.9K
CodeProject 正在变化。 阅读更多。
Home

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

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.91/5 (34投票s)

2003 年 6 月 30 日

2分钟阅读

viewsIcon

204875

downloadIcon

3579

一个用于连接和断开拨号上网会话的 Web 应用程序

Sample Image - webdialup.gif

引言

我最近更改了我的家庭网络,基本上是添加了一个服务器来将网络连接到互联网。不幸的是,我住的地方无法使用宽带互联网,因此互联网连接服务器需要拨号连接到我们的 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 修复,如果用户有多个拨号上网电话簿,他们可能会遇到一些问题。
© . All rights reserved.