麻豆小视频在线观看_中文黄色一级片_久久久成人精品_成片免费观看视频大全_午夜精品久久久久久久99热浪潮_成人一区二区三区四区

首頁 > 學(xué)院 > 開發(fā)設(shè)計 > 正文

基于.NET的多用戶客戶端設(shè)計

2019-11-17 04:39:47
字體:
供稿:網(wǎng)友


  摘要: 在C/S 模式中,服務(wù)器端往往是設(shè)計的重點。為了測試服務(wù)器的性能,不得不使用大量的計算機(jī)作為客戶端。在實際情況中,往往無法提供大量的計算機(jī)用以測試,同時,這也是資源的浪費,為了解決這個問題,本文提出了模擬多用戶客戶端的設(shè)計方法,并給出具體代碼說明。


  要害字:多用戶 客戶端 連接隊列

  1. 概述

  在C/S 模式中,服務(wù)器端往往是設(shè)計的重點。一般來說,服務(wù)器的能夠承受的連接數(shù)量是衡量一個服務(wù)器性能好壞的重要標(biāo)準(zhǔn),為了測試服務(wù)器能夠承受的連接數(shù),我們必須使用多臺客戶機(jī)來測試他的性能.可是,很多情況下,我們沒有那么多的機(jī)器,同時使用多臺機(jī)器進(jìn)行測試也是浪費資源,為此,我們設(shè)計了模擬多用戶客戶端程序來解決這個問題。

  本文采用MFC的CSocket類在.NET平臺上進(jìn)行設(shè)計.所謂的模擬多用戶就是用一個客戶端程序來建立多個與服務(wù)器的連接,就似乎多個客戶端與服務(wù)器進(jìn)行連接一樣。設(shè)計的重點是:

   程序能夠生成用戶指定的數(shù)目的連接;

   用戶可以在建立的連接中任意指定某個連接進(jìn)行通信;

   用戶可以隨意更換連接進(jìn)行通信測試,每個連接不會互相混淆,尤其是在讀寫數(shù)據(jù)的時候,不能張冠李戴;

   用戶可以隨意指定斷開某個連接,而不會影響其他連接。

  那么這么多的連接究竟如何治理呢?

  首先,我們要有一種數(shù)據(jù)結(jié)構(gòu)來描述每個連接的具體情況。本文采用了結(jié)構(gòu)體。

  自定義結(jié)構(gòu)體strUCt socket_info
{ CSocket* s_client; //保存用戶的SOCKET值
u_long client_addr; //保存用戶網(wǎng)絡(luò)地址
CString username; //用戶昵稱
int id; //連接號
} ;  然后,使用C++的模板類CList來治理這些連接。以后所做的所有事情就是對這個鏈表的操作。

  2.設(shè)計步驟:

  2.1創(chuàng)建一個基于對話框的工程CClientDlg.在MFC應(yīng)用程序向?qū)е羞x中windows 套接字。

  2.2給對話框添加菜單,并添加菜單項,包括配置服務(wù)器、用戶登陸、退出、通信、斷開連接。

  2.3添加"配置服務(wù)器"響應(yīng)函數(shù)OnServerConfserver(),調(diào)出服務(wù)器配置對話框Server Configure。輸入服務(wù)器的
  2.5 添加"通信"響應(yīng)函數(shù)OnCommunication(),調(diào)出通信對話框,如圖1所示。點擊"發(fā)送",發(fā)送數(shù)據(jù);點擊"接收",接收數(shù)據(jù);點擊"斷開該連接",關(guān)閉socket,并從鏈表中刪除該連接。

  2.6 添加"退出"菜單響應(yīng)函數(shù)。遍歷整個連接隊列,將所有的連接斷開并刪除隊列中所有結(jié)構(gòu)體,將隊列清空。

進(jìn)入討論組討論。
  3.具體代碼:

  3.1 聲明全局變量
struct socket_info {……} ; //如前所示
extern CList<socket_info,socket_info&> s_info; //鏈表類
extern CClientSocket* lSocket; //用于標(biāo)識當(dāng)前正在通信的連接
extern int id; //用于指示用戶選擇的要進(jìn)行通信的連接
extern char pBuf[100]; //接收緩沖區(qū)  3.2 實現(xiàn)CClientDlg.cpp中的響應(yīng)函數(shù):
void CClientDlg::OnServerConflogin()//"用戶登陸"菜單響應(yīng)函數(shù)
{ CLoginDlg dlg;
int t=0; //記錄失敗的連接數(shù)
int size=s_info.GetSize(); //查看當(dāng)前連接鏈表的長度
if(dlg.DoModal()==IDOK)
{ socket_info* pInfo; //聲明結(jié)構(gòu)體
for(int i=0;i<dlg.m_nUserCount;i++)
{ pInfo = new socket_info;
pInfo->s_client=new CClientSocket();
if(!(pInfo->s_client->Create())) //創(chuàng)建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; //設(shè)置當(dāng)前連接的id
pInfo->username=dlg.m_strUsername;
s_info.AddTail(*pInfo); //將成功的連接加入鏈表
}
}
int c=dlg.m_nUserCount-t; //得到成功的連接數(shù)
char message[10];
::s
strcat(message,"個連接成功");
if(c>=0) AfxMessageBox(message); //彈出提示對話框
}
}  3.3 實現(xiàn)CommunicationDlg.cpp中的響應(yīng)函數(shù):
void CCommunicationDlg::OnBnClickedQuery()//"發(fā)送"按鈕的響應(yīng)函數(shù)
{ 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());
//發(fā)送m_strSendData文本框中的文本
break; }
if(pos==NULL) break;
else info =s_info.GetNext(pos);
}
}
}else AfxMessageBox("the queer is empty!"); //鏈表為空
}void CCommunicationDlg::OnBnClickedAdd() //"接收"按鈕的響應(yīng)函數(shù)
{ UpdateData();
BOOL MsgEnd=TRUE;
int iRecv; //每次讀取的字符數(shù)
if(!lSocket==NULL)
{ memset(pBuf,0,100); //清空緩沖區(qū)
do{ iRecv=lSocket->Receive(pBuf,100);//接收數(shù)據(jù)
if(iRecv<100&&iRecv>0) { MsgEnd=TRUE;}
pBuf[iRecv]=0; //給緩沖區(qū)結(jié)尾,即賦'/0'
}while(!MsgEnd);
m_ReceData.SetSel(0,-1);
m_ReceData.ReplaceSel(pBuf); //在m_ReceData文本框中顯示接收的字符
} else AfxMessageBox("the socket was disconnected");
}void CCommunicationDlg::OnBnClickedCancel()//"斷開該連接"按鈕的響應(yīng)函數(shù)  與"退出"菜單響應(yīng)函數(shù)類似,不同之處在于,退出菜單要清空整個隊列,而"斷開該連接"函數(shù)僅僅是找到當(dāng)前的正在通信的連接并將其斷開。
……
socket_info info=s_info.GetAt(s_info.FindIndex(id)); //找到id對應(yīng)的結(jié)構(gòu)體
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)); //從鏈表中刪除該結(jié)構(gòu)體
AfxMessageBox("Disconnect successfully!");   4. 設(shè)計技巧

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

  4.1 對于一個基于對話框的應(yīng)用程序,Visual MFC應(yīng)用程序向?qū)Р粫o對話框創(chuàng)建菜單。假如要在對話框中顯示菜單,必須把它作為一個資源,并連接到對話框窗口。具體步驟:

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

   打開資源試圖的"對話框"選項,右擊對話框(IDD_CLIENT_DIALOG),選擇"屬性", 在彈出的屬性表中找到"Menu",將它的值設(shè)為IDR_MENU1;
  4.2 用戶要建立連接,就要指定連接數(shù),問題是,用戶不一定一次指定所有的連接。比如說,第一次,用戶指定了50個連接,程序?qū)?0個連接加入到連接隊列中。經(jīng)過測試,用戶發(fā)現(xiàn)50個連接運行情況良好,于是,用戶想要測試100個連接的運行情況,這時,我們不能要求用戶退出并重新運行程序,然后指定100個連接重新進(jìn)行測試。我們要做的就是讓用戶能夠再次指定50個連接,并且將這50個連接加入到前50個連接的后面。所以,在設(shè)計時,每次建立指定數(shù)目的連接前,必須查詢隊列的長度,然后將建立的連接加入到隊列中正確的位置上。正如"用戶登陸"菜單響應(yīng)函數(shù)所示:
int size=s_info.GetSize();//查看當(dāng)前連接鏈表的長度

pInfo->id =size+i; //設(shè)置當(dāng)前連接的id  4.3 每次用戶指定某個連接進(jìn)行測試時,程序都要自動搜索連接隊列找到指定的連接,并發(fā)送信息。問題是,我們的發(fā)送和接收是不同的響應(yīng)函數(shù),如何保證接收信息的連接是用戶指定的連接呢?例如,用戶建立了100個連接,指定Id為59的連接進(jìn)行通信,當(dāng)發(fā)送數(shù)據(jù)時,程序自動找到Id=59的socket發(fā)送數(shù)據(jù),可是,當(dāng)接收數(shù)據(jù)時,程序怎么知道是哪個連接負(fù)責(zé)接收數(shù)據(jù)呢?我們可以在接收響應(yīng)函數(shù)中再次查找隊列,但是,這樣不但增加了系統(tǒng)資源的消耗,而且增加了系統(tǒng)的延遲。我們采用全局變量lSocket來解決這個問題。
lSocket=info.s_client;//將用戶指定的連接的socket賦予lSocket
lSocket->Send(m_strSendData,m_strSendData.GetLength());//發(fā)文本框中的文本
iRecv=lSocket->Receive(pBuf,100);   4.4 每次用戶退出程序之前,必須斷開所有連接,并清空隊列。 如"退出"菜單響應(yīng)函數(shù)所示。

  5. 結(jié)束語

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


發(fā)表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發(fā)表
主站蜘蛛池模板: a网站在线 | asian附近女人裸体pics | 久久99久久98精品免观看软件 | 羞羞答答www网站进入 | 婷婷亚洲一区二区三区 | 国产成人精品自拍视频 | 成人av一二三区 | 操嫩草| 欧美成人午夜 | 在线亚洲综合 | 亚洲第一男人天堂 | 国产精品剧情一区二区三区 | fc2成人免费人成在线观看播放 | 亚洲成人高清在线观看 | 91成人久久| 一级大片久久 | 国产91影院| 欧美日韩大片在线观看 | 久久久久久久久久久国产精品 | 免费在线观看成人av | 人人看人人艹 | 成人 在线| 国产精品久久久久久模特 | 黄色一级片在线观看 | 久久久久久久久久一本门道91 | 精品中文字幕在线观看 | 久久精品国产久精国产 | 免费久久久| 一本色道久久综合亚洲精品图片 | 国产免费一区二区三区 | 国产成人高清在线观看 | 中文字幕国产欧美 | 日本娇小18xxxⅹhd | 亚洲精品久久久久久久久久 | 亚洲视频欧美 | 一级全毛片 | 一级黄色国产视频 | 久久精品探花 | 大学生一级毛片 | 国产亚洲精品综合一区91555 | 7777在线观看 |