基于Csocket的聊天程序_第1頁(yè)
基于Csocket的聊天程序_第2頁(yè)
基于Csocket的聊天程序_第3頁(yè)
基于Csocket的聊天程序_第4頁(yè)
基于Csocket的聊天程序_第5頁(yè)
已閱讀5頁(yè),還剩12頁(yè)未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

基于Csocket的聊天程序?qū)嶒?yàn)四使用CSocket類的網(wǎng)絡(luò)通信基礎(chǔ)知識(shí)CSocket類是CAsyncSocket類的派生類,它提供了對(duì)通過(guò)CArchive對(duì)象使用套接字工作的更高級(jí)抽象。CSocket類的使用比CAsyncSocket類更加容易,它繼承了CAsyncSocket類的許多封裝了API的成員函數(shù),并且管理了通信的大多數(shù)方面,這使用戶從原來(lái)不得不使用原始API或者AsyncSocket類的繁雜工作巾解脫出來(lái)。更加重要的是CSocket類提供了對(duì)于同步操作CArchive對(duì)象十分重要的阻塞功能,且CSocket通過(guò)與類CSocketFile和CArchive一起來(lái)管理對(duì)數(shù)據(jù)的發(fā)送和接收,使收發(fā)數(shù)據(jù)的操作變得簡(jiǎn)單明了CSocket類是CAsyncSocket類的派生類,它對(duì)WinsockAPI進(jìn)行進(jìn)一步封裝,因此它的成員函數(shù)比CAsyncSocket要少得多,不難掌握。(1)CSocket和Create這兩個(gè)函數(shù)與CAsyncSocket類的同名成員函數(shù)的作用和用法相似。(2)IsBlocking該函數(shù)用來(lái)確定套接字當(dāng)前是否有正在執(zhí)行的阻塞調(diào)用,其原型為:BOOLIsBlocking();如果套接字處于阻塞狀態(tài),則返回非0值,否則返回0。(3)FromHandle該函數(shù)用于從給定的SOCKET句柄中得到相應(yīng)的CSocket對(duì)象指針,其原型為:staticCSocket*PASCALFromHandle(SOCKEThSocket);其中,參數(shù)hSocket是給定的SOCKET句柄。如果函數(shù)調(diào)用成功,則返回CSocket對(duì)象指針,如果返回NULL,則該句柄沒(méi)有與socket對(duì)象相連。(4)Attach該函數(shù)用于將SOCKET句柄與CSocket對(duì)象相連,其原型為:BOOLAttach(SOCKEThSocket):其中,hSocket用于知道欲與CSocket對(duì)象相連的SOCKET句柄。如果函數(shù)調(diào)用成功則返回非0值,否則返回0。(5)CancelBlockingCall該函數(shù)用于取消正存進(jìn)行的阻塞調(diào)用,其原型為:voidCanceIBlockingCall();通過(guò)調(diào)用該函數(shù),原始的阻塞調(diào)用將立即被中止,并返回錯(cuò)誤碼WSAEINTR。注意:如果阻塞是由Connect調(diào)用引起的,則雖然WindowsSockets將立即中止阻塞調(diào)用,但是除非連接完成或超時(shí),否則套接字資源可能都不會(huì)被釋放,而且除非1被取消的調(diào)用為Accept,否則該函數(shù)都將使套接字處于不確定的狀態(tài)。(6)OnMessagePending重載該函數(shù)可以在Windows中尋找并響應(yīng)特定的消息,其原型為:virtualBOOLOnMessagePending():如果該消息被處理,則返回非0值,否則返回0。共同使用CSocket與CArchive對(duì)象是最簡(jiǎn)單的套接字編程模型,其中CArchive對(duì)象將幫助程序員處理許多以前必須使用API或CAsyncSocket類來(lái)處理的通信問(wèn)題,大大減少了編程的工作量。圖1值得注意的是,盡管CSocketFile類是CFile的派生類,但它并不支持CFile的一些成員函數(shù),例如Seek、GetLengh、SetLengh、LockRange、UnlockRange以及GetPosition等函數(shù),這還是比較容易理解的,因?yàn)镃SocketFile是從相關(guān)的CSocket對(duì)象中讀出或?qū)懭胱止?jié)序列,與文件無(wú)關(guān),諸如Seek或GetPosition等函數(shù)并無(wú)意義。為了禁止CSocketFile所不支持的CFile成員函數(shù)在CSocketFile類中被重載,在執(zhí)行重載這些函數(shù)時(shí),就會(huì)觸發(fā)一個(gè)CNotSupportedException異常。此外,CSocketFile也能單獨(dú)使用(不與CArchive對(duì)象共I同使用)。默認(rèn)情況下,CSocketFile的構(gòu)造函數(shù)的bArchiveCompatible參數(shù)為T(mén)RUE,這指定了文件對(duì)象與歸檔一起使用。要使文件對(duì)象不與歸檔一起使用,只需將bArchiveCompatible設(shè)置為FALSE即可。不過(guò),當(dāng)CSocketFile與歸檔對(duì)象一起使用時(shí),它具有更好的性能,并減少了“死鎖”的危險(xiǎn)。CSocket編程模型如圖2所示。注意:CArchive對(duì)象只能單向傳遞數(shù)據(jù):載入(接收)或存儲(chǔ)(發(fā)送)。在某些情況下,用戶越須使用兩個(gè)CArchive對(duì)象,一個(gè)進(jìn)行數(shù)據(jù)發(fā)送,而另一個(gè)進(jìn)行數(shù)據(jù)2接收。并且CArchive類特別為CSocket類提供了IsBufferEmpty成員函數(shù),如果緩沖區(qū)包含多個(gè)數(shù)據(jù)消息,例如,需要循環(huán)直到所有的數(shù)據(jù)都被讀出,并且緩沖區(qū)被清空。否則,下一個(gè)將接收數(shù)據(jù)的通告可能被無(wú)限延遲。使用IsBufferEmpty函數(shù),可以確定接收到了所有數(shù)據(jù)。此外,CSocket類也和CAsyncSocket-樣提供了一些重載函數(shù),包括:OnReceive、OnSend、OnAccept、OnConnect和OnClose并且CSocket類還提供了一個(gè)高級(jí)的重載函數(shù)OnMessagePending。MFC在套接寧響應(yīng)Windows消息時(shí)調(diào)用該函數(shù)??梢灾剌dOnMessagePending函數(shù)以從Windows尋找特定的消息并響應(yīng)它們。它的默認(rèn)版本是,當(dāng)?shù)却枞{(diào)用完成時(shí),檢查消息隊(duì)列并尋找WM_PAINT消息,它發(fā)送重繪消息以便提高顯示質(zhì)量。因此假如要用到這些重載函數(shù)的話,一般需要從CSocket類派生自己的Socket類方能重載這些函數(shù)。本實(shí)驗(yàn)采用CSocket編程模型建立一個(gè)聊天程序的簡(jiǎn)單實(shí)例。使用vc++6建立一個(gè)基于對(duì)話框的工程,建立工程時(shí)注意選上“Windows套接字”復(fù)選框。圖2編程模型編程步驟:3一、服務(wù)器端應(yīng)用程序設(shè)計(jì)(工程名稱SocSvr)1.1、界面及各控件屬性界面如下:4各控件屬性如下控件類型控件IDCaption屬性控件變量變量類型列表框IDC_LST_Logm_lst_logCListBox編輯框IDC_EDT_SenMsgm_edt_senMsgCEdit按鈕IDC_BTN_Sendm_btn_sendCButton列表框控件IDC_LST_Log的屬性“sort”值為false,屬性“HorizontalScroll”值為true。按鈕IDC_BTN_Send屬性Disable值為true。1.2、定義CSocket類的派生類CSocListen和CSocRecv從CSocket編程模型知道,服務(wù)器端需要兩種套接字,一個(gè)用來(lái)偵聽(tīng)連接請(qǐng)求,一個(gè)用來(lái)與請(qǐng)求連接的套接字建立連接。因此,為程序添加兩個(gè)CSocket派生類:SSocListen和CSocRecv,它們與對(duì)話框類密切配合,共同完成程序所要求實(shí)現(xiàn)的功能。在vc集成環(huán)境左側(cè)的工程管理欄中,切換到“classview”頁(yè),對(duì)準(zhǔn)“SocSvrClasses”點(diǎn)右鍵,在彈出的菜單中點(diǎn)擊“newclass”,彈出“newclass”對(duì)話框。在此對(duì)話框的“Classtype”組合框中選擇“MFCClass”,在“Baseclass”組合框中選擇“CSocket”,然后再在“Name”文本框中填入類的名稱“CSocListen”,點(diǎn)擊“OK”按鈕。這樣,一個(gè)CSocket類的派生類“CSocListen”就創(chuàng)建好了。用同樣的方法創(chuàng)建CSocket類的另一個(gè)派生類“CSocRecv”。創(chuàng)建過(guò)程的對(duì)話框如下圖所示。51.3、建立套接字與對(duì)話框類的關(guān)聯(lián)在程序中,對(duì)話框類要用到套接字類,而套接字類在響應(yīng)某些消息,如在函數(shù)OnAccept、OnReceive中進(jìn)行處理時(shí),也要改變對(duì)話框的某些控件狀態(tài),以反映給用戶這些事情的發(fā)生。這里存在著兩個(gè)類相互使用的情況,把套接字類對(duì)象定義成對(duì)話框類的成員變量,同時(shí)在套接字類中也把對(duì)話框類定義為成員變量。如何實(shí)現(xiàn)這樣的用法呢,在對(duì)話框類實(shí)現(xiàn)文件(cpp文件)中加入套接字頭文件的聲明,然后在套接字類實(shí)現(xiàn)文件(cpp文件)中加入對(duì)話框類頭文件的聲明,然后在對(duì)話框類的頭文件里把套接字的指針變量定義為對(duì)話框的成員變量,再在套接字類的頭文件里把對(duì)話框的指針變量定義為對(duì)該套接字的成員變量。具體做法應(yīng)該如下:首先,在SocSvrDlg.h文件中加入套接字類頭文件的聲明,語(yǔ)句#pragmaonce的后面加入如下語(yǔ)句:classCSocListen;//聲明偵聽(tīng)類classCSocRecv;//聲明接收客戶端消息類然后在該文件中為CSocSvrDlg類增加兩個(gè)公有成員變量,語(yǔ)句如下:CSocListen*m_pCSocListen;//定義一個(gè)偵聽(tīng)類的指針6CSocRecv*m_pCSocRecv;//定義一個(gè)接收客戶端消息類的指針再在SocSvrDlg.cpp文件中把兩個(gè)套接字類的頭文件包含進(jìn)來(lái):#include"SocListen.h"http://偵聽(tīng)類,包含進(jìn)來(lái)#include"SocRecv.h"http://接收客戶端消息類,包含進(jìn)來(lái)這樣在對(duì)話框類中就可以使用套接字類了。接下來(lái)在套接字類中加入對(duì)話框類信息。首先,在SocListen.h文件的開(kāi)頭,語(yǔ)句#pragmaonce的后面加入如下語(yǔ)句:classCSocSvrDlg;//聲明對(duì)話框類然后,在該文件中為CSocListen類添加一個(gè)公有成員變量和一個(gè)構(gòu)造函數(shù):CSocListen(CSocSvrDlg*pDlgSocSvr);CSocSvrDlg*m_pDlgSocSvr;接著在SocListen.cpp文件中添加新的構(gòu)造函數(shù)的實(shí)現(xiàn),并添加一條關(guān)于SocSvrDlg.h文件的預(yù)編譯聲明,代碼如下:#include"SocSvrDlg.h"http://對(duì)話框類,包含進(jìn)來(lái)CSocListen::CSocListen(CSocSvrDlg*pDlgSocSvr){m_pDlgSocSvr=pDlgSocSvr;//初始化對(duì)話框指針}這樣,在套接字類中也可以通過(guò)成員變量使用對(duì)話框了。使用同樣的方法對(duì)CSocRecv類進(jìn)行設(shè)置,使其也可以通過(guò)成員變量使用對(duì)話框。1.4、為套接字添加串行化讀寫(xiě)信息的功能在服務(wù)器端的兩個(gè)套接字中,只有CSocRecv套接字是真正與客戶端套接字建立連接,發(fā)送與接收數(shù)據(jù)的,因此,我們只為該類添加串行化讀寫(xiě)信息功能。在SocRecv.h文件中為類CSocRecv添加三個(gè)公有成員變量。CsocketFile*m_pCSocFile;Carchive*m_pCArcIn;Carchive*m_pCArcOut;1.5、在對(duì)話框中初始化套接字并偵聽(tīng)連接請(qǐng)求在OnInitDialog函數(shù)中添加如下代碼:if(m_pCSocListen=newCSocListen(this)){if(m_pCSocListen->Create(1000))//創(chuàng)建端口號(hào){m_lst_log.AddString("等待連接??");m_pCSocListen->Listen();}else{7m_lst_log.AddString("初始化失敗,請(qǐng)重新啟動(dòng)程序");deletem_pCSocListen;//清除偵聽(tīng)socket所占內(nèi)存}}else{m_lst_log.AddString("初始化失敗,請(qǐng)重新啟動(dòng)程序");}上述代碼主要是創(chuàng)建并初始化ServSock套接字,并開(kāi)始偵聽(tīng)連接請(qǐng)求。1.6、接受連接請(qǐng)求由于是CSocListen類的*m_pCSocListen對(duì)象在偵聽(tīng)連接請(qǐng)求,因此由該類來(lái)接受連接請(qǐng)求。首先,在SocListen.h文件中加入如下語(yǔ)句:#iinclude“SocRecv.h”然后,重載該類的OnAccept函數(shù),在該函數(shù)中添加如下代碼:CSocRecv*pCSocRecv;//接收客戶端消息類指針if(pCSocRecv=newCSocRecv(this->m_pDlgSocSvr)){if(Accept(*pCSocRecv)){pCSocRecv->m_pCSocFile=newCSocketFile(pCSocRecv);pCSocRecv->m_pCArcIn=newCArchive(pCSocRecv->m_pCSocFile,CArchive::load);pCSocRecv->m_pCArcOut=newCArchive(pCSocRecv->m_pCSocFile,CArchive::store);m_pDlgSocSvr->m_pCSocRecv=pCSocRecv;pCSocRecv=NULL;m_pDlgSocSvr->m_lst_log.AddString("連接成功,可以開(kāi)始傳遞消息咯~");m_pDlgSocSvr->m_btn_send.EnableWindow(TRUE);}else{m_pDlgSocSvr->m_lst_log.AddString("試圖連接客戶端失敗~");deletepCSocRecv;}}else{m_pDlgSocSvr->m_lst_log.AddString("連接套接字初始化失敗~");}上述代碼首先調(diào)用Accept函數(shù)接受連接請(qǐng)求,然后為該連接創(chuàng)建一個(gè)CSocRecv8類型的套接字,并為該套接字關(guān)聯(lián)CArchive對(duì)象,使其能實(shí)現(xiàn)串行化傳輸信息的功能。最后把關(guān)聯(lián)好的套接字傳回給對(duì)話框?qū)ο蠊┢涫褂?。這樣,對(duì)話框?qū)ο蟮某蓡T變量RecvSock套接字便與客戶端套接字之間建立了一條信息通道,信息將在兩個(gè)套接字之間傳遞。1.7、接收信息連接建立成功后,當(dāng)有信息到達(dá)服務(wù)器端時(shí),就會(huì)引發(fā)SocRecv套接字對(duì)象的OnReceive函數(shù),因此需要重載CSocRecv類的OnReceive函數(shù)。添加代碼如下:CStringcsRecMsg;//接收到的信息(*m_pCArcIn)>>csRecMsg;//接收信息m_pDlgSocSvr->m_lst_log.AddString("客戶端發(fā)來(lái)的信息如下:");m_pDlgSocSvr->m_lst_log.AddString(csRecMsg);//添加到列表框//選中列表框中剛剛收到的消息m_pDlgSocSvr->m_lst_log.SetCurSel(m_pDlgSocSvr->m_lst_log.GetCount()-1);1.8、發(fā)送信息為對(duì)話框“發(fā)送”按鈕添加事件處理函數(shù)OnBTNSend(),代碼如下:voidCSocSvrDlg::OnBTNSend(){//TODO:AddyourcontrolnotificationhandlercodehereCStringcsSenMsg;//要發(fā)送的消息m_edt_senMsg.GetWindowText(csSenMsg);//獲得編輯框內(nèi)容if(csSenMsg==""){AfxMessageBox("空字符串,不能發(fā)送~");return;}m_lst_log.AddString("你發(fā)出的信息如下:");m_lst_log.AddString(csSenMsg);m_lst_log.SetCurSel(m_lst_log.GetCount()-1);*(m_pCSocRecv->m_pCArcOut)<<csSenMsg;m_pCSocRecv->m_pCArcOut->Flush();}9二、客戶端應(yīng)用程序設(shè)計(jì)(工程名稱SocClt)2.1、界面及各控件屬性界面如下:各控件屬性如下控件類型控件IDCaption屬性控件變量變量類型列表框IDC_LST_Logm_lst_logCListBox編輯框IDC_EDT_SenMsgm_edt_senMsgCEdit按鈕IDC_BTN_Sendm_btn_sendCButton列表框控件IDC_LST_Log的屬性“sort”值為false,屬性“HorizontalScroll”值為true。按鈕IDC_BTN_Send屬性Disable值為true。2.2、創(chuàng)建套接字類(從CSocket類派生)客戶端只需要一個(gè)套接字,命名為CSocSend。2.3、建立對(duì)話框類與套接字類的關(guān)聯(lián)首先,在SocCltDlg.h文件的開(kāi)頭,語(yǔ)句#pragmaonce后面加入如下語(yǔ)句:classCSocSend;//聲明socket類然后,在該文件中為CSocCltDlg類添加一個(gè)公有成員變量,語(yǔ)句如下:10CSocSend*m_pCSocSend;//定義socket類指針再在CsocSend中添加對(duì)話框類的成員變量。首先,在SocSend.h文件的開(kāi)頭,語(yǔ)句#pragmaonce后面加入如下語(yǔ)句:classCSocCltDlg;//聲明對(duì)話框類然后,在該文件中為CSocSend類添加一公有成員變量和一個(gè)構(gòu)造函數(shù),語(yǔ)句如下:CSocSend(CSocCltDlg*pDlgSocClt);CSocCltDlg*m_pDlgSocClt;//定義一個(gè)對(duì)話框類的指針接著,在SocSend.cpp文件中添加新的構(gòu)造函數(shù)的實(shí)現(xiàn)代碼,并添加一條關(guān)于CSocCltDlg.h文件的預(yù)編譯聲明,代碼如下:#include"SocCltDlg.h"http://對(duì)話框類,包含進(jìn)來(lái)CSocSend::CSocSend(CSocCltDlg*pDlgSocClt){m_pDlgSocClt=pDlgSocClt;}這樣,便完成了對(duì)話框和套接字之間的連接了。2.4、為套接字添加串行化讀寫(xiě)信息的功能在SocSend.h文件中,為類CSocSend添加三個(gè)公有成員變量,代碼如下:CSocketFile*m_pCSocFile;CArchive*m_pCArcIn;CArchive*m_pCArcOut;2.5、在對(duì)話框中初始化套接字并建立連接在對(duì)話框類的OnInitDialog函數(shù)中添加如下代碼m_lst_log.AddString("正在連接??");if(m_pCSocSend=newCSocSend(this)){if(m_pCSocSend->Create())//創(chuàng)建套接字{//if(m_pCSocSend->Connect("localhost",1000))//服務(wù)器名稱、端口號(hào)if(m_pCSocSend->Connect("cy-sys",1000))//服務(wù)器名稱、端口號(hào){m_pCSocSend->m_pCSocFile=newCSocketFile(m_pCSocSend);m_pCSocSend->m_pCArcIn=newCArchive(m_pCSocSend->m_pCSocFile,CArchive::load);m_pCSocSend->m_pCArcOut=newCArchive(m_pCSocSend->m_pCSocFile,CArchive::store);m_lst_log.AddString("連接成功,可以開(kāi)始傳遞消息咯~");m_btn_send.EnableWindow(TRUE);}else11{m_lst_log.AddString("連接不成功~");deletem_pCSocSend;//清除socket所占內(nèi)存}}else{m_lst_log.AddString("初始化失敗,請(qǐng)重新啟動(dòng)程序");deletem_pCSocSend;//清除socket所占內(nèi)存}}else{m_lst_log.AddString("初始化失敗,請(qǐng)重新啟動(dòng)程序");}2.6、接收消息消息到來(lái)時(shí),會(huì)引發(fā)套接字的OnReceive消息

溫馨提示

  • 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

評(píng)論

0/150

提交評(píng)論