• <ruby id="5koa6"></ruby>
    <ruby id="5koa6"><option id="5koa6"><thead id="5koa6"></thead></option></ruby>

    <progress id="5koa6"></progress>

  • <strong id="5koa6"></strong>
  • 淺談基于.NET的多用戶客戶端設計[2]

    發表于:2007-05-14來源:作者:點擊數: 標簽:設計多用戶.NET客戶端淺談
    3.具體代碼: 3.1聲明全局變量 struct socket_info {……} ; //如前所示 extern CList s_info; //鏈表類 extern CC lientSocket* lSocket; //用于標識當前正在通信的連接 extern int id; //用于指示用戶選擇的要進行通信的連接 extern char pBuf[100]; //接收

      3.具體代碼:

      3.1聲明全局變量

      struct socket_info {……} ; //如前所示

      extern CList s_info; //鏈表類

      extern CClientSocket* lSocket; //用于標識當前正在通信的連接

      extern int id; //用于指示用戶選擇的要進行通信的連接

      extern char pBuf[100]; //接收緩沖區

      3.2實現CClientDlg.cpp中的響應函數:

      void CClientDlg::OnServerConflogin()//"用戶登陸"菜單響應函數

      { CLoginDlg dlg;

      int t=0; //記錄失敗的連接數

      int size=s_info.GetSize(); //查看當前連接鏈表的長度

      if(dlg.DoModal()==IDOK)

      { socket_info* pInfo; //聲明結構體

      for(int i=0;i

      { pInfo = new socket_info;

      pInfo->s_client=new CClientSocket();

      if(!(pInfo->s_client->Create())) //創建socket

      { delete pInfo->s_client;

      pInfo->s_client=NULL;

      }

      if(!(pInfo->s_client->Connect(m_strIpaddress,m_Port))) //連接

      { t++; //如果失敗,t增加,釋放空間

      delete pInfo->s_client;

      pInfo->s_client=NULL;

      }

      else{ //如果成功

      pInfo->id =size+i; //設置當前連接的id

      pInfo->username=dlg.m_strUsername;

      s_info.AddTail(*pInfo); //將成功的連接加入鏈表

      }

      }

      int c=dlg.m_nUserCount-t; //得到成功的連接數

      char message[10];

      ::sprintf(message,"%d",c); //將數字轉換成字符串

      strcat(message,"個連接成功");

      if(c>=0) AfxMessageBox(message); //彈出提示對話框

      }

      }

      3.3實現CommunicationDlg.cpp中的響應函數:

      void CCommunicationDlg::OnBnClickedQuery()//"發送"按鈕的響應函數

      { lSocket=NULL;

      UpdateData();

      id=atoi(m_strQueryId); //獲得用戶輸入的連接號

      POSITION pos;

      if(!s_info.IsEmpty())

      { socket_info info=s_info.GetHead();

      if(id>=s_info.GetCount()) //可選擇的id必須小于鏈表的大小

      MessageBox("the data is larger than the count of the list","Alert",MB_OK);

      else{ for(pos=s_info.GetHeadPosition();;) //遍歷整個鏈表

      { if(info.id==id&&!info.s_client==NULL)

      { lSocket=info.s_client; //將用戶指定的連接的socket賦予lSocket lSocket->Send(m_strSendData,m_strSendData.GetLength());

      //發送m_strSendData文本框中的文本

      break; }

      if(pos==NULL) break;

      else info =s_info.GetNext(pos);

      }

      }

      }else AfxMessageBox("the queer is empty!"); //鏈表為空

      }

      void CCommunicationDlg::OnBnClickedAdd() //"接收"按鈕的響應函數

      { UpdateData();

      BOOL MsgEnd=TRUE;

      int iRecv; //每次讀取的字符數

      if(!lSocket==NULL)

      { memset(pBuf,0,100); //清空緩沖區

      do{ iRecv=lSocket->Receive(pBuf,100);//接收數據

      if(iRecv<100&&iRecv>0) { MsgEnd=TRUE;}

      pBuf[iRecv]=0; //給緩沖區結尾,即賦'\0'

      }while(!MsgEnd);

      m_ReceData.SetSel(0,-1);

      m_ReceData.ReplaceSel(pBuf); //在m_ReceData文本框中顯示接收的字符

      } else AfxMessageBox("the socket was disconnected");

      }

      void CCommunicationDlg::OnBnClickedCancel()//"斷開該連接"按鈕的響應函數

      與"退出"菜單響應函數類似,不同之處在于,退出菜單要清空整個隊列,而"斷開該連接"函數僅僅是找到當前的正在通信的連接并將其斷開。

      ……

      socket_info info=s_info.GetAt(s_info.FindIndex(id)); //找到id對應的結構體

      if(!info.s_client==NULL){

      if(info.s_client->ShutDown(2)){ //斷開該連接

      info.s_client->Close();

      delete info.s_client;

      info.s_client=NULL;

      s_info.RemoveAt(s_info.FindIndex(id)); //從鏈表中刪除該結構體

      AfxMessageBox("Disconnect suclearcase/" target="_blank" >ccessfully!");

      4.設計技巧

      在設計中,我們要注意幾個問題,這些問題的解決直接影響到程序的性能。

      4.1對于一個基于對話框的應用程序,Visual MFC應用程序向導不會給對話框創建菜單。如果要在對話框中顯示菜單,必須把它作為一個 資源,并連接到對話框窗口。具體步驟:

       右擊資源試圖的"菜單"選項,創建一個菜單IDR_MENU1,添加菜單項;

       打開資源試圖的"對話框"選項,右擊對話框(IDD_CLIENT_DIALOG),選擇"屬性",在彈出的屬性表中找到"Menu",將它的值設為IDR_MENU1;

      4.2用戶要建立連接,就要指定連接數,問題是,用戶不一定一次指定所有的連接。比如說,第一次,用戶指定了50個連接,程序將50個連接加入到連接隊列中。經過測試,用戶發現50個連接運行情況良好,于是,用戶想要測試100個連接的運行情況,這時,我們不能要求用戶退出并重新運行程序,然后指定100個連接重新進行測試。我們要做的就是讓用戶能夠再次指定50個連接,并且將這50個連接加入到前50個連接的后面。所以,在設計時,每次建立指定數目的連接前,必須查詢隊列的長度,然后將建立的連接加入到隊列中正確的位置上。正如"用戶登陸"菜單響應函數所示:

      int size=s_info.GetSize();//查看當前連接鏈表的長度

      pInfo->id =size+i; //設置當前連接的id

      4.3每次用戶指定某個連接進行測試時,程序都要自動搜索連接隊列找到指定的連接,并發送信息。問題是,我們的發送和接收是不同的響應函數,如何保證接收信息的連接是用戶指定的連接呢?例如,用戶建立了100個連接,指定Id為59的連接進行通信,當發送數據時,程序自動找到Id=59的socket發送數據,可是,當接收數據時,程序怎么知道是哪個連接負責接收數據呢?我們可以在接收響應函數中再次查找隊列,但是,這樣不但增加了系統資源的消耗,而且增加了系統的延遲。我們采用全局變量lSocket來解決這個問題。

      lSocket=info.s_client;//將用戶指定的連接的socket賦予lSocket

      lSocket->Send(m_strSendData,m_strSendData.GetLength());//發文本框中的文本

      iRecv=lSocket->Receive(pBuf,100);

      4.4每次用戶退出程序之前,必須斷開所有連接,并清空隊列。如"退出"菜單響應函數所示。

      5.結束語

      經過實際驗證,該程序能夠很好的測試服務器的連接承受能力,從理論上來說,用戶可以指定任意多的連接,實際上,連接數受到計算機資源的限制。在通信過程中,各個連接能夠良好的進行,不會互相干擾。

    原文轉自:http://www.kjueaiud.com

    評論列表(網友評論僅供網友表達個人看法,并不表明本站同意其觀點或證實其描述)
    老湿亚洲永久精品ww47香蕉图片_日韩欧美中文字幕北美法律_国产AV永久无码天堂影院_久久婷婷综合色丁香五月

  • <ruby id="5koa6"></ruby>
    <ruby id="5koa6"><option id="5koa6"><thead id="5koa6"></thead></option></ruby>

    <progress id="5koa6"></progress>

  • <strong id="5koa6"></strong>