




版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領
文檔簡介
1、 . 1 / 68VC+網絡聊天軟件摘摘 要要網絡聊天室,其實質就是基于 Internet 的一種網絡聊天軟件。它可以在網絡環境下進行實時的一對多或多對多的匿名交談。網絡聊天室軟件的制作方法有很多種,比如用 MFC 和 Java 等語言設計的就有很多,本次課程設計主要是利用 MFC 所提供的各種控件尤其是 WinSock 控件,基于 C/S 模式,設計了一個網絡聊天室,圓滿地實現在網絡上實時聊天與多種人性化的輔助功能。關鍵詞:WinSockWinSock;C/SC/S ;VisualVisual C+C+ 6.06.0;聊天室聊天室 . 2 / 68目錄目錄.查找資料 41.1 網絡聊天程序的
2、開發背景 41.2 網絡聊天程序的設計目標 4.相關知識 52.1 WINSOCK介紹 52.2MFC 的 CASYNCSOCKET類和 CSOCKET類 62.3 利用 CSOCKET進行有連接的通信 82.4 方案比較與選擇 9.詳細設計 .14.1 聊天程序現 .15.程序流程圖 624.1 建立連接的流程圖 624.2 客戶關閉或者注銷時的程序流程圖 63.程序運行結果 645.1 客戶端 645.2 服務端 64、討論與進一步研究建議 65、課程設計心得 66、參考文獻 67 . 3 / 681.查找資料當前是數字信息時代,網絡時代,獲得信息的渠道做種多樣。而最為快速的當然就是網絡了
3、。所以在課程設計動員之后,我們就馬不停蹄的通過互聯網收縮有關網絡編程和 MFC 編程的有關資料。找到大量資料之后,我們還有根據課程設計的要求進行篩選資料,最后選定方案和確定實現方法。這也是我們第一階段的工作。 1.1 網絡聊天程序的開發背景近年來,互連網發展日新月異,網絡使空間的距離不再成為人們溝通的障礙,世界各個角落的人們可以通過 Internet 收發、實時聊天、獲取最新的資訊。所以網絡聊天的程序早已被前人所實現,而且實現的方法多種多樣。因此,本次課程設計,我們主要借鑒前人創立的方法和編程經驗來制作一個 C/S 聊天室程序,通過制作該程序達到的學習網絡 socket 編程和使用 MFC 編
4、程的相關知識。 1.2 網絡聊天程序的設計目標本課題是設計一個網絡聊天的程序,包括服務器端和客戶端,主要功能為: 客戶端部分:、輸入服務器端 IP 地址和端口號進行連接、發送消息給服務器端并顯示服務器端回傳的消息、在客戶端增加歷史聊天記錄和當天聊天記錄、可以設置個性昵稱、增添快捷表情、更換個性圖像和背景設計服務器端部分:、立服務器端與客戶端的連接請求 . 4 / 68、接收所有用戶發送的消息、向所有在線用戶群發消息、在客戶端增加歷史聊天記錄和當天聊天記錄、可以設置個性昵稱、增添快捷表情、更換個性圖像和背景設計通過這次課程設計,可以比較深入的了解和掌握 WINSOCK 控件基本屬性、方法和事件,
5、熟悉 VC+的開發環境。理解網絡聊天通信的概念,輸控制協議(TCP)進行數據交流,初步掌握網絡聊天通信程序的設計方法,以與 WINDOWS編程的一些方法。并能鞏固和擴展之前學過的知識,進行項目的設計開發訓練,更好的適應社會的需求。 . 5 / 682.相關知識2.1 Winsock 介紹Windows Sockets 規以 U.C. Berkeley 大學 BSD UNIX 中流行的 Socket 接口為例定義了一套 Micosoft Windows 下網絡編程接口。它不僅包含了人們所熟悉的 Berkeley Socket 風格的庫函數;也包含了一組針對 Windows 的擴展庫函數,以使程序
6、員能充分地利用 Windows 消息驅動機制進行編程。 Windows Sockets 規本意在于提供給應用程序開發者一套簡單的 API,并讓各家網絡軟件供應商共同遵守。此外,在一個特定版本 Windows 的基礎上,Windows Sockets 也定義了一個二進制接口(ABI) ,以此來保證應用 Windows Sockets API 的應用程序能夠在任何網絡軟件供應商的符合 Windows Sockets協議的實現上工作。因此這份規定義了應用程序開發者能夠使用,并且網絡軟件供應商能夠實現的一套庫函數調用和相關語義。 遵守這套 Windows Sockets 規的網絡軟件,我們稱之為 Wi
7、ndows Sockets兼容的,而 Windows Sockets 兼容實現的提供者,我們稱之為 Windows Sockets 提供者。一個網絡軟件供應商必須百分之百地實現 Windows Sockets規才能做到現 Windows Sockets 兼容。 任何能夠與 Windows Sockets 兼容實現協同工作的應用程序就被認為是具有 Windows Sockets 接口。我們稱這種應用程序為 Windows Sockets 應用程序。 Windows Sockets 規定義并記錄了如何使用 API 與 Internet 協議族(IPS,通常我們指的是 TCP/IP)連接,尤其要指出
8、的是所有的 Windows Sockets 實現都支持流套接口和數據報套接口. . 6 / 68 應用程序調用 Windows Sockets 的 API 實現相互之間的通訊。Windows Sockets 又利用下層的網絡通訊協議功能和操作系統調用實現實際的通訊工作。 2.22.2 MFCMFC 的的 CAsyncsocketCAsyncsocket 類和類和 CSocketCSocket 類類構造一個 CAsyncSocket 對象并使用該對象創建基礎 SOCKET 句柄。 套接字的創建:遵循兩階段構造的 MFC 模式。 例如: CAsyncSocket sock;sock.Create(
9、 ); / Use the default parameters - 或 - CAsyncSocket* pSocket = new CAsyncSocket;int nPort = 27;pSocket- Create( nPort, SOCK_DGRAM ); 上面的第一個構造函數在堆棧上創建一個 CAsyncSocket 對象,第二個構造函數在堆上創建 CAsyncSocket 。上面的第一個 Create 調用使用默認參數創建流式套接字,第二個 Create 調用創建具有指定端口和地址的數據文報套接字。 (任一個 Create 版本都可以和任一種構造方法一起使用。 ) Create 的
10、參數有: “端口”:短整型。 對于服務器套接字,必須指定端口。對于客戶端套接字,通常接受此參數的默認值,該值允許 Windows Sockets 選擇端口。 套接字類型: SOCK_STREAM (默認值)或 SOCK_DGRAM 。 套接字“地址” ,如“”或“128.56.22.8” 。 該地址為網絡上的網際協議 (IP) 地址。很可能要始終依賴此參數的默認值。 如果套接字是客戶端,則使用 CAsyncSocket:Connect 將此套接字對象連接到服務器套接字。 如果套接字是服務器,則將套接字設置為開始偵聽(使用 CAsyncSocket:Listen)來自客戶端的連接嘗試。接收到連接
11、請求時, . 7 / 68用 CAsyncSocket:Accept 接受該請求。 接受連接后,可以執行驗證密碼等任務。注意 Accept 成員函數采用對新的空 CSocket 對象的引用作為它的參數。在調用 Accept 之前,必須構造該對象。如果此套接字對象超出圍,則連接關閉。不要對這個新套接字對象調用 Create 。 通過調用 CAsyncSocket 對象的封裝 Windows Sockets API 函數的成員函數,與其他套接字進行通信。 如果在堆棧上創建了套接字對象,當包含函數超出圍時將調用此對象的析構函數。如果使用 new 運算符在堆上創建了套接字對象,則您必須負責使用 del
12、ete 運算符銷毀此對象。 析構函數在銷毀對象之前調用對象的 Close 成員函數。 . 8 / 682.3 利用 CSocket 進行有連接的通信微軟的 MFC 把復雜的 WinSock API 函數封裝到類里,這使得編寫網絡應用程序更容易。CAsyncSocket 類逐個封裝了 WinSock API,為高級網絡程序員 提供了更加有力而靈活的方法。這個類基于程序員了解網絡通訊的假設,目的是為了在 MFC 中使用 WinSock,程序員有責任處理諸如阻塞、字節順序和在Unicode 與 MBCS 間轉換字符的任務。為了給程序員提供更方便的接口以自動處理這些任務,MFC 給出 了CSocket
13、 類,這個類是由 CAsyncSocket 類繼承下來的,它提供了比CAsyncSocket 更高層的 WinSock API 接口。CSocket 類和 CSocketFile 類可以與 CArchive 類一起合作來管理發送和接收的數據,這使管理數據收發更加便利。CSocket 對象提供阻塞模式,這對于 CArchive 的同步操作是至關重要的。阻塞函數(如 Receive()、Send()、ReceiveFrom()、SendTo() 和 Accept())直到操作完成后才返回控制權。因此如果需要低層控制和高效率,就使用 CasyncSock 類;如果需要方便,則可使用 CSocket
14、類。由于我們對網絡底層的了解比較淺薄,所以這次課程設計我們選擇了采用CSocket 類來編程實現。下面主要針對這種方法進行講述。使用 CSocket 對象涉與 CArchive 和 CSocketFile 類對象。以下介紹的針對字節流型(即基于 TCP/IP 協議)套接字的操作步驟中,只有第 3 和第 4 步對于客戶端和服務端操作是不同的,其他步驟都一樣。 構造一個 CSocket 對象。 使用這個對象的 Create()成員函數產生一個 socket 對象。在客戶端程序中,除非需要數據報套接字,Create()函數一般情況下應該使用默認參數。而對于服務端程序,必須在調用 Create 時指定
15、一個端口。需要注意的是,CArchive 類對象不能與數據報(UDP)套接字一起工作,因此對于數據報套接字,CAsyncSocket 和 CSocket 的使用方法是一樣的。 如果是客戶端套接字,則調用 CAsyncSocket Connect()函數與服務端套接字連接;如果是服務端套接字,則調用 CAsyncSocketListen()開始監聽來自客戶端的連接請求,收到連接請求后,調用CAsyncSocketAccept()函數接受請求,建立連接。請注意 Accept()成員 . 9 / 68函數需要一個新的并且為空的 CSocket 對象作為它的參數。 重載 CSocket類的部分函數。客
16、戶端需要重載 OnReceive(int i) 和 OnClose(int i);服務器端需要重載 OnAccept(int i) 、OnClose(int i) 和 OnReceive(int i); 調用 Send()的方法來發送數據,調用 Receive()的方法來接受數據。 調用 Close()方法來關閉套接字以終止通信。通訊完畢后,銷毀 CSocket 對象。2.42.4方案比較與選擇方案比較與選擇系統分析與設計系統分析與設計1、系統構架方式如下圖所示:設計出一個完整的網絡聊天程序,使之實現以上基本要求。1、 服務端需要完成的三件事1) 在特定端口等待連接請求,并需要維護一個客戶連接
17、表,已記錄所有成功連接。2) 與時接受消息,然后轉發到客戶連接。 . 10 / 683) 監控連接狀態,客戶離開或故障時從列表中刪除相應表項,并與時更新連接表。2、 客戶端需要完成的三件事1) 建立與維護服務器的連接,并隨時監測連接狀態。2) 把用戶輸入的信息與時發送到服務端,同時準備好接受,并顯示信息。3) 在用戶退出時關閉連接。程序方案程序方案比較:比較:方案一:基于方案一:基于 TCPTCP 的的 socketsocket 編程編程TCP(Transmission Control Protocol,傳輸控制協議)是基于連接的協議,也就是說,在正式收發數據前,必須和對方建立可靠的連接。服務
18、器端程序流程如下:1) 創建套接字(socket) ;2) 將套接字綁定到一個本地地址和端口上(bind) ;3) 將套接字設為監聽模式,準備接受客戶請求(listen) ;4) 等待客戶請求到來;當請求到來后,接受連接請求,返回一個新的對應于此次連接的套接字(accept) ;5) 用返回的套接字和客戶端進行通信(send/recv) ;6) 返回,等待另一客戶請求;7) 關閉套接字;客戶端程序流程如下:1) 創建套接字(socket) ;2) 向服務器發出連接請求(connect) ;3) 和服務器端進行通信(send/recv) ;4) 關閉套接字。在服務器端,當調用 accept 函數
19、時,程序就會等待,等待客戶調用connect 函數發出連接請求,然后服務器端接受該請求,于是雙方就建立了連 . 11 / 68接。之后,服務器端和客戶端就可以利用 send 和 recv 函數進行通信了。因為服務器需要接受客戶端的請求,所以必須告訴本地主機它打算在哪個 IP 地址和哪個端口上等待客戶要求,因此必須調用 bind 函數來實現這一功能。而對客戶端來說,當它發起連接請求,服務器端接受請求后,在服務端就保存了改客戶端的 IP 地址和端口的信息。這樣,對服務器端來說,一旦建立連接之后,實際上它已經保存了客戶端的 IP 地址和端口號的信息,就可以利用所返回的套接字調用 send/recv
20、函數與客戶端進行通信。程序流程圖如下:方案二:基于方案二:基于 UDPUDP(面向無連接)的(面向無連接)的 socketsocket 程序程序UDP(User Data Protocol,用戶數據報協議)是與 TCP 相對應的協議。它是面向非連接的協議,它不與對方建立連接,而是直接就把數據包發送過去。UDP 適用于一次只傳送少量數據、對可靠性要求不高的應用環境服務器端也叫接收端,對于基于 UDP(面向無連接)的套接字編程來說,它的服務器端和客戶端這種概念不是很強化,我們也可以把服務器端,即先啟 . 12 / 68動的一端稱為接收端,發送數據的一端稱為發送端,也稱為客戶端。服務端程序編寫流程如
21、下:1) 創建套接字(socket) ;2) 將套接字綁定到一個本地地址和端口上(bind) ;3) 等待接受數據(recvfrom) ;4) 關閉套接字。雖然面向無連接的 socket 編程無須建立連接,但是為了完成這次通信,對于接受端來說,它必須先啟動以接受客戶端發送的數據,因此接收端必須告訴主機它是在哪個地址和端口上等待數據的到來,接收端(服務器端)必須調用bind 函數將套接字綁定到一個本地地址和端口上。客戶端程序編寫流程如下:1) 創建套接字(socket) ;2) 向服務器發送數據(sengto) ;3) 關閉套接字。在 UDP 的套接字編程時,利用的是 sendto 和 recv
22、from 這兩個函數實現數據的發送和接收,而基于 TCP 的套接字編程時,發送數據是調用 send 函數,接受數據調用 recv 函數。程序流程圖如下: . 13 / 68方案比較結果方案比較結果TCP 與 UDP 最基本的區別在于基于連接與無連接,相比之下,第一種方案對系統的要求以與數據量都比較大,但是保證數據的正確性與數據順序,在傳輸大量數據的時候具有更高的可靠性。至于第二種方案的優點在于傳輸的速度快,程序結構精簡。總的來說,我認為 TCP 協議更能滿足目前各行業對遠程數據傳輸的要求,它提供更穩定更便利的傳輸通道,滿足了對安全性的要求以與遠程數據傳輸的要求。所以我們小組選擇方案一。 . 1
23、4 / 683.3.詳細設計詳細設計我們利用 MFC 提供的 CSocket 類來編程實現一個網絡聊天室。那么就需要一個聊天的服務器(即是服務端) ,它可以和很多客戶端進行通信,從而把來自不同的客戶的聊天信息轉交到所有其他的客戶端。當然也需要用戶界面(客戶端) 。這樣就形成了一個采用Client/Server 結構的并可以多人同時在線的聊天室。同時,服務器端應該有一定的管理功能,如手動/自動響應申請、設置服務器名稱和服務器端口、在線統計、單獨斷開某人連接以與保持聊天記錄等功能。對于客戶端,因為是面向用戶,所以外觀和功能都應有更高的要求。實現諸如:手動輸入 IP 和用戶名、頭像切換、心情書寫、表
24、情輸入、軟件皮膚切換、注銷登錄、保存聊天記錄以與伸縮界面等功能。下面詳細介紹各項功能是如何實現 . 15 / 68的。3.13.1 聊天程序的實現聊天程序的實現(1)首先啟動 Visual C+ 6.0,利用 MFC AppWizardEXE建立一個新的 MFC工程,工程名為 chat,在 MFC AppWizard Step1 的時候選擇 Dialog based 即基于對話框,在 Step4 時勾選 Windows Sockets 選項(如圖表 02) ,其他默認值下一步。圖表 01 . 16 / 68圖表 02(2)客戶端的界面如圖圖表 03 所示。其中包含文檔編輯框、按鍵控件、靜態文本
25、控件組成。左半邊由上自下分別是:頭像、昵稱、當天聊天信息顯示、12個表情按鈕、消息輸入框和發送按鈕。右半邊有歷史記錄顯示框、歷史記錄顯示按鈕。圖表 03 軟件界面 . 17 / 68圖表 04 控件類型與各自 ID標題控件類型控件 ID昵稱:StaticIDC_STATIC服務器 IP:StaticIDC_STATIC端口號(默認 5000):StaticIDC_STATIC頭像ButtonIDC_TouXiang表情 1ButtonIDC_BQ1表情 2ButtonIDC_BQ2表情 3ButtonIDC_BQ3表情 4ButtonIDC_BQ4表情 5ButtonIDC_BQ5表情 6Bu
26、ttonIDC_BQ6表情 7ButtonIDC_BQ7表情 8ButtonIDC_BQ8表情 9ButtonIDC_BQ9表情 10ButtonIDC_BQ10表情 11ButtonIDC_BQ11表情 12ButtonIDC_BQ12發送ButtonIDC_SEND連接ButtonIDC_CONNECT建立ButtonIDC_SETSERVER聊天紀錄ButtonIDC_LiaoTianJiLu聊天信息顯示EditIDC_SHOWTEXT信息輸入EditIDC_INPUTTEXT昵稱輸入EditIDC_NAME服務器 IP 輸入EditIDC_SERVERIP端口輸入EditIDC_POR
27、T聊天記錄顯示EditIDC_ShowHistory . 18 / 68聊天程序總共有 6 個類。其中,CChatApp 和 CAboutDlg 由 AppWizard 實現;另外,CServerSocket 和 CClientSocket 分別負責服務端和客戶端的網絡通信功能;CChatDlg 為程序的主控類,主界面、通信方式與程序邏輯均由該類實現,它繼承自 CDialog 類;CMessgage 是對消息的封裝。CClientSocketCClientSocket通過相應的 OnReceive 消息來接收數據,響應 OnClose 消息來斷開對話的處理,實現以 CArchive 對數據進行
28、的串行化。類定義代碼如下:#includeMessg.h /命令目標class CChatDlg;class CClientSocket:public CSocketpublic: CArchive *m_aSessionIn; CArchive *m_aSessionOut; CSocketFile *m_sfSocketFile; CChatDlg *m_dlg; bool m_bInit; /是否進行了初始化 bool m_bClose; /連接是否關閉public: void Init(CChatDlg *dlg); BOOL SendMessage(CMessg *msg); voi
29、d CloseSocket();public: static int GetLocalHostName(CString &sHostName); /獲得本地 . 19 / 68計算機名稱 static int GetIpAddress(const CString &sHostName, CString &sIpAddress); /獲得本地 IP static int GetIpAddress(const CString &sHostName,BYTE &f0, BYTE &f1,BYTE &f2,BYTE &f3); /獲得本地 IP static CString ErrorReason(i
30、nt tag);public: virtual void OnReceive(int nErrorCode); virtual void OnClose(int nErrorCode);public: CClientSocket(); virtual CClientSocket();protected:;CClientSocket.CPPCClientSocket.CPP 中的代碼:中的代碼:#include stdafx.h#include chat.h#include ClientSocket.h#includeChatDlg.h/ CClientSocketCClientSocket:C
31、ClientSocket() m_aSessionIn=NULL;m_aSessionOut=NULL; m_sfSocketFile=NULL; m_bInit=false; . 20 / 68 m_bClose=false;CClientSocket:CClientSocket() if(m_aSessionIn) delete m_aSessionIn; if(m_aSessionOut) delete m_aSessionOut; if(m_sfSocketFile) delete m_sfSocketFile;/ClientSocket 成員函數void CClientSocket:
32、OnReceive(int nErrorCode) CSocket:OnReceive(nErrorCode); /OnReceive()函數的實現 do CMessg temp; temp.Serialize(*m_aSessionIn); m_dlg-m_sMsgList+=temp.m_strText+rn;m_dlg-m_tmpMsgList=temp.m_strText+rn;m_dlg-SetDlgItemText(IDC_SHOWTEXT,m_dlg-m_sMsgList);FILE* fp;fp = fopen(chatnote.txt,a+);fputs(m_dlg-m_tm
33、pMsgList,fp);fclose(fp); m_dlg-SetDlgItemText(IDC_SHOWTEXT,m_dlg-m_sMsgList); int linenum=(CEdit*) . 21 / 68 (m_dlg-GetDlgItem(IDC_SHOWTEXT)-GetLineCount(); (CEdit*) (m_dlg-GetDlgItem(IDC_SHOWTEXT)-LineScroll(linenum); if(!m_dlg-m_bClient) for(POSITION pos=m_dlg-m_connectionList.GetHeadPosition(); p
34、os!=NULL;) CClientSocket *t=(CClientSocket*) m_dlg-m_connectionList.GetNext(pos); if(t-m_hSocket!=this-m_hSocket) t-SendMessage(&temp); while(!m_aSessionIn-IsBufferEmpty();void CClientSocket:Init(CChatDlg *dlg) m_sfSocketFile=new CSocketFile(this); m_aSessionIn=new CArchive(m_sfSocketFile,CArchive:l
35、oad); m_aSessionOut=new CArchive(m_sfSocketFile,CArchive:store); m_bClose=false; this-m_dlg=dlg; . 22 / 68/*SendMessage()函數的實現*主要功能:*將信息串行化*/BOOL CClientSocket:SendMessage(CMessg *msg) if(m_aSessionOut!=NULL) msg-Serialize(*m_aSessionOut); m_aSessionOut-Flush(); return TRUE; else m_bClose=true; /對方關
36、閉了連接 CloseSocket(); m_dlg-CloseSessionSocket(); return FALSE; /*CloseSocket()函數的實現*主要功能:*關閉套接字的連接 . 23 / 68*/void CClientSocket:CloseSocket() if(m_aSessionIn) delete m_aSessionIn; m_aSessionIn=NULL; if(m_aSessionOut) delete m_aSessionOut; m_aSessionOut=NULL; if(m_sfSocketFile) delete m_sfSocketFile;
37、 m_sfSocketFile=NULL; Close(); m_bInit=false; m_bClose=true;/*OnClose()函數的實現*主要功能:*關閉套接字的連接*/void CClientSocket:OnClose(int nErrorCode) . 24 / 68 m_bClose=true; CloseSocket(); m_dlg-CloseSessionSocket(); CSocket:OnClose(nErrorCode);/*GetLocalHostName()函數的實現*主要功能:*獲得本地計算機的名稱*/int CClientSocket:GetLoc
38、alHostName(CString &sHostName) char szHostName256; int nRetCode; nRetCode=gethostname(szHostName,sizeof(szHostName); if(nRetCode!=0) /產生錯誤 sHostName=_T(沒有取得); return GetLastError(); sHostName=szHostName; return 0;/*GetIpAddress()函數的實現*主要功能:*取得本地 IP 地址*/int CClientSocket:GetIpAddress(const CString &s
39、HostName,CString . 25 / 68&sIpAddress) /獲得本地 IP struct hostent FAR *lpHostEnt=gethostbyname(sHostName); if(lpHostEnt=NULL) /產生錯誤 sIpAddress=_T(); return GetLastError(); LPSTR lpAddr=lpHostEnt-h_addr_list0; if(lpAddr) struct in_addr inAddr; memmove(&inAddr,lpAddr,4); sIpAddress=inet_ntoa(inAddr); /轉換
40、為標準格式 if(sIpAddress.IsEmpty() sIpAddress=_T(沒有取得); return 0;/* GetIpAddress ()函數的實現*主要功能:*獲得本地 IP 地址*/int CClientSocket:GetIpAddress(const CString &sHostName,BYTE &f0, BYTE &f1,BYTE &f2,BYTE &f3)/獲得IP 地址 . 26 / 68 struct hostent FAR *lpHostEnt=gethostbyname(sHostName); if(lpHostEnt=NULL) /產生錯誤 f0=f1
41、=f2=f3=0; return GetLastError(); LPSTR lpAddr=lpHostEnt-h_addr_list0; /獲取 IP if(lpAddr) struct in_addr inAddr; memmove(&inAddr,lpAddr,4); f0=inAddr.S_un.S_un_b.s_b1; f1=inAddr.S_un.S_un_b.s_b2; f2=inAddr.S_un.S_un_b.s_b3; f3=inAddr.S_un.S_un_b.s_b4; return 0;CString CClientSocket:ErrorReason(int tag
42、) /錯誤信息的宏定義 CString result; switch(tag) case WSANOTINITIALISED: result=A successful AfxSocketInit must occur before using this API.; break; . 27 / 68 case WSAENETDOWN: result=The network subsystem failed; break; case WSAEADDRINUSE: result=The specified address is already in use; break; case WSAEINPR
43、OGRESS: result=A blocking Windows Socket call is in progress; break; case WSAEADDRNOTAVAIL: result=The specified address is not available from the local machine; break; case WSAEAFNOSUPPORT: result=Address in the specified family cannot be used with this socket; break; case WSAECONNREFUSED: result=T
44、he attempt to connect eas rejected; break; case WSAEDESTADDRREQ: result=A destination address is requireed; break; case WSAEFAULT: result=The nSockAddrLen arguement is incorrect; break; case WSAEINVAL: result=Invalid host address; break; . 28 / 68 case WSAEISCONN: result=The socket is already connec
45、ted; break; case WSAEMFILE: result=No more file descriptions are available; break; case WSAENETUNREACH: result=The network cannot be reached from this host at this time; break; case WSAENOBUFS: result=No buffer space is available.The socket cannot be connected; break; case WSAENOTSOCK: result=The de
46、scriptor is not a socket; break; case WSAETIMEDOUT: result=Attempt to connect timed out without establishing a connection; break; case WSAEWOULDBLOCK: result=The socket is marked as nonblocking and the connnection cannot be completed immediately; break; default: result=unknown error; return result;
47、. 29 / 68CServerSocketCServerSocketCServerSocket 主要功能是實現 OnAccept()消息,負責監聽服務窗口,是一個服務 socket。CServerSocket.h 的代碼如下:/ CServerSocket command targetclass CChatDlg;class CServerSocket: public CSocketpublic: CServerSocket(); virtual CServerSocket(); CChatDlg *m_dlg; UINT m_uPort; BOOL Init(UINT port,CChat
48、Dlg *dlg);public: virtual void OnAccept(int nErrorCode); /用于響應 OnAccept 消息的函數;CServerSocket.CPPCServerSocket.CPP 的代碼如下:的代碼如下:#include stdafx.h#include chat.h#include ServerSocket.h#include ChatDlg.h . 30 / 68/ CServerSocketCServerSocket:CServerSocket()CServerSocket:CServerSocket()/CServerSocket 成員函數
49、BOOL CServerSocket:Init(UINT port,CChatDlg *dlg) m_uPort=port; m_dlg=dlg; if(Create(m_uPort)=FALSE) AfxMessageBox(_T(Server Socket Create Error); return FALSE; if(this-Listen()=FALSE) AfxMessageBox(Server Listen Error); return FALSE; m_dlg-SetDlgItemText(IDC_SHOWTEXT,Serverr Has Been Set OK!); retur
50、n TRUE; void CServerSocket:OnAccept(int nErrorCode) . 31 / 68 m_dlg-ProcessPendingAccept(); CSocket:OnAccept(nErrorCode);CMessgCMessgCMessg 類主要作用是實現信息的串行化,方便信息的傳輸。CMessg.h 代碼如下:#pragma onceclass CMessg:public CObject /命令目標protected: DECLARE_DYNCREATE(CMessg)public: CMessg();public: CString m_strText
51、;public: void Init();public: virtual CMessg(); virtual void Serialize(CArchive &ar); /實行串行化#if def_DEBUG virtual void AssertValid() const; virtual void Dump(CDumpContext &dc) const;#endif; . 32 / 68CMessg.CPPCMessg.CPP 代碼如下:代碼如下:#include stdafx.h#include chat.h#include Messg.h/ Construction/Destruct
52、ionIMPLEMENT_DYNCREATE(CMessg,CObject)CMessg:CMessg() Init();CMessg:CMessg()/CMessg 成員函數void CMessg:Init() m_strText = _T();/CMsg serializationvoid CMessg:Serialize(CArchive &ar) if (ar.IsStoring() arm_strText; /CMsg diagnostics#if def_DEBUGvoid CMessg:AssertValid() const CObject:AssertValid();void
53、CMessg:Dump(CDumpContext&dc) const CObject:Dump(dc);#endifCChatDlgCChatDlgCChatDlg 類負責調度整個工程,實現界面消息的添加與響應,組織整個工程的運行。1) 程序開始運行,進行對話框的初始化是在 OnInitDialog()函數中實現的,在開始的時候自動獲得本地機器的 IP 地址并顯示在 IP Address Control 控件中。2) 連接服務器按鈕消息的響應函數。完成服務器的連接,調用CClientSocket 類的 Connect 函數來實現,同時對連接返回的信息進行處理。3) 建立服務器按鈕信息的響應函數
54、。4) 發送按鈕消息的響應函數。讀取文本框中的信息,調用 CMessg 類的函數以實現信息的串行化,然后再調用 CClientSocket 類的 . 34 / 68SendMessage()函數將信息發送給建立連接的對方。ChatDlg.h 代碼如下:/ CChatDlg dialog#include ClientSocket.h#include ServerSocket.h/CChatDlg 對話框class CChatDlg : public CDialog/構造public: CChatDlg(CWnd* pParent = NULL); /標準構造函數 /對話框數據 enumIDD=I
55、DD_CHAT_DIALOG;protected: virtual void DoDataExchange(CDataExchange *pDX);protected: HICON m_hIcon; /生成的消息映射函數 virtual BOOL OnInitDialog(); afx_msg void OnSysCommand(UINT nID,LPARAM lParam); afx_msg void OnPaint(); /afx_msg void OnInputText(); afx_msg HCURSOR OnQueryDragIcon(); DECLARE_MESSAGE_MAP()
56、public: CString m_sInputText;public: CString name;public: CString m_sShowString;public: . 35 / 68UINT m_uPort; /添加的變量public: bool m_bInit; bool m_bClient; CClientSocket m_clientsocket; CServerSocket m_pListenSocket; CPtrList m_connectionList; CString m_sMsgList;CString m_tmpMsgList;public: void Proc
57、essPendingAccept(); void CloseSessionSocket(); void ClearContent(); void OnClearconnection();public: afx_msg void OnBnClickedConnect();public: afx_msg void OnBnClickedSetserver();public: afx_msg void OnBnClickedButton1();CChatDlg.CPPCChatDlg.CPP 代碼如下:代碼如下:#include stdafx.h#include chat.h#include cha
58、tDlg.h . 36 / 68#ifdef _DEBUG#define new DEBUG_NEW#undef THIS_FILEstatic char THIS_FILE = _FILE_;#endif/ CAboutDlg dialog used for App Aboutint TouXiangNum=0;CString LiaoTianJiLu;class CAboutDlg:public CDialogpublic: CAboutDlg(); enumIDD=IDD_ABOUTBOX;protected: virtual void DoDataExchange(CDataExcha
59、nge *pDX);protected: DECLARE_MESSAGE_MAP();CAboutDlg:CAboutDlg():CDialog(CAboutDlg:IDD)void CAboutDlg:DoDataExchange(CDataExchange *pDX) . 37 / 68 CDialog:DoDataExchange(pDX); BEGIN_MESSAGE_MAP(CAboutDlg,CDialog)END_MESSAGE_MAP()CChatDlg:CChatDlg(CWnd *pParent /*=NULL*/) :CDialog(CChatDlg:IDD,pParen
60、t)m_sInputText=_T(); name=_T();m_hIcon = AfxGetApp()-LoadIcon(IDR_MAINFRAME); /加載圖標 m_sShowString=_T(); m_uPort=5000; m_hIcon=AfxGetApp()-LoadIcon(IDR_MAINFRAME);void CChatDlg:DoDataExchange(CDataExchange *pDX) CDialog:DoDataExchange(pDX); DDX_Text(pDX,IDC_INPUTTEXT,m_sInputText); DDX_Text(pDX,IDC_N
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯系上傳者。文件的所有權益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經權益所有人同意不得將文件中的內容挪作商業或盈利用途。
- 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
- 6. 下載文件中如有侵權或不適當內容,請與我們聯系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 六一快樂活動方案
- 六一教室活動方案
- 六一晨間游戲活動方案
- 六一活力節目活動方案
- 六一活動公司活動方案
- 六一活動呼啦圈活動方案
- 六一活動拍球活動方案
- 六一活動聯盟活動方案
- 六一活動集體街舞活動方案
- 六一涮鍋活動方案
- 物理降溫法與熱療技術試題
- 2017年12月大學英語四級真題試卷及答案(三套全)
- 汽車起重機日常檢查維修保養記錄表
- GB/T 43334-2023獨立型微電網能量管理系統技術要求
- 垃圾分類督導服務投標方案(技術標)
- 23秋國家開放大學《電氣控制與PLC》形考任務1-4參考答案
- 內部審核首末次會議簽到表
- 英語演講智慧樹知到課后章節答案2023年下重慶大學
- 魯迅故鄉原文故鄉魯迅
- 老舊小區改造投標方案(全套技術標)
- 政府采購處理流程圖
評論
0/150
提交評論