MFC_9.14_客戶端註冊登陸,服務器匹配用戶名密碼

客戶端註冊登陸,服務器匹配用戶名密碼

  • 資源視圖建立對話框style->puptop,更改ID爲IDD_DIA_JOIN,添加基於CDialog類Sign_Join
  • 添加兩個編輯框變量名分別是m_edit1m_edit2,然後添加按鈕,三個,功能分別是註冊,登陸,和退出
  • 更改CDialog.h中的結構體和協議號的定義,相應的,在另一個程序裏Server.h文件中做同樣修改
enum{
    //定義協議編號
    INF_ADD = 0x1234,
    INF_BROW,
    INF_JOIN,
    INF_LOGIN,
    INF_FIND

};

struct ServerData 
{
    //信息數據
    int Row;
    int Column;
    int Num;
    char Account[200];
    char Pass[200];
    bool flag;
};
#include "afxwin.h"
  • 設置登陸對話框的彈出位置,資源視圖,右邊屬性,重寫函數OnPaint()
void Sign_Join::OnPaint()
{
    CPaintDC dc(this); // device context for painting
    // TODO: 在此處添加消息處理程序代碼
    int xSize = ::GetSystemMetrics (SM_CXSCREEN);
    int ySize = ::GetSystemMetrics (SM_CYSCREEN);
    //設置窗口大小
    int cx = (xSize*2)/6;
    int cy = (ySize*3)/6;
    //設置顯示位置
    int x = (xSize-cx)/2;
    int y = (ySize-cy)/2;

    //設置主窗口位置和大小
    CWnd::MoveWindow(CRect(x,y,cx+x,cy+y));
    // 不爲繪圖消息調用 CDialog::OnPaint()
}

客戶端

  • 一、客戶端中初始化及三個按鈕響應函數的實現,雙擊開啓函數
  • 1、初始化,登陸註冊新建一個Socket進行與服務器的鏈接
  • Sign_Join.h中,加一句
// Sign_Join 對話框

class Sign_Join : public CDialog
{
    CSocket sock;
  • 資源視圖下,登陸註冊對話框右邊屬性窗口,重寫函數OnInitDialog()
BOOL Sign_Join::OnInitDialog()
{
    CDialog::OnInitDialog();

    // TODO:  在此添加額外的初始化
    SetWindowText("登陸/註冊");
    //設置退出X禁用,不然點掉了直接跳出主程序窗口,登陸就無效了
    ::EnableMenuItem(::GetSystemMenu(this->m_hWnd, false), SC_CLOSE, MF_BYCOMMAND | MF_GRAYED);//forbid close

    sock.Create();
    if (!sock.Connect("127.0.0.1",8668))//修改爲自己的IP
    {
        AfxMessageBox("連接失敗:無法連接服務器,請檢查你的網絡連接!");
            EndDialog(IDCANCEL);
        return FALSE;
    }

    return TRUE;  // return TRUE unless you set the focus to a control
    // 異常: OCX 屬性頁應返回 FALSE
}
  • 2、註冊按鈕的函數響應,都在Sign_Join.cpp文件中
void Sign_Join::OnBnClickedButton1()
{
    // TODO: 在此添加控件通知處理程序代碼
    CString m_Sign_Account,m_Sign_Pass;
    m_edit1.GetWindowText(m_Sign_Account); 
    m_edit2.GetWindowText(m_Sign_Pass);
    //檢查輸入是否爲空,去除左右空格
    m_Sign_Account.TrimLeft();
    m_Sign_Account.TrimRight();
    m_Sign_Pass.TrimLeft();
    m_Sign_Pass.TrimRight();

    if((m_Sign_Account=="")||(m_Sign_Pass==""))
    {
        AfxMessageBox("error");
        return;
    }

    int nCmd1  = INF_JOIN;   //發送給服務器的命令
    sock.Send(&nCmd1,sizeof(nCmd1));

    //類型轉換,發送的信息不能爲CString格式,轉化爲用戶名和密碼的Char類型,並且flag真,表示已經存在,(假爲不存在,剛註冊)
    ServerData data;
    strncpy(data.Account,(LPCTSTR)m_Sign_Account,sizeof(data.Account));
    strncpy(data.Pass,(LPCTSTR)m_Sign_Pass,sizeof(data.Pass));
    data.flag=true;
    sock.Send(&data,sizeof(data));

    //從服務器接收被處理過的data,驗證flag
    sock.Receive(&data,sizeof(data));
    if(!data.flag)
    {
        AfxMessageBox("註冊成功");
        //CDialog::OnOK();
    }
    else
    {
        AfxMessageBox("用戶已存在");//用戶已存在提示框,不關閉註冊框,可讓用戶自由選擇是否繼續註冊
    }

}

3、登陸按鈕


void Sign_Join::OnBnClickedButton2()
{
    // TODO: 在此添加控件通知處理程序代碼
    CString m_Login_Account,m_Login_Pass;
    m_edit1.GetWindowText(m_Login_Account); 
    m_edit2.GetWindowText(m_Login_Pass);
    m_Login_Account.TrimLeft();
    m_Login_Account.TrimRight();
    m_Login_Pass.TrimLeft();
    m_Login_Pass.TrimRight();

    if((m_Login_Account=="")||(m_Login_Pass==""))
    {
        AfxMessageBox("error");
        return;
    }

    int nCmd2  = INF_LOGIN;
    sock.Send(&nCmd2,sizeof(nCmd2));

    ServerData data;
    strncpy(data.Account,(LPCTSTR)m_Login_Account,sizeof(data.Account));
    strncpy(data.Pass,(LPCTSTR)m_Login_Pass,sizeof(data.Pass));
    data.flag=false;

    sock.Send(&data,sizeof(data));
    sock.Receive(&data,sizeof(data));
    if(data.flag)
    {
        AfxMessageBox(m_Login_Account+" "+" "+"成功登錄");//找到則顯示的是用戶名+性別+已登錄
        m_Login_Account="";//成功登錄後把用戶框和密碼框文本清除
        m_Login_Pass="";
        //UpdateData(FALSE);//將數據從控件變量傳遞給控件
        pDlg->turnf();
        OnOK();
    }
    else{
        MessageBox("用戶名不存在或密碼錯誤");//用戶密碼錯誤或用戶不存在提示
    }

}

4、退出按鈕,直接退出程序

void Sign_Join::OnBnClickedCancel()
{
    // TODO: 在此添加控件通知處理程序代碼
    exit(0);
    //OnCancel();
}
  • 5、設置禁止移動對話框,資源視圖,點擊登陸對話框,屬性添加消息響應WM_SYSCOMMAND,注意最後是CDialog::,不管是什麼類都是這個
void Sign_Join::OnSysCommand(UINT nID, LPARAM lParam)
{
    // TODO: 在此添加消息處理程序代碼和/或調用默認值
    if (nID == SC_MOVE || nID==0xF012)
        return;
    else

    CDialog::OnSysCommand(nID, lParam);
}

服務器

  • 二、在服務器的ClientSocket.cpp文件中,被重載的虛函數OnReceive中寫入協議命令的函數。
void CCLientSocket::OnReceive(int nErrorCode)
{
    // TODO: 在此添加專用代碼和/或調用基類
    int nCmd = 0,nLen = 0;
    if(Receive(&nCmd,sizeof(nCmd))<=0)
        return ;
    switch(nCmd)
    {
    case INF_ADD:
        AddData();
        break;
    case INF_BROW:
        Browse();
        break;
    case INF_JOIN:
        join_add();
        break;
    case INF_LOGIN:
        login_find();
        break;
    }


    CSocket::OnReceive(nErrorCode);
}

1、join_add()函數的具體實現

void CCLientSocket::join_add(void)
{
    ServerData data;
    Receive(&data,sizeof(data));
        //return ;

    CString m_Sign_Account(data.Account);
    CString m_Sign_Pass(data.Pass);
    //m_Sign_Account(data.Account);
    //m_Sign_Pass(data.Pass);

    // TODO: 在此添加控件通知處理程序代碼
    CString username;//從文件中讀取用戶名進行校驗,如果輸入的用戶名在文件已存在則不進行註冊

    bool flag=false;//標記
    char * path="username.txt";//文件路徑

    CFile fp;//使用MFC的CFile將暑假寫入文件
    fp.Open((LPCTSTR)path,CFile::modeCreate|CFile::modeNoTruncate|CFile::modeReadWrite);
    fp.SeekToBegin();//移動文件指針位置至文件頭

    CArchive ar(&fp,CArchive::load);//使用CArchive進行讀取文件

     //校驗操作
     while(ar.ReadString(username))
     {
         username.TrimLeft();
         username.TrimRight();
         if(strcmp(username,m_Sign_Account)==0) {
             flag=true;//如果已存在用戶名,則標記flag爲true
             break;
         }
         else {
             ar.ReadString(username);//讀取下一行(每一行爲一個屬性,比如用戶名,密碼,性別,總共3 個屬性)
             ar.ReadString(username);//讀取下一
         }
     }
     ar.Close();
     fp.SeekToEnd();   //文件寫入爲追加操作,所以寫入前必須將文件指針移動至文件尾

     if(!flag)
     {
        //CFile Write(*str,GetLength())寫入
        fp.Write(m_Sign_Account,m_Sign_Account.GetLength());
        //win雖是\r\n,在寫程序只需要\n即可換行
        fp.Write("\n",sizeof(char));
        fp.Write(m_Sign_Pass,m_Sign_Pass.GetLength());
        fp.Write("\n",sizeof(char));

        fp.Close();

        data.flag=false; 
    }
     Send(&data,sizeof(data));

}
  • 2、login_find()函數的實現

void CCLientSocket::login_find(void)
{
    ServerData data;
    Receive(&data,sizeof(data));
    CString m_Login_Account(data.Account);
    CString m_Login_Pass(data.Pass);


    CString username;
    CString password;

    //與註冊類似操作

    bool flag=false;
    char * path="username.txt";
    CFile file;

    file.Open(path,CFile::modeRead);
    file.SeekToBegin();
    CArchive ar(&file,CArchive::load);
    //去除數據左右空格數據

    //校驗用戶密碼,與註冊校驗相同的操作,這裏多驗證了一步,即校驗密碼
    while(ar.ReadString(username))
    {
        if(ar.ReadString(password))
            {
                username.TrimLeft();
                username.TrimRight();
                password.TrimLeft();
                password.TrimRight();
                if(strcmp(username,m_Login_Account)==0
            &&strcmp(password,m_Login_Pass)==0)
                {
                    flag=true;
                    data.flag=true; 


                    //ar.ReadString(sex);//如果用戶驗證正確,flag=true,並且sex爲用戶的性別
                    break;          
                }               
            }
        //ar.ReadString(sex);     
    }
    //關閉CFile和CArchive
    Send(&data,sizeof(data));
    ar.Close();
    file.Close();

}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章