標籤:mfc socket tcp協議
1網路聊天室項目描述1.1功能描述
MyQQv1採用C/S模式,構建網路聊天室,具體實現功能:
A.能顯示線上使用者列表
B.能在聊天室裡進行群聊天
C.能指定使用者進行私聊
D.某使用者下線,其他使用者能接到提示
1.2所需技術
MFC,Socket通訊端,TCP/IP協議,動態數組,CString字串拼接與拆分
2網路聊天室運行流程圖2.1伺服器運行流程圖
2.2用戶端運行流程圖
3網路聊天室詳細3.1通訊格式
每次用戶端與伺服器之間的通訊都是發送“START&命令&自己名字&訊息&私密者&END”(為標準格式字串)的字串,然後接受方會進行分割和按照“&”進行分段解析。
3.1.1訊息分割
當某次(在接受全部線上使用者列表時)次接受不止一條格式字串時,把整個字串切割成若干個標準格式字串。程式清單如下所示。
/********************************************************************函數名稱:MsgCut函數功能:把資料流按通訊格式分割處理傳入參數:CString strText傳回值: 無********************************************************************/void CClientSocket::MsgCut(CString strText){UINT nfirst , nlast;CString strTmp;while(strText.GetLength() > 9){nfirst = strText.Find("START");nlast = strText.Find("END");strTmp = strText.Mid(nfirst, nlast+3);//每次截取從START到END的字串char * sTran = strTmp.GetBuffer(0);//CString轉化為char *型MsgDeal(sTran);strText = strText.Mid(nlast+3,strText.GetLength()-nlast-3);}}
nfirst得到“START”子串的起始位置,nlast得到“END”子串的起始位置,strTmp為“START”開始到“END”(包括末尾D)的一個標準格式字串。再把原始長串切掉剛形成的strTmp,strText使用Mid(上一個EDN位置+3,總長度-上一個EDN位置-3)函數得到切割完的字串,直到strText滿足最小標準長度。
3.1.2按“&”分段解析
每個標準格式字串中包含命令,發來使用者名稱,訊息,私密者4個資訊。它們按照“&”串連在一起,接收端要按“&”分段解析,程式清單如下。
/***********************************************************************函數名稱:MsgExplain函數功能:對訊息的拆解,訊息傳來的格式是 k&1&使用者名稱&說的話&私密的人傳入參數:char sMsgDeal[5][BUFMAX],char * sMsgInit傳回值: 無***********************************************************************/void CClientSocket::MsgExplain(char sMsgDeal[6][BUFMAX],char * sMsgInit){char *p;bool bFlg = FALSE;int iRow = -1;int iCol = 0;char c = 0;p=sMsgInit;while (*p != '\0'){c = *p;if ( c != '&'){if (bFlg == FALSE)//如果碰到新的單詞列{bFlg = TRUE;iRow++;iCol = 0;}sMsgDeal[iRow][iCol] = c;iCol++;} else{if (bFlg == TRUE){sMsgDeal[iRow][iCol]='\0';}bFlg = FALSE;}p++;sMsgDeal[iRow][iCol] = '\0';}}
其中最後一句是當解析到最後一個單詞的時候沒有&,但是還是要在字串的末尾加’\0’的字串結束符,避免最後一個sMsgDeal[6]串出錯。
3.2伺服器類3.2.1重載OnAccept函數
伺服器使用Create(PORT)開啟成功後,使用Listen()進行監聽,當有用戶端進行串連請求後,發生OnAccept訊息響應,此時重載OnAccept函數。
/***********************************************************************函數名稱:OnAccept函數功能:接受串連傳入參數:int nErrorCode傳回值: 無***********************************************************************/void CServerSocket::OnAccept(int nErrorCode) {// TODO: Add your specialized code here and/or call the base classCClientSocket *_pNewClient = new CClientSocket();_pNewClient->GetServerPointer(this);//!!這句話至關重要,把伺服器的通訊端綁定到此Accept(*_pNewClient);m_ClientArr.Add(_pNewClient);//接受一個串連把它加入到動態數組中CSocket::OnAccept(nErrorCode);}
建立一個CClientSocket通訊端,把用戶端的串連綁定到此通訊端上,並把此通訊端增加到動態數組中。相當於伺服器端自從接受新的串連後就不再管理,後面的發送與接受都使用自己剛剛建立的CClientSocket通訊端來完成。
3.2.2發送給指定使用者
伺服器負責所有訊息的轉寄,當有私密訊息發來時,進行分類處理。有私密訊息時,掃描動態數字,把私密者的名字與動態數組每個通訊端的名字進行比較,相同則進行轉寄。
3.3用戶端類3.3.1初次串連
用戶端串連成功,發送包含自己名字的標註格式字串。如下程式清單所示。
/***********************************************************************函數名稱:OnButLink函數功能:用戶端串連伺服器傳入參數:無傳回值: 無***********************************************************************/void CSetDlg::OnButLink() {// TODO: Add your control notification handler code hereCMyQQDlg *pParent = (CMyQQDlg*)this->GetParent(); pParent->m_Client.Create();//pParent->m_Client.SetDialog(pParent); //設定通訊端成員變數UpdateData(TRUE);pParent->m_Client.m_strUserName = m_sName;if(pParent->m_Client.Connect(m_sServerIP,PORT)){MessageBox("串連伺服器成功");CString str;pParent->m_Client.m_strUserName = m_sName;str.Format("START&0&%s&0&0&END",m_sName);pParent->m_Client.Send(str,str.GetLength());pParent->m_cChoseFlg = 2;pParent->SetWindowText("用戶端——"+m_sName);}else{MessageBox("串連失敗","警告");}EndDialog(0);}
伺服器端接受到新上線的使用者名稱,把它賦給建立CClientSocket的m_strUserName,使動態數組裡每個通訊端都有一個m_strUserName與之對應,為私密資訊做好準備。
3.3.2重載OnReceive函數
用戶端接收到訊息,產生OnReceive訊息,這裡進行重寫,進行字串的拆分與解析。程式清單如下。
/***********************************************************************函數名稱:OnReceive函數功能:用戶端的接受訊息的響應函數傳入參數:int nErrorCode傳回值: 無***********************************************************************/void CClientSocket::OnReceive(int nErrorCode) {// TODO: Add your specialized code here and/or call the base classchar strText[512] = {0};Receive(strText, 512);MsgCut(strText);CSocket::OnReceive(nErrorCode);}
用戶端接收到訊息後,是產生了OnReceive訊息。重載OnReceive函數,把每次得到字串進行拆分解析。
4網路聊天室運行情況
著作權聲明:本文為博主原創文章,未經博主允許不得轉載。
網路聊天室