版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
1、<p><b> 摘 要</b></p><p> 網(wǎng)絡(luò)聊天室,其實(shí)質(zhì)就是基于Internet的一種網(wǎng)絡(luò)聊天軟件。它可以在網(wǎng)絡(luò)環(huán)境下進(jìn)行實(shí)時(shí)的一對(duì)多或多對(duì)多的匿名交談。網(wǎng)絡(luò)聊天室軟件的制作方法有很多種,比如用MFC 和Java等語言設(shè)計(jì)的就有很多,本次課程設(shè)計(jì)主要是利用MFC所提供的各種控件尤其是WinSock控件,基于C/S模式,設(shè)計(jì)了一個(gè)網(wǎng)絡(luò)聊天室,圓滿地實(shí)現(xiàn)在網(wǎng)絡(luò)上實(shí)時(shí)
2、聊天及多種人性化的輔助功能。</p><p> 關(guān)鍵詞:WinSock;C/S ;Visual C++ 6.0;聊天室</p><p><b> 目錄</b></p><p><b> ?。?查找資料4</b></p><p> 1.1 網(wǎng)絡(luò)聊天程序的開發(fā)背景4</p>&l
3、t;p> 1.2 網(wǎng)絡(luò)聊天程序的設(shè)計(jì)目標(biāo)4</p><p><b> ?。?相關(guān)知識(shí)5</b></p><p> 2.1 Winsock介紹5</p><p> 2.2 MFC 的CAsyncsocket類和CSocket類6</p><p> 2.3 利用CSocket進(jìn)行有連接的通信..
4、................................8</p><p> 2.4 方案比較與選擇...............................................9</p><p> 3.詳細(xì)設(shè)計(jì)........................................................14</p><p
5、> 3.1聊天程序現(xiàn)....................................................15</p><p> ?。?程序流程圖62</p><p> 4.1 建立連接的流程圖62</p><p> 4.2 客戶關(guān)閉或者注銷時(shí)的程序流程圖63</p><p> ?。?程序運(yùn)行結(jié)果64&l
6、t;/p><p> 5.1 客戶端64</p><p><b> 5.2服務(wù)端64</b></p><p> ?。?、討論及進(jìn)一步研究建議...........................................65</p><p> 7、課程設(shè)計(jì)心得...........................
7、.......................66</p><p> ?。?、參考文獻(xiàn).......................................................67</p><p><b> 1.查找資料 </b></p><p> 當(dāng)前是數(shù)字信息時(shí)代,網(wǎng)絡(luò)時(shí)代,獲得信息的渠道做種多樣。而最為快速的當(dāng)然就是
8、網(wǎng)絡(luò)了。所以在課程設(shè)計(jì)動(dòng)員之后,我們就馬不停蹄的通過互聯(lián)網(wǎng)收縮有關(guān)網(wǎng)絡(luò)編程和MFC編程的有關(guān)資料。找到大量資料之后,我們還有根據(jù)課程設(shè)計(jì)的要求進(jìn)行篩選資料,最后選定方案和確定實(shí)現(xiàn)方法。這也是我們第一階段的工作。 </p><p> 1.1 網(wǎng)絡(luò)聊天程序的開發(fā)背景 </p><p> 近年來,互連網(wǎng)發(fā)展日新月異,網(wǎng)絡(luò)使空間的距離不再成為人們溝通的障礙,世界各個(gè)角落的人們可以通過Inter
9、net收發(fā)郵件、實(shí)時(shí)聊天、獲取最新的資訊。所以網(wǎng)絡(luò)聊天的程序早已被前人所實(shí)現(xiàn),而且實(shí)現(xiàn)的方法多種多樣。因此,本次課程設(shè)計(jì),我們主要借鑒前人創(chuàng)立的方法和編程經(jīng)驗(yàn)來制作一個(gè)C/S聊天室程序,通過制作該程序達(dá)到的學(xué)習(xí)網(wǎng)絡(luò)socket編程和使用MFC編程的相關(guān)知識(shí)。 </p><p> 1.2 網(wǎng)絡(luò)聊天程序的設(shè)計(jì)目標(biāo) </p><p> 本課題是設(shè)計(jì)一個(gè)網(wǎng)絡(luò)聊天的程序,包括服務(wù)器端和客戶端,主
10、要功能為: 客戶端部分:</p><p> ?。?、輸入服務(wù)器端IP地址和端口號(hào)進(jìn)行連接</p><p> 2、發(fā)送消息給服務(wù)器端并顯示服務(wù)器端回傳的消息</p><p> 3、在客戶端增加歷史聊天記錄和當(dāng)天聊天記錄 </p><p> 4、可以設(shè)置個(gè)性昵稱、增添快捷表情、更換個(gè)性圖像和背景設(shè)計(jì)</p><p>&
11、lt;b> 服務(wù)器端部分:</b></p><p> 立服務(wù)器端與客戶端的連接請(qǐng)求</p><p> ?。病⒔邮账杏脩舭l(fā)送的消息</p><p> 3、向所有在線用戶群發(fā)消息</p><p> ?。础⒃诳蛻舳嗽黾託v史聊天記錄和當(dāng)天聊天記錄 </p><p> ?。?、可以設(shè)置個(gè)性昵稱、增添快捷表
12、情、更換個(gè)性圖像和背景設(shè)計(jì)</p><p> 通過這次課程設(shè)計(jì),可以比較深入的了解和掌握WINSOCK控件基本屬性、方法和事件,熟悉VC++的開發(fā)環(huán)境。理解網(wǎng)絡(luò)聊天通信的概念,輸控制協(xié)議(TCP)進(jìn)行數(shù)據(jù)交流,初步掌握網(wǎng)絡(luò)聊天通信程序的設(shè)計(jì)方法,以及WINDOWS編程的一些方法。并能鞏固和擴(kuò)展之前學(xué)過的知識(shí),進(jìn)行項(xiàng)目的設(shè)計(jì)開發(fā)訓(xùn)練,更好的適應(yīng)社會(huì)的需求。 </p><p><b&g
13、t; 2.相關(guān)知識(shí)</b></p><p> 2.1 Winsock介紹</p><p> Windows Sockets規(guī)范以U.C. Berkeley大學(xué)BSD UNIX中流行的Socket接口為范例定義了一套Micosoft Windows下網(wǎng)絡(luò)編程接口。它不僅包含了人們所熟悉的Berkeley Socket風(fēng)格的庫函數(shù);也包含了一組針對(duì)Windows的擴(kuò)展庫函數(shù)
14、,以使程序員能充分地利用Windows消息驅(qū)動(dòng)機(jī)制進(jìn)行編程。 Windows Sockets規(guī)范本意在于提供給應(yīng)用程序開發(fā)者一套簡(jiǎn)單的API,并讓各家網(wǎng)絡(luò)軟件供應(yīng)商共同遵守。此外,在一個(gè)特定版本W(wǎng)indows的基礎(chǔ)上,Windows Sockets也定義了一個(gè)二進(jìn)制接口(ABI),以此來保證應(yīng)用Windows Sockets API的應(yīng)用程序能夠在任何網(wǎng)絡(luò)軟件供應(yīng)商的符合Windows Sockets協(xié)議的實(shí)
15、現(xiàn)上工作。因此這份規(guī)范定義了應(yīng)用程序開發(fā)者能夠使用,并且網(wǎng)絡(luò)軟件供應(yīng)商能夠?qū)崿F(xiàn)的一套庫函數(shù)調(diào)用和相關(guān)語義。 遵守這套Windows Sockets規(guī)范的網(wǎng)絡(luò)軟件,我們稱之為Windows Sockets兼容的,而Windows Sockets兼容實(shí)現(xiàn)的提供者,我們稱之為Windows Soc</p><p> 2.2 MFC 的CAsyncsocket類和CSocket類</
16、p><p> 構(gòu)造一個(gè) CAsyncSocket 對(duì)象并使用該對(duì)象創(chuàng)建基礎(chǔ) SOCKET 句柄。 </p><p> ?、偬捉幼值膭?chuàng)建:遵循兩階段構(gòu)造的 MFC 模式。 </p><p><b> 例如: </b></p><p> CAsyncSocket sock;sock.Create( ); // Use th
17、e default parameters </p><p><b> - 或 - </b></p><p> CAsyncSocket* pSocket = new CAsyncSocket;int nPort = 27;</p><p> pSocket-> Create( nPort, SOCK_DGRAM ); </p&
18、gt;<p> 上面的第一個(gè)構(gòu)造函數(shù)在堆棧上創(chuàng)建一個(gè) CAsyncSocket 對(duì)象,第二個(gè)構(gòu)造函數(shù)在堆上創(chuàng)建 CAsyncSocket 。上面的第一個(gè) Create 調(diào)用使用默認(rèn)參數(shù)創(chuàng)建流式套接字,第二個(gè) Create 調(diào)用創(chuàng)建具有指定端口和地址的數(shù)據(jù)文報(bào)套接字。(任一個(gè) Create 版本都可以和任一種構(gòu)造方法一起使用。) </p><p> Create 的參數(shù)有: </p>
19、<p> “端口”:短整型。 </p><p> 對(duì)于服務(wù)器套接字,必須指定端口。對(duì)于客戶端套接字,通常接受此參數(shù)的默認(rèn)值,該值允許 Windows Sockets 選擇端口。 </p><p> 套接字類型: SOCK_STREAM (默認(rèn)值)或 SOCK_DGRAM 。 </p><p> 套接字“地址”,如“ftp1.scau.edu.cn
20、”或“128.56.22.8”。 該地址為網(wǎng)絡(luò)上的網(wǎng)際協(xié)議 (IP) 地址。很可能要始終依賴此參數(shù)的默認(rèn)值。 </p><p> ?、谌绻捉幼质强蛻舳?,則使用 CAsyncSocket::Connect 將此套接字對(duì)象連接到服務(wù)器套接字。 如果套接字是服務(wù)器,則將套接字設(shè)置為開始偵聽(使用 CAsyncSocket::Listen)來自客戶端的連接嘗試。接收到連接請(qǐng)求時(shí),用 CAsyncSocket::Acce
21、pt 接受該請(qǐng)求。 </p><p> ③接受連接后,可以執(zhí)行驗(yàn)證密碼等任務(wù)。</p><p> 注意 Accept 成員函數(shù)采用對(duì)新的空 CSocket 對(duì)象的引用作為它的參數(shù)。在調(diào)用 Accept 之前,必須構(gòu)造該對(duì)象。如果此套接字對(duì)象超出范圍,則連接關(guān)閉。不要對(duì)這個(gè)新套接字對(duì)象調(diào)用 Create 。 </p><p> ?、芡ㄟ^調(diào)用 CAsyncSocke
22、t 對(duì)象的封裝 Windows Sockets API 函數(shù)的成員函數(shù),與其他套接字進(jìn)行通信。 </p><p> ?、萑绻诙褩I蟿?chuàng)建了套接字對(duì)象,當(dāng)包含函數(shù)超出范圍時(shí)將調(diào)用此對(duì)象的析構(gòu)函數(shù)。如果使用 new 運(yùn)算符在堆上創(chuàng)建了套接字對(duì)象,則您必須負(fù)責(zé)使用 delete 運(yùn)算符銷毀此對(duì)象。 析構(gòu)函數(shù)在銷毀對(duì)象之前調(diào)用對(duì)象的 Close 成員函數(shù)。</p><p> 2.3 利用CSo
23、cket進(jìn)行有連接的通信</p><p> 微軟的MFC把復(fù)雜的WinSock API函數(shù)封裝到類里,這使得編寫網(wǎng)絡(luò)應(yīng)用程序更容易。CAsyncSocket類逐個(gè)封裝了WinSock API,為高級(jí)網(wǎng)絡(luò)程序員 提供了更加有力而靈活的方法。這個(gè)類基于程序員了解網(wǎng)絡(luò)通訊的假設(shè),目的是為了在MFC中使用WinSock,程序員有責(zé)任處理諸如阻塞、字節(jié)順序和在Unicode與MBCS 間轉(zhuǎn)換字符的任務(wù)。</p>
24、;<p> 為了給程序員提供更方便的接口以自動(dòng)處理這些任務(wù),MFC給出 了CSocket類,這個(gè)類是由CAsyncSocket類繼承下來的,它提供了比CAsyncSocket更高層的WinSock API接口。CSocket類和CSocketFile類可以與CArchive類一起合作來管理發(fā)送和接收的數(shù)據(jù),這使管理數(shù)據(jù)收發(fā)更加便利。CSocket對(duì)象提供阻塞模式,這對(duì)于CArchive的同步操作是至關(guān)重要的。阻塞函數(shù)(如
25、Receive()、Send()、ReceiveFrom()、SendTo() 和Accept())直到操作完成后才返回控制權(quán)。</p><p> 因此如果需要低層控制和高效率,就使用CasyncSock類;如果需要方便,則可使用CSocket類。</p><p> 由于我們對(duì)網(wǎng)絡(luò)底層的了解比較淺薄,所以這次課程設(shè)計(jì)我們選擇了采用CSocket類來編程實(shí)現(xiàn)。下面主要針對(duì)這種方法進(jìn)行講述
26、。</p><p> 使用CSocket對(duì)象涉及CArchive和CSocketFile 類對(duì)象。以下介紹的針對(duì)字節(jié)流型(即基于TCP/IP協(xié)議)套接字的操作步驟中,只有第3和第4步對(duì)于客戶端和服務(wù)端操作是不同的,其他步驟都相同。 </p><p> ?、贅?gòu)造一個(gè)CSocket對(duì)象。 ② 使用這個(gè)對(duì)象的Create()成員函數(shù)產(chǎn)生一個(gè)socket對(duì)象。在客戶端程序中,除非需要數(shù)據(jù)
27、報(bào)套接字,Create()函數(shù)一般情況下應(yīng)該使用默認(rèn)參數(shù)。而對(duì)于服務(wù)端程序,必須在調(diào)用Create時(shí)指定一個(gè)端口。需要注意的是,CArchive類對(duì)象不能與數(shù)據(jù)報(bào)(UDP)套接字一起工作,因此對(duì)于數(shù)據(jù)報(bào)套接字,CAsyncSocket和CSocket 的使用方法是一樣的。 ?、?如果是客戶端套接字,則調(diào)用CAsyncSocket ∷Connect()函數(shù)與服務(wù)端套接字連接;如果是服務(wù)端套接字,則調(diào)用CAsyncSocket∷List
28、en()開始監(jiān)聽來自客戶端的連接請(qǐng)求,收到連接請(qǐng)求后,調(diào)用CAsyncSocket∷Accept()函數(shù)接受請(qǐng)求,建立連接。請(qǐng)注意Accept()成員函數(shù)需要一個(gè)新的并且為空的CSocket對(duì)象作為它的參數(shù)。 ?、?重載CSocket類的部分函數(shù)??蛻舳诵枰剌dOnReceive(int i) 和 OnClose(int i);服務(wù)器端需要重載OnAccept(int i) 、OnClose(int i) 和 OnR</p&g
29、t;<p> 2.4 方案比較與選擇 </p><p><b> 系統(tǒng)分析與設(shè)計(jì)</b></p><p> 1、系統(tǒng)構(gòu)架方式如下圖所示:</p><p> 設(shè)計(jì)出一個(gè)完整的網(wǎng)絡(luò)聊天程序,使之實(shí)現(xiàn)以上基本要求。</p><p> 服務(wù)端需要完成的三件事</p><p>
30、; 在特定端口等待連接請(qǐng)求,并需要維護(hù)一個(gè)客戶連接表,已記錄所有成功連接。</p><p> 及時(shí)接受消息,然后轉(zhuǎn)發(fā)到客戶連接。</p><p> 監(jiān)控連接狀態(tài),客戶離開或故障時(shí)從列表中刪除相應(yīng)表項(xiàng),并及時(shí)更新連接表。</p><p> 客戶端需要完成的三件事</p><p> 建立與維護(hù)服務(wù)器的連接,并隨時(shí)監(jiān)測(cè)連接狀態(tài)。</
31、p><p> 把用戶輸入的信息及時(shí)發(fā)送到服務(wù)端,同時(shí)準(zhǔn)備好接受,并顯示信息。</p><p> 在用戶退出時(shí)關(guān)閉連接。</p><p><b> 程序方案比較:</b></p><p> 方案一:基于TCP的socket編程</p><p> TCP(Transmission Control
32、 Protocol,傳輸控制協(xié)議)是基于連接的協(xié)議,也就是說,在正式收發(fā)數(shù)據(jù)前,必須和對(duì)方建立可靠的連接。</p><p> 服務(wù)器端程序流程如下:</p><p> 創(chuàng)建套接字(socket);</p><p> 將套接字綁定到一個(gè)本地地址和端口上(bind);</p><p> 將套接字設(shè)為監(jiān)聽模式,準(zhǔn)備接受客戶請(qǐng)求(listen
33、);</p><p> 等待客戶請(qǐng)求到來;當(dāng)請(qǐng)求到來后,接受連接請(qǐng)求,返回一個(gè)新的對(duì)應(yīng)于此次連接的套接字(accept);</p><p> 用返回的套接字和客戶端進(jìn)行通信(send/recv);</p><p> 返回,等待另一客戶請(qǐng)求;</p><p><b> 關(guān)閉套接字;</b></p>&
34、lt;p> 客戶端程序流程如下:</p><p> 創(chuàng)建套接字(socket);</p><p> 向服務(wù)器發(fā)出連接請(qǐng)求(connect);</p><p> 和服務(wù)器端進(jìn)行通信(send/recv);</p><p><b> 關(guān)閉套接字。</b></p><p> 在服務(wù)器端
35、,當(dāng)調(diào)用accept函數(shù)時(shí),程序就會(huì)等待,等待客戶調(diào)用connect函數(shù)發(fā)出連接請(qǐng)求,然后服務(wù)器端接受該請(qǐng)求,于是雙方就建立了連接。之后,服務(wù)器端和客戶端就可以利用send和recv函數(shù)進(jìn)行通信了。因?yàn)榉?wù)器需要接受客戶端的請(qǐng)求,所以必須告訴本地主機(jī)它打算在哪個(gè)IP地址和哪個(gè)端口上等待客戶要求,因此必須調(diào)用bind函數(shù)來實(shí)現(xiàn)這一功能。而對(duì)客戶端來說,當(dāng)它發(fā)起連接請(qǐng)求,服務(wù)器端接受請(qǐng)求后,在服務(wù)端就保存了改客戶端的IP地址和端口的信息。這
36、樣,對(duì)服務(wù)器端來說,一旦建立連接之后,實(shí)際上它已經(jīng)保存了客戶端的IP地址和端口號(hào)的信息,就可以利用所返回的套接字調(diào)用send/recv函數(shù)與客戶端進(jìn)行通信。</p><p><b> 程序流程圖如下:</b></p><p> 方案二:基于UDP(面向無連接)的socket程序</p><p> UDP(User Data Protoco
37、l,用戶數(shù)據(jù)報(bào)協(xié)議)是與TCP相對(duì)應(yīng)的協(xié)議。它是面向非連接的協(xié)議,它不與對(duì)方建立連接,而是直接就把數(shù)據(jù)包發(fā)送過去。UDP適用于一次只傳送少量數(shù)據(jù)、對(duì)可靠性要求不高的應(yīng)用環(huán)境</p><p> 服務(wù)器端也叫接收端,對(duì)于基于UDP(面向無連接)的套接字編程來說,它的服務(wù)器端和客戶端這種概念不是很強(qiáng)化,我們也可以把服務(wù)器端,即先啟動(dòng)的一端稱為接收端,發(fā)送數(shù)據(jù)的一端稱為發(fā)送端,也稱為客戶端。</p>&l
38、t;p> 服務(wù)端程序編寫流程如下:</p><p> 創(chuàng)建套接字(socket);</p><p> 將套接字綁定到一個(gè)本地地址和端口上(bind);</p><p> 等待接受數(shù)據(jù)(recvfrom);</p><p><b> 關(guān)閉套接字。</b></p><p> 雖然面向
39、無連接的socket編程無須建立連接,但是為了完成這次通信,對(duì)于接受端來說,它必須先啟動(dòng)以接受客戶端發(fā)送的數(shù)據(jù),因此接收端必須告訴主機(jī)它是在哪個(gè)地址和端口上等待數(shù)據(jù)的到來,接收端(服務(wù)器端)必須調(diào)用bind函數(shù)將套接字綁定到一個(gè)本地地址和端口上。</p><p> 客戶端程序編寫流程如下:</p><p> 創(chuàng)建套接字(socket);</p><p> 向服
40、務(wù)器發(fā)送數(shù)據(jù)(sengto);</p><p><b> 關(guān)閉套接字。</b></p><p> 在UDP的套接字編程時(shí),利用的是sendto和recvfrom這兩個(gè)函數(shù)實(shí)現(xiàn)數(shù)據(jù)的發(fā)送和接收,而基于TCP的套接字編程時(shí),發(fā)送數(shù)據(jù)是調(diào)用send函數(shù),接受數(shù)據(jù)調(diào)用recv函數(shù)。</p><p><b> 程序流程圖如下:</b
41、></p><p><b> 方案比較結(jié)果</b></p><p> TCP與UDP最基本的區(qū)別在于基于連接與無連接,相比之下,第一種方案對(duì)系統(tǒng)的要求以及數(shù)據(jù)量都比較大,但是保證數(shù)據(jù)的正確性與數(shù)據(jù)順序,在傳輸大量數(shù)據(jù)的時(shí)候具有更高的可靠性。至于第二種方案的優(yōu)點(diǎn)在于傳輸?shù)乃俣瓤欤绦蚪Y(jié)構(gòu)精簡(jiǎn)。</p><p> 總的來說,我認(rèn)為TCP
42、協(xié)議更能滿足目前各行業(yè)對(duì)遠(yuǎn)程數(shù)據(jù)傳輸?shù)囊?,它提供更穩(wěn)定更便利的傳輸通道,滿足了對(duì)安全性的要求以及遠(yuǎn)程數(shù)據(jù)傳輸?shù)囊蟆?lt;/p><p> 所以我們小組選擇方案一。</p><p><b> 3.詳細(xì)設(shè)計(jì)</b></p><p> 我們利用MFC提供的CSocket類來編程實(shí)現(xiàn)一個(gè)網(wǎng)絡(luò)聊天室。那么就需要一個(gè)聊天的服務(wù)器(即是服務(wù)端),它可以
43、和很多客戶端進(jìn)行通信,從而把來自不同的客戶的聊天信息轉(zhuǎn)交到所有其他的客戶端。當(dāng)然也需要用戶界面(客戶端)。這樣就形成了一個(gè)采用Client/Server結(jié)構(gòu)的并可以多人同時(shí)在線的聊天室。同時(shí),服務(wù)器端應(yīng)該有一定的管理功能,如手動(dòng)/自動(dòng)響應(yīng)申請(qǐng)、設(shè)置服務(wù)器名稱和服務(wù)器端口、在線名單統(tǒng)計(jì)、單獨(dú)斷開某人連接以及保持聊天記錄等功能。對(duì)于客戶端,因?yàn)槭敲嫦蛴脩?,所以外觀和功能都應(yīng)有更高的要求。實(shí)現(xiàn)諸如:手動(dòng)輸入IP 和用戶名、頭像切換、心情書寫、
44、表情輸入、軟件皮膚切換、注銷登錄、保存聊天記錄以及伸縮界面等功能。下面詳細(xì)介紹各項(xiàng)功能是如何實(shí)現(xiàn)的。</p><p> 3.1聊天程序的實(shí)現(xiàn)</p><p> (1)首先啟動(dòng)Visual C++ 6.0,利用MFC AppWizard[EXE]建立一個(gè)新的MFC工程,工程名為chat,在MFC AppWizard Step1的時(shí)候選擇Dialog based 即基于對(duì)話框,在Step4
45、時(shí)勾選Windows Sockets選項(xiàng)(如圖表 02),其他默認(rèn)值下一步。</p><p><b> 圖表 01</b></p><p><b> 圖表 02</b></p><p> ?。?)客戶端的界面如圖圖表 03所示。其中包含文檔編輯框、按鍵控件、靜態(tài)文本控件組成。左半邊由上自下分別是:頭像、昵稱、當(dāng)
46、天聊天信息顯示、12個(gè)表情按鈕、消息輸入框和發(fā)送按鈕。右半邊有歷史記錄顯示框、歷史記錄顯示按鈕。</p><p> 圖表 03軟件界面</p><p><b> 圖表 04</b></p><p> 聊天程序總共有6個(gè)類。其中,CChatApp和CAboutDlg由AppWizard實(shí)現(xiàn);另外,CServerSocket和CClien
47、tSocket分別負(fù)責(zé)服務(wù)端和客戶端的網(wǎng)絡(luò)通信功能;CChatDlg為程序的主控類,主界面、通信方式及程序邏輯均由該類實(shí)現(xiàn),它繼承自CDialog類;CMessgage是對(duì)消息的封裝。</p><p> CClientSocket</p><p> 通過相應(yīng)的OnReceive消息來接收數(shù)據(jù),響應(yīng)OnClose消息來斷開對(duì)話的處理,實(shí)現(xiàn)以CArchive對(duì)數(shù)據(jù)進(jìn)行的串行化。</p
48、><p><b> 類定義代碼如下:</b></p><p> #include"Messg.h" //命令目標(biāo)</p><p> class CChatDlg;</p><p> class CClientSocket:public CSocket</p><p>&l
49、t;b> {</b></p><p><b> public:</b></p><p> CArchive *m_aSessionIn;</p><p> CArchive *m_aSessionOut;</p><p> CSocketFile *m_sfSocketFile;</p&
50、gt;<p> CChatDlg *m_dlg;</p><p> bool m_bInit; //是否進(jìn)行了初始化</p><p> bool m_bClose; //連接是否關(guān)閉</p><p><b> public:</b></p><p> void Init(CChatDlg *d
51、lg);</p><p> BOOL SendMessage(CMessg *msg);</p><p> void CloseSocket();</p><p><b> public:</b></p><p> static int GetLocalHostName(CString &sHostNam
52、e); //獲得本地計(jì)算機(jī)名稱</p><p> static int GetIpAddress(const CString &sHostName,</p><p> CString &sIpAddress); //獲得本地IP</p><p> static int GetIpAddress(const CString &sHos
53、tName,BYTE &f0,</p><p> BYTE &f1,BYTE &f2,BYTE &f3); //獲得本地IP</p><p> static CString ErrorReason(int tag);</p><p><b> public:</b></p><p>
54、; virtual void OnReceive(int nErrorCode);</p><p> virtual void OnClose(int nErrorCode);</p><p><b> public:</b></p><p> CClientSocket();</p><p> virtual
55、 ~CClientSocket();</p><p> protected:</p><p><b> };</b></p><p> CClientSocket.CPP中的代碼:</p><p> #include "stdafx.h"</p><p> #incl
56、ude "chat.h"</p><p> #include "ClientSocket.h"</p><p> #include"ChatDlg.h"</p><p> // CClientSocket</p><p> CClientSocket::CClientSock
57、et()</p><p><b> {</b></p><p> m_aSessionIn=NULL;</p><p> m_aSessionOut=NULL;</p><p> m_sfSocketFile=NULL;</p><p> m_bInit=false;</p>
58、<p> m_bClose=false;</p><p><b> }</b></p><p> CClientSocket::~CClientSocket()</p><p><b> {</b></p><p> if(m_aSessionIn)</p>&
59、lt;p> delete m_aSessionIn;</p><p> if(m_aSessionOut)</p><p> delete m_aSessionOut;</p><p> if(m_sfSocketFile)</p><p> delete m_sfSocketFile;</p><p>
60、;<b> }</b></p><p> //ClientSocket成員函數(shù)</p><p> void CClientSocket::OnReceive(int nErrorCode)</p><p><b> {</b></p><p> CSocket::OnReceive(nEr
61、rorCode); //OnReceive()函數(shù)的實(shí)現(xiàn)</p><p><b> do</b></p><p><b> {</b></p><p> CMessg temp;</p><p> temp.Serialize(*m_aSessionIn);</p>&l
62、t;p> m_dlg->m_sMsgList+=temp.m_strText+"\r\n";</p><p> m_dlg->m_tmpMsgList=temp.m_strText+"\r\n";</p><p> m_dlg->SetDlgItemText(IDC_SHOWTEXT,m_dlg->m_sMsgLi
63、st);</p><p><b> FILE* fp;</b></p><p> fp = fopen("chatnote.txt","a+");</p><p> fputs(m_dlg->m_tmpMsgList,fp);</p><p> fclose(fp)
64、;</p><p> m_dlg->SetDlgItemText(IDC_SHOWTEXT,m_dlg->m_sMsgList);</p><p> int linenum=((CEdit*)</p><p> (m_dlg->GetDlgItem(IDC_SHOWTEXT)))->GetLineCount();</p>
65、<p><b> ((CEdit*)</b></p><p> (m_dlg->GetDlgItem(IDC_SHOWTEXT)))->LineScroll(linenum);</p><p> if(!m_dlg->m_bClient)</p><p> { </p>
66、<p> for(POSITION pos=m_dlg->m_connectionList.GetHeadPosition();</p><p> pos!=NULL;)</p><p><b> {</b></p><p> CClientSocket *t=(CClientSocket*)</p>&l
67、t;p> m_dlg->m_connectionList.GetNext(pos);</p><p> if(t->m_hSocket!=this->m_hSocket)</p><p><b> {</b></p><p> t->SendMessage(&temp);</p>&l
68、t;p><b> }</b></p><p><b> }</b></p><p><b> }</b></p><p><b> }</b></p><p> while(!m_aSessionIn->IsBufferEmpty()
69、);</p><p><b> }</b></p><p> void CClientSocket::Init(CChatDlg *dlg)</p><p><b> {</b></p><p> m_sfSocketFile=new CSocketFile(this);</p>
70、<p> m_aSessionIn=new CArchive(m_sfSocketFile,CArchive::load);</p><p> m_aSessionOut=new CArchive(m_sfSocketFile,CArchive::store);</p><p> m_bClose=false;</p><p> this-&g
71、t;m_dlg=dlg;</p><p><b> }</b></p><p><b> /*</b></p><p> *SendMessage()函數(shù)的實(shí)現(xiàn)</p><p><b> *主要功能:</b></p><p><b>
72、 *將信息串行化</b></p><p><b> */</b></p><p> BOOL CClientSocket::SendMessage(CMessg *msg)</p><p><b> {</b></p><p> if(m_aSessionOut!=NULL)&l
73、t;/p><p><b> {</b></p><p> msg->Serialize(*m_aSessionOut);</p><p> m_aSessionOut->Flush();</p><p> return TRUE;</p><p><b> }</
74、b></p><p><b> else</b></p><p><b> {</b></p><p> m_bClose=true; //對(duì)方關(guān)閉了連接</p><p> CloseSocket();</p><p> m_dlg->CloseSes
75、sionSocket();</p><p> return FALSE;</p><p><b> }</b></p><p><b> }</b></p><p><b> /*</b></p><p> *CloseSocket()函數(shù)的實(shí)
76、現(xiàn)</p><p><b> *主要功能:</b></p><p><b> *關(guān)閉套接字的連接</b></p><p><b> */</b></p><p> void CClientSocket::CloseSocket()</p><p>
77、;<b> {</b></p><p> if(m_aSessionIn)</p><p><b> {</b></p><p> delete m_aSessionIn;</p><p> m_aSessionIn=NULL;</p><p><b>
78、 }</b></p><p> if(m_aSessionOut)</p><p><b> {</b></p><p> delete m_aSessionOut;</p><p> m_aSessionOut=NULL;</p><p><b> }</b
79、></p><p> if(m_sfSocketFile)</p><p><b> {</b></p><p> delete m_sfSocketFile;</p><p> m_sfSocketFile=NULL;</p><p><b> }</b>&
80、lt;/p><p><b> Close();</b></p><p> m_bInit=false;</p><p> m_bClose=true;</p><p><b> }</b></p><p><b> /*</b></p>
81、<p> *OnClose()函數(shù)的實(shí)現(xiàn)</p><p><b> *主要功能:</b></p><p><b> *關(guān)閉套接字的連接</b></p><p><b> */</b></p><p> void CClientSocket::OnClos
82、e(int nErrorCode)</p><p><b> {</b></p><p> m_bClose=true;</p><p> CloseSocket();</p><p> m_dlg->CloseSessionSocket();</p><p> CSocket::
83、OnClose(nErrorCode);</p><p><b> }</b></p><p><b> /*</b></p><p> *GetLocalHostName()函數(shù)的實(shí)現(xiàn)</p><p><b> *主要功能:</b></p><p&
84、gt; *獲得本地計(jì)算機(jī)的名稱</p><p><b> */</b></p><p> int CClientSocket::GetLocalHostName(CString &sHostName)</p><p><b> {</b></p><p> char szHostN
85、ame[256];</p><p> int nRetCode;</p><p> nRetCode=gethostname(szHostName,sizeof(szHostName));</p><p> if(nRetCode!=0)</p><p> { //產(chǎn)生錯(cuò)誤</p><p> sHost
86、Name=_T("沒有取得");</p><p> return GetLastError();</p><p><b> }</b></p><p> sHostName=szHostName;</p><p><b> return 0;</b></p>
87、<p><b> }</b></p><p><b> /*</b></p><p> *GetIpAddress()函數(shù)的實(shí)現(xiàn)</p><p><b> *主要功能:</b></p><p><b> *取得本地IP地址</b>&l
88、t;/p><p><b> */</b></p><p> int CClientSocket::GetIpAddress(const CString &sHostName,CString &sIpAddress)</p><p><b> //獲得本地IP</b></p><p>
89、;<b> {</b></p><p> struct hostent FAR *lpHostEnt=gethostbyname(sHostName);</p><p> if(lpHostEnt==NULL)</p><p> { //產(chǎn)生錯(cuò)誤</p><p> sIpAddress=_T("
90、");</p><p> return GetLastError();</p><p><b> }</b></p><p> LPSTR lpAddr=lpHostEnt->h_addr_list[0];</p><p> if(lpAddr)</p><p><b
91、> {</b></p><p> struct in_addr inAddr;</p><p> memmove(&inAddr,lpAddr,4);</p><p> sIpAddress=inet_ntoa(inAddr); //轉(zhuǎn)換為標(biāo)準(zhǔn)格式</p><p> if(sIpAddress.IsEm
92、pty())</p><p> sIpAddress=_T("沒有取得");</p><p><b> }</b></p><p><b> return 0;</b></p><p><b> }</b></p><p>&
93、lt;b> /*</b></p><p> * GetIpAddress ()函數(shù)的實(shí)現(xiàn)</p><p><b> *主要功能:</b></p><p><b> *獲得本地IP地址</b></p><p><b> */</b></p>
94、<p> int CClientSocket::GetIpAddress(const CString &sHostName,BYTE &f0,</p><p> BYTE &f1,BYTE &f2,BYTE &f3)//獲得IP地址</p><p><b> {</b></p><p>
95、; struct hostent FAR *lpHostEnt=gethostbyname(sHostName);</p><p> if(lpHostEnt==NULL)</p><p> { //產(chǎn)生錯(cuò)誤</p><p> f0=f1=f2=f3=0;</p><p> return GetLastError();</
96、p><p><b> }</b></p><p> LPSTR lpAddr=lpHostEnt->h_addr_list[0]; //獲取IP</p><p> if(lpAddr)</p><p><b> {</b></p><p> struct in
97、_addr inAddr;</p><p> memmove(&inAddr,lpAddr,4);</p><p> f0=inAddr.S_un.S_un_b.s_b1; </p><p> f1=inAddr.S_un.S_un_b.s_b2;</p><p> f2=inAddr.S_un.S_un_b.s_b3;&
98、lt;/p><p> f3=inAddr.S_un.S_un_b.s_b4;</p><p><b> }</b></p><p><b> return 0;</b></p><p><b> }</b></p><p> CString CCl
99、ientSocket::ErrorReason(int tag) //錯(cuò)誤信息的宏定義</p><p><b> {</b></p><p> CString result;</p><p> switch(tag)</p><p><b> {</b></p><p
100、> case WSANOTINITIALISED:</p><p> result="A successful AfxSocketInit must occur before using this API.";</p><p><b> break;</b></p><p> case WSAENETDOWN:
101、</p><p> result="The network subsystem failed";</p><p><b> break;</b></p><p> case WSAEADDRINUSE:</p><p> result="The specified address i
102、s already in use";</p><p><b> break;</b></p><p> case WSAEINPROGRESS:</p><p> result="A blocking Windows Socket call is in progress";</p><p&
103、gt;<b> break;</b></p><p> case WSAEADDRNOTAVAIL:</p><p> result="The specified address is not available from the local machine";</p><p><b> break;<
104、;/b></p><p> case WSAEAFNOSUPPORT:</p><p> result="Address in the specified family cannot be used with this socket";</p><p><b> break;</b></p><
105、;p> case WSAECONNREFUSED:</p><p> result="The attempt to connect eas rejected";</p><p><b> break;</b></p><p> case WSAEDESTADDRREQ:</p><p>
106、 result="A destination address is requireed";</p><p><b> break;</b></p><p> case WSAEFAULT:</p><p> result="The nSockAddrLen arguement is incorrect&qu
107、ot;;</p><p><b> break;</b></p><p> case WSAEINVAL:</p><p> result="Invalid host address";</p><p><b> break;</b></p><p&g
108、t; case WSAEISCONN:</p><p> result="The socket is already connected";</p><p><b> break;</b></p><p> case WSAEMFILE:</p><p> result="No m
109、ore file descriptions are available";</p><p><b> break;</b></p><p> case WSAENETUNREACH:</p><p> result="The network cannot be reached from this host at thi
110、s time";</p><p><b> break;</b></p><p> case WSAENOBUFS:</p><p> result="No buffer space is available.The socket cannot be connected";</p><p&
111、gt;<b> break;</b></p><p> case WSAENOTSOCK:</p><p> result="The descriptor is not a socket";</p><p><b> break;</b></p><p> case W
112、SAETIMEDOUT:</p><p> result="Attempt to connect timed out without establishing a connection";</p><p><b> break;</b></p><p> case WSAEWOULDBLOCK:</p>
113、<p> result="The socket is marked as nonblocking and the connnection cannot be completed immediately";</p><p><b> break;</b></p><p><b> default:</b><
114、/p><p> result="unknown error";</p><p><b> }</b></p><p> return result;</p><p><b> }</b></p><p> CServerSocket</p>
115、;<p> CServerSocket主要功能是實(shí)現(xiàn)OnAccept()消息,負(fù)責(zé)監(jiān)聽服務(wù)窗口,是一個(gè)服務(wù)socket。</p><p> CServerSocket.h的代碼如下:</p><p> // CServerSocket command target</p><p> class CChatDlg;</p><
116、p> class CServerSocket: public CSocket</p><p><b> {</b></p><p><b> public:</b></p><p> CServerSocket();</p><p> virtual ~CServerSocket()
117、;</p><p> CChatDlg *m_dlg;</p><p> UINT m_uPort;</p><p> BOOL Init(UINT port,CChatDlg *dlg);</p><p><b> public:</b></p><p> virtual void O
118、nAccept(int nErrorCode); //用于響應(yīng)OnAccept消息的函數(shù)</p><p><b> };</b></p><p> CServerSocket.CPP的代碼如下:</p><p> #include "stdafx.h"</p><p> #include &
119、quot;chat.h"</p><p> #include "ServerSocket.h"</p><p> #include "ChatDlg.h"</p><p> // CServerSocket</p><p> CServerSocket::CServerSocket()
120、</p><p><b> {</b></p><p><b> }</b></p><p> CServerSocket::~CServerSocket()</p><p><b> {</b></p><p><b> }<
121、/b></p><p> //CServerSocket成員函數(shù)</p><p> BOOL CServerSocket::Init(UINT port,CChatDlg *dlg)</p><p><b> {</b></p><p> m_uPort=port;</p><p>
122、 m_dlg=dlg;</p><p> if(Create(m_uPort)==FALSE)</p><p><b> {</b></p><p> AfxMessageBox(_T("Server Socket Create Error"));</p><p> return FALSE
123、;</p><p><b> }</b></p><p> if(this->Listen()==FALSE)</p><p><b> {</b></p><p> AfxMessageBox("Server Listen Error");</p>
124、<p> return FALSE;</p><p><b> }</b></p><p> m_dlg->SetDlgItemText(IDC_SHOWTEXT,"Serverr Has Been Set OK!");</p><p> return TRUE;</p><p&g
125、t;<b> }</b></p><p> void CServerSocket::OnAccept(int nErrorCode)</p><p><b> {</b></p><p> m_dlg->ProcessPendingAccept();</p><p> CSocket
126、::OnAccept(nErrorCode);</p><p><b> }</b></p><p><b> CMessg</b></p><p> CMessg類主要作用是實(shí)現(xiàn)信息的串行化,方便信息的傳輸。</p><p> CMessg.h代碼如下:</p><p&
127、gt; #pragma once</p><p> class CMessg:public CObject //命令目標(biāo)</p><p><b> {</b></p><p> protected:</p><p> DECLARE_DYNCREATE(CMessg)</p><p>
128、;<b> public:</b></p><p><b> CMessg();</b></p><p><b> public:</b></p><p> CString m_strText;</p><p><b> public:</b>&
129、lt;/p><p> void Init();</p><p><b> public:</b></p><p> virtual ~CMessg();</p><p> virtual void Serialize(CArchive &ar); //實(shí)行串行化</p><p>
130、#if def_DEBUG</p><p> virtual void AssertValid() const;</p><p> virtual void Dump(CDumpContext &dc) const;</p><p><b> #endif</b></p><p><b> };
131、</b></p><p> CMessg.CPP代碼如下:</p><p> #include "stdafx.h"</p><p> #include "chat.h"</p><p> #include "Messg.h"</p><p&g
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 眾賞文庫僅提供信息存儲(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ì)自己和他人造成任何形式的傷害或損失。
最新文檔
- vc++課程設(shè)計(jì)----用winsock實(shí)現(xiàn)聊天
- vc++軟件課程設(shè)計(jì)報(bào)告
- vc++課程設(shè)計(jì)--聊天室程序設(shè)計(jì)
- vc++課程設(shè)計(jì)報(bào)告
- vc++面向?qū)ο笳n程設(shè)計(jì)報(bào)告---局域網(wǎng)聊天程序
- 用vc++簡(jiǎn)單的多線程聊天室課程設(shè)計(jì)
- vc++網(wǎng)絡(luò)聊天室的實(shí)現(xiàn)計(jì)算機(jī)操作系統(tǒng)課程設(shè)計(jì)
- vc++庫函數(shù)課程設(shè)計(jì)
- mfc聊天軟件課程設(shè)計(jì)---網(wǎng)絡(luò)聊天程序設(shè)計(jì)
- vc++課程設(shè)計(jì)報(bào)告----對(duì)抗游戲
- vc++課程設(shè)計(jì)-- 餐飲管理系統(tǒng)
- vc++課程設(shè)計(jì)--工資管理
- mfc聊天軟件課程設(shè)計(jì)---網(wǎng)絡(luò)聊天程序設(shè)計(jì)
- vc++課程設(shè)計(jì)報(bào)告--對(duì)抗游戲
- vc++課程設(shè)計(jì)--工資管理
- 軟件課程設(shè)計(jì)---簡(jiǎn)易網(wǎng)絡(luò)聊天系統(tǒng)
- 網(wǎng)絡(luò)課程設(shè)計(jì)---使用vc++編程實(shí)現(xiàn)網(wǎng)絡(luò)嗅探器
- 課程設(shè)計(jì):網(wǎng)絡(luò)嗅探器設(shè)計(jì) sniffer vc++平臺(tái)
- vc++課設(shè)課程設(shè)計(jì)報(bào)告
- vc++課程設(shè)計(jì)報(bào)告---球員管理系統(tǒng)
評(píng)論
0/150
提交評(píng)論