2023年全國(guó)碩士研究生考試考研英語(yǔ)一試題真題(含答案詳解+作文范文)_第1頁(yè)
已閱讀1頁(yè),還剩38頁(yè)未讀 繼續(xù)免費(fèi)閱讀

下載本文檔

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

文檔簡(jiǎn)介

1、<p>  局域網(wǎng)即時(shí)通信軟件設(shè)計(jì)</p><p>  畢業(yè)論文(設(shè)計(jì))任務(wù)書(shū)</p><p><b>  院(系):文經(jīng)學(xué)院</b></p><p>  [摘 要] 即時(shí)通信在互聯(lián)網(wǎng)領(lǐng)域的應(yīng)用取得了巨大的成功,但是在學(xué)校、企業(yè)內(nèi)部的應(yīng)用仍遠(yuǎn)未普及。鑒于即時(shí)通信作為一項(xiàng)有廣泛應(yīng)用價(jià)值的技術(shù)框架,在逐步適應(yīng)企業(yè)網(wǎng)絡(luò)、教育網(wǎng)絡(luò)的應(yīng)用特點(diǎn)

2、后,局域網(wǎng)即時(shí)通信必將取得和電子郵件一樣的普及效果。該系統(tǒng)使用.NET作為開(kāi)發(fā)平臺(tái)、Mysql數(shù)據(jù)庫(kù)存儲(chǔ)用戶(hù)信息和聊天記錄,用套接字連接客戶(hù)端和服務(wù)器,用數(shù)據(jù)包套接字發(fā)送消息。本系統(tǒng)采用C/S模式構(gòu)建,由客戶(hù)端和服務(wù)器端組成。客戶(hù)端只要填寫(xiě)服務(wù)器的IP地址和通信端口號(hào),并通過(guò)所分配的賬號(hào),就可以登錄和使用。服務(wù)器與Mysql數(shù)據(jù)庫(kù)可部署在同一網(wǎng)段的任一節(jié)點(diǎn)上,通過(guò)接收客戶(hù)端不同請(qǐng)求而對(duì)數(shù)據(jù)庫(kù)進(jìn)行增刪改查的操作,這樣就可以方便的進(jìn)行維護(hù)并

3、且保證了同一局域網(wǎng)信息的安全和網(wǎng)絡(luò)資源的充分利用,并且最大程度的保證了數(shù)據(jù)庫(kù)的安全性。使用該系統(tǒng)可進(jìn)行一般的文字交流,查詢(xún)聊天記錄,及在線用戶(hù)顯示等功能。</p><p>  [關(guān)鍵詞] .NET Framework;Socket;多線程;Mysql數(shù)據(jù)庫(kù);TCP/IP協(xié)議;ADO.NET</p><p>  [Abstract] Instant messaging application

4、s on the Internet were a great success, but in schools, enterprises are still far from universal in application. In view of instant messaging applications as the value of a broad technical framework, and gradually adapt

5、to the corporate network, the application of the characteristics of the education network, the LAN access to instant messaging and e-mail will be the same universal effect.The introduction of the system. NET as a develop

6、ment platform, Mysql</p><p>  This can be convenient for maintenance and to ensure that the same local area network information security and make full use of network resources and ensure maximum safety of th

7、e database. The system can be used for general exchange of text, query chats, and online user functions.</p><p>  [Key words] .NET Framework; Socket; Thread; Mysql Database; TCP/IP; ADO.NET</p><p&

8、gt;<b>  目 錄</b></p><p><b>  前言1</b></p><p>  1.課題及開(kāi)發(fā)平臺(tái)簡(jiǎn)介1</p><p>  1.1 課題介紹1</p><p>  1.2 開(kāi)發(fā)平臺(tái)簡(jiǎn)介1</p><p>  1.3 編程語(yǔ)言簡(jiǎn)介(C#)2

9、</p><p>  1.4主要設(shè)計(jì)功能4</p><p>  2.數(shù)據(jù)庫(kù)設(shè)計(jì)及基本實(shí)現(xiàn)原理5</p><p>  2.1 數(shù)據(jù)庫(kù)設(shè)計(jì)5</p><p>  2.1.1 class表簡(jiǎn)介5</p><p>  2.1.2 user表簡(jiǎn)介5</p><p>  2.1.2 chatlog

10、表簡(jiǎn)介6</p><p>  2.2 基本實(shí)現(xiàn)原理7</p><p>  2.2.1 WINSOCK接口7</p><p>  2.2.2客戶(hù)機(jī)/服務(wù)器模式7</p><p>  2.3 二者的結(jié)合(DBA)8</p><p>  3.客戶(hù)端編程實(shí)現(xiàn)10</p><p>  3.1

11、用戶(hù)登陸功能10</p><p>  3.1.1 連接服務(wù)器11</p><p>  3.1.2 開(kāi)啟新線程用于接收服務(wù)器發(fā)回的消息11</p><p>  3.1.3 向服務(wù)器發(fā)送用戶(hù)名與密碼信息11</p><p>  3.2 接收服務(wù)器發(fā)回的指令12</p><p>  3.2.1 接收發(fā)回的原始消息并

12、還原12</p><p>  3.2.2 分析處理服務(wù)器發(fā)回的指令12</p><p>  3.3 登陸后界面初始化12</p><p>  3.3.1 驗(yàn)證成功與進(jìn)入主界面12</p><p>  3.3.2 初始化用戶(hù)列表13</p><p>  3.3.3 顯示在線用戶(hù)15</p>&l

13、t;p>  3.4 聊天功能16</p><p>  3.4.1 發(fā)送消息16</p><p>  3.4.2 接收消息18</p><p>  3.5 查詢(xún)聊天記錄功能19</p><p>  3.6 用戶(hù)離線22</p><p>  3.6.1 發(fā)送離線請(qǐng)求22</p><p&

14、gt;  3.6.2 接收用戶(hù)離線消息22</p><p>  3.7 報(bào)錯(cuò)功能23</p><p>  4.服務(wù)器端編程實(shí)現(xiàn)24</p><p>  4.1 啟動(dòng)服務(wù)24</p><p>  4.1.1 聲明變量24</p><p>  4.1.2 顯示服務(wù)器IP24</p><p&g

15、t;  4.1.3 啟動(dòng)服務(wù)24</p><p>  4.1.4 監(jiān)聽(tīng)客戶(hù)端請(qǐng)求25</p><p>  4.2 接收客戶(hù)端請(qǐng)求26</p><p>  4.3 根據(jù)客戶(hù)端不同請(qǐng)求做出操作26</p><p>  4.3.1 連接請(qǐng)求27</p><p>  4.3.2 即時(shí)聊天請(qǐng)求29</p>

16、<p>  4.3.3 查詢(xún)聊天記錄請(qǐng)求30</p><p>  4.3.4 用戶(hù)離線請(qǐng)求30</p><p>  4.4 即時(shí)發(fā)送“錯(cuò)誤”指令31</p><p><b>  5.結(jié)論32</b></p><p><b>  6.致謝33</b></p>&l

17、t;p><b>  參考文獻(xiàn)34</b></p><p><b>  前言</b></p><p>  由于因特網(wǎng)的迅速流行,越來(lái)越多的應(yīng)用程序具備了在網(wǎng)上與其它程序通信的能力。從WIN95開(kāi)始微軟把網(wǎng)絡(luò)功能融進(jìn)了它的操作系統(tǒng),使得應(yīng)用程序網(wǎng)絡(luò)通信能力更為普及。因此,微軟的TCP/IP協(xié)議也就成為網(wǎng)絡(luò)應(yīng)用程序基于的首選協(xié)議。</p&

18、gt;<p>  一般采用TCP/IP協(xié)議的應(yīng)用程序只實(shí)現(xiàn)了單用戶(hù)與服務(wù)器間點(diǎn)對(duì)點(diǎn)的連接,而本文在VC6.0的環(huán)境下,運(yùn)用了了多線程以及共享數(shù)據(jù)結(jié)構(gòu)技術(shù),不僅實(shí)現(xiàn)了多用戶(hù)與服務(wù)器間的連接,而且解決了多用戶(hù)間信息互發(fā)問(wèn)題----依靠服務(wù)器的轉(zhuǎn)發(fā)功能。并且,數(shù)據(jù)庫(kù)技術(shù)的引入,使得大數(shù)據(jù)保存成為了可能,并可在任意客戶(hù)端查詢(xún)聊天記錄。</p><p>  借助微軟Visual Studio2008 .NET

19、開(kāi)發(fā)平臺(tái),與其自帶的ADO.NET組件,使開(kāi)發(fā)效率大大提速。</p><p>  1.課題及開(kāi)發(fā)平臺(tái)簡(jiǎn)介</p><p><b>  1.1 課題介紹</b></p><p>  局域網(wǎng)即時(shí)通信,不同于大家熟知的MSN這樣的基于互聯(lián)網(wǎng)的即時(shí)通信,而是基于學(xué)校教育網(wǎng)、企業(yè)內(nèi)部局域網(wǎng)使用的即時(shí)通信。</p><p>  即時(shí)

20、通信在互聯(lián)網(wǎng)領(lǐng)域的應(yīng)用取得了巨大的成功,但是在學(xué)校、企業(yè)等內(nèi)部網(wǎng)絡(luò)的應(yīng)用仍遠(yuǎn)未普及。傳輸速度、總體投入及廣域網(wǎng)無(wú)法比肩的安全性,注定了局域網(wǎng)層出不窮的潛力,在學(xué)校、企業(yè)內(nèi)部更是如此。在這種前提下,一款可以即時(shí)收發(fā)消息用來(lái)收發(fā)通知,可查詢(xún)歷史消息的通信軟件的需求成為了必然。正是在這種前提下,結(jié)合實(shí)際情況,我決定開(kāi)發(fā)一套局域網(wǎng)即時(shí)通信軟件設(shè)計(jì)軟件。</p><p>  1.2 開(kāi)發(fā)平臺(tái)簡(jiǎn)介</p>&l

21、t;p>  .NET Framework 是微軟的幾個(gè)開(kāi)發(fā)團(tuán)隊(duì)一起努力發(fā)展的成果,最主要用來(lái)產(chǎn)生一個(gè)可以用來(lái)快速開(kāi)發(fā)、部署網(wǎng)站服務(wù)及應(yīng)用程序的開(kāi)發(fā)平臺(tái)。作為微軟公司繼WindowsDNA以來(lái)的新的開(kāi)發(fā)平臺(tái)。.Net Framework是以一種類(lèi)似于Java系統(tǒng)的虛擬機(jī)方式運(yùn)行和管理的編程平臺(tái),通過(guò)CLR為基礎(chǔ),支持多種語(yǔ)言(C#、VB.NET、C++、Python等)的開(kāi)發(fā)。</p><p>  C#是一種

22、安全的、穩(wěn)定的、簡(jiǎn)單的,由C和C++衍生出來(lái)的面向?qū)ο蟮木幊陶Z(yǔ)言。它在繼承C和C++強(qiáng)大功能的同時(shí)去掉了一些它們的復(fù)雜特性(例如沒(méi)有宏和模版,不允許</p><p>  多重繼承)。C#綜合了VB簡(jiǎn)單的可視化操作和C++的高運(yùn)行效率,以其強(qiáng)大的操作能力、優(yōu)雅的語(yǔ)法風(fēng)格、創(chuàng)新的語(yǔ)言特性和便捷的面向組件編程的支持成為.NET開(kāi)發(fā)的首選語(yǔ)言。</p><p>  在Visual Studio 2

23、008的C++語(yǔ)言當(dāng)中,MFC可以支持Vista的通用控件。Visual Studio 2008還支持智能感應(yīng),除此以外,對(duì)于AJAX引入了很多擴(kuò)展控件,從而可以快速開(kāi)發(fā)ASP.NET AJAX的應(yīng)用。新的Vista SDK中包含大量的非托管API。UAC(用戶(hù)訪問(wèn)控制)是Vista的一種訪問(wèn)控制機(jī)制,主要是防止病毒對(duì)系統(tǒng)的破壞。</p><p>  使用Visual Studio 2008可以高效開(kāi)發(fā)Windo

24、ws應(yīng)用。設(shè)計(jì)器中可以實(shí)時(shí)反映變更,XAML中智能感知功能可以提高開(kāi)發(fā)效率。同時(shí)Visual Studio 2008支持項(xiàng)目模板、調(diào)試器和部署程序。使用Expression交互式設(shè)計(jì)器可以無(wú)縫集成設(shè)計(jì)人員與開(kāi)發(fā)人員的工作流程。</p><p>  LINQ是一種用來(lái)進(jìn)行數(shù)據(jù)訪問(wèn)的編程模型,使得.NET語(yǔ)言可以直接支持?jǐn)?shù)據(jù)查詢(xún)。LINQ的目標(biāo)是降低訪問(wèn)數(shù)據(jù)的復(fù)雜度。LINQ可以用統(tǒng)一的方法訪問(wèn)不同類(lèi)型的數(shù)據(jù),可以將

25、數(shù)據(jù)作為對(duì)象使用,能夠更好地與編程模型集成,可以在Visual Studio 中進(jìn)行智能提示。</p><p>  1.3 編程語(yǔ)言簡(jiǎn)介(C#)</p><p>  1.面向?qū)ο蟮目梢暬幊谭椒ǎ?lt;/p><p>  用傳統(tǒng)程序設(shè)計(jì)語(yǔ)言設(shè)計(jì)程序時(shí),大都是通過(guò)編寫(xiě)程序代碼來(lái)實(shí)現(xiàn)用戶(hù)界面,在設(shè)計(jì)過(guò)程中看不到界面的實(shí)際顯示效果,必須編譯后運(yùn)行程序才能觀察,這很麻煩,大大影

26、響了軟件開(kāi)發(fā)的效率。C#則是應(yīng)用的面向?qū)ο蟮某绦蛟O(shè)計(jì)方法(OOP),提供了可視化的設(shè)計(jì)方法,它把程序和數(shù)據(jù)封裝起來(lái)作為一個(gè)對(duì)象,并為每個(gè)對(duì)象賦予應(yīng)有的屬性,使對(duì)象成為實(shí)在的東西。開(kāi)發(fā)人員不必再為界面設(shè)計(jì)而編寫(xiě)大量程序代碼,也不需要通過(guò)一遍遍編譯來(lái)修改不滿意之處了。只要按設(shè)計(jì)要求的屏幕布局,用系統(tǒng)提供的工具,在屏幕上畫(huà)出各種“部件”,即圖形對(duì)象,并設(shè)置這些圖形對(duì)象的屬性,就可以輕松完成任務(wù)了。C#會(huì)自動(dòng)產(chǎn)生界面設(shè)計(jì)代碼,程序設(shè)計(jì)人員不必再

27、手工編寫(xiě)實(shí)現(xiàn)程序功能的那些煩人的代碼,從而可以大大提高程序設(shè)計(jì)的效率。</p><p>  2.結(jié)構(gòu)化程序設(shè)計(jì)語(yǔ)言:</p><p>  C#是在C/C++語(yǔ)言的基礎(chǔ)上發(fā)展起來(lái)的,具有高級(jí)程序設(shè)計(jì)語(yǔ)言的語(yǔ)句結(jié)構(gòu),接近于自然語(yǔ)言和人類(lèi)的邏輯思維方式。C#語(yǔ)句簡(jiǎn)單易懂,其編輯器支持彩色代碼,可自動(dòng)進(jìn)行語(yǔ)法錯(cuò)誤檢查,同時(shí)具有功能強(qiáng)大且使用靈活的調(diào)試器和編譯器。</p><p&

28、gt;  C#是面向?qū)ο笮驼Z(yǔ)言,在輸入代碼的同時(shí),解釋系統(tǒng)將高級(jí)語(yǔ)言分解翻譯成計(jì)算機(jī)可以識(shí)別的機(jī)器指令,并判斷每個(gè)語(yǔ)句的語(yǔ)法錯(cuò)誤。在設(shè)計(jì)C#程序的過(guò)程中,隨時(shí)可以運(yùn)行程序,而在整個(gè)程序設(shè)計(jì)好之后,可以編譯生成可執(zhí)行文件(.EXE),脫離C#環(huán)境,直接在Windows環(huán)境下運(yùn)行。</p><p>  3.事件驅(qū)動(dòng)編程機(jī)制:</p><p>  C#通過(guò)事件來(lái)執(zhí)行對(duì)象的操作。一個(gè)對(duì)象可能會(huì)產(chǎn)生

29、多個(gè)事件,每個(gè)事件都可以通過(guò)一段程序來(lái)響應(yīng)。例如,命令按鈕是一個(gè)對(duì)象,當(dāng)用戶(hù)單擊該按鈕時(shí),將產(chǎn)生一個(gè)“單擊”(CLICK)事件,而在產(chǎn)生該事件時(shí)將執(zhí)行一段程序,用來(lái)實(shí)現(xiàn)指定的操作。</p><p>  在用C#設(shè)計(jì)大型應(yīng)用軟件時(shí),不必建立具有明顯開(kāi)始和結(jié)束的程序,而是編寫(xiě)若干個(gè)微小的子程序,即過(guò)程。這些過(guò)程分別面向不同的對(duì)象,由用戶(hù)操作引發(fā)某個(gè)事件來(lái)驅(qū)動(dòng)完成某種特定的功能,或者由事件驅(qū)動(dòng)程序調(diào)用通用過(guò)程來(lái)執(zhí)行指定

30、的操作,這樣可以方便編程人員,提高效率。</p><p>  4.訪問(wèn)數(shù)據(jù)庫(kù)功能:</p><p>  C#具有強(qiáng)大的數(shù)據(jù)庫(kù)管理功能,利用數(shù)據(jù)控件和數(shù)據(jù)庫(kù)管理窗口,可以直接建立或處理Microsoft SQL Server 2005 Express格式的數(shù)據(jù)庫(kù),并提供了強(qiáng)大的數(shù)據(jù)存儲(chǔ)和檢索功能。同時(shí),C#還能直接編輯和訪問(wèn)其他外部數(shù)據(jù)庫(kù),如:DATABASE,F(xiàn)oxPro,Paradox等

31、,這些數(shù)據(jù)庫(kù)格式都可以用C# 編輯和處理。</p><p>  C#提供開(kāi)放式數(shù)據(jù)連接,即ADO.NET功能,可通過(guò)直接訪問(wèn)或建立連接的方式使用并操作后臺(tái)大型網(wǎng)絡(luò)數(shù)據(jù)庫(kù),如SQL Server,Oracle等。在應(yīng)用程序中,可以使用結(jié)構(gòu)化查詢(xún)語(yǔ)言SQL數(shù)據(jù)標(biāo)準(zhǔn),直接訪問(wèn)服務(wù)器上的數(shù)據(jù)庫(kù),還提供了簡(jiǎn)單的面向?qū)ο蟮膸?kù)操作指令和多用戶(hù)數(shù)據(jù)庫(kù)訪問(wèn)的加鎖機(jī)制和網(wǎng)絡(luò)數(shù)據(jù)庫(kù)的SQL的編程技術(shù),為單機(jī)上運(yùn)行的數(shù)據(jù)庫(kù)提供了SQL網(wǎng)

32、絡(luò)接口,可以在分布式環(huán)境中快速而有效地實(shí)現(xiàn)客戶(hù)/服務(wù)器(client/server)方案。</p><p>  5.動(dòng)態(tài)數(shù)據(jù)交換(DDE)功能:</p><p>  利用動(dòng)態(tài)數(shù)據(jù)交換(Dynamic Data Exchange)技術(shù),可以把一種應(yīng)用程序中的數(shù)據(jù)動(dòng)態(tài)地鏈接到另一種應(yīng)用程序中,使兩種完全不同的應(yīng)用程序建立起一條動(dòng)態(tài)數(shù)據(jù)鏈路。當(dāng)原始數(shù)據(jù)變化時(shí),可以自動(dòng)更新鏈接的數(shù)據(jù)。C#提供了動(dòng)

33、態(tài)數(shù)據(jù)交換的編程技術(shù),可以在應(yīng)用程序中與其他Windows應(yīng)用程序建立動(dòng)態(tài)數(shù)據(jù)交換,在不同的應(yīng)用程序之間進(jìn)行通信。</p><p>  6.對(duì)象的鏈接與嵌入(OLE)功能:</p><p>  對(duì)象的鏈接與嵌入(OLE)將每個(gè)應(yīng)用程序都看作是一個(gè)對(duì)象(object),將不同的對(duì)象鏈接(link)起來(lái),再嵌入(embed)某個(gè)應(yīng)用程序中,從而可以得到具有聲音、影像、圖像、動(dòng)畫(huà)、文字等各種信息

34、的集合式的文件。利用OLE技術(shù),可以方便地建立復(fù)合式文檔(compound document),這種文檔由來(lái)自多個(gè)不同應(yīng)用程序的對(duì)象組成,文檔中的每個(gè)對(duì)象都與原來(lái)的應(yīng)用程序相聯(lián)系,并可執(zhí)行與原來(lái)應(yīng)用程序完全相同的操作。Visual Basic就采用了OLE技術(shù)。</p><p>  7.動(dòng)態(tài)鏈接庫(kù)(DLL)功能:</p><p>  C# 是一種高級(jí)程序設(shè)計(jì)語(yǔ)言,不具備低級(jí)語(yǔ)言的功能,對(duì)訪

35、問(wèn)機(jī)器硬件的操作不太容易實(shí)現(xiàn)。但它可以通過(guò)動(dòng)態(tài)鏈接庫(kù)技術(shù)將C/C++或匯編語(yǔ)言編寫(xiě)的程序加入到C# 應(yīng)用程序中,可以像調(diào)用內(nèi)部函數(shù)一樣調(diào)用其他語(yǔ)言編寫(xiě)的函數(shù)。此外,通過(guò)動(dòng)態(tài)鏈接庫(kù),還可以調(diào)用Windows應(yīng)用程序接口(API)函數(shù),實(shí)現(xiàn)SDK所具有的功能。</p><p><b>  1.4主要設(shè)計(jì)功能</b></p><p>  本程序需要具備以下功能:</p

36、><p><b>  用戶(hù)密碼驗(yàn)證功能;</b></p><p>  與在線用戶(hù)進(jìn)行即時(shí)通信交流;</p><p>  保存與離線好友交流文字信息功能;</p><p>  顯示所有好友在線和離線功能;</p><p><b>  查詢(xún)聊天記錄功能;</b></p>

37、<p>  2.數(shù)據(jù)庫(kù)設(shè)計(jì)及基本實(shí)現(xiàn)原理</p><p><b>  2.1 數(shù)據(jù)庫(kù)設(shè)計(jì)</b></p><p>  在Mysql中建立名稱(chēng)為client的數(shù)據(jù)庫(kù),并在此數(shù)據(jù)庫(kù)中創(chuàng)建chatlog、class、user三個(gè)數(shù)據(jù)表分別用來(lái)存放聊天記錄、存放班級(jí)信息和存放用戶(hù)信息。</p><p>  以下為對(duì)各個(gè)數(shù)據(jù)表的詳細(xì)說(shuō)明。&l

38、t;/p><p>  2.1.1 class表簡(jiǎn)介</p><p>  class數(shù)據(jù)表設(shè)計(jì)視圖如表2-1所示:</p><p>  表2-1 class表</p><p>  如上表所示,class表共有classBM、classNAME兩個(gè)字段,分別存放班級(jí)編碼和班級(jí)名稱(chēng),并且必須一一對(duì)應(yīng)。在設(shè)計(jì)程序中的好友列表中,作為所有學(xué)生的根節(jié)點(diǎn)。在好

39、友列表顯示時(shí),可根據(jù)學(xué)生所屬班級(jí)進(jìn)行方便快速的查找。所有學(xué)生必須只屬于一個(gè)班級(jí)編碼下,否則不能正常顯示。此表由服務(wù)器所在電腦維護(hù)。</p><p>  2.1.2 user表簡(jiǎn)介</p><p>  user數(shù)據(jù)表設(shè)計(jì)視圖如表2-2所示:</p><p>  表2-2 user表</p><p>  user表共有id、name、passwo

40、rd、classBM四個(gè)字段,分表用來(lái)存放用戶(hù)id、姓名、密碼、班級(jí)代碼。</p><p>  id字段為此數(shù)據(jù)表主鍵,不允許重復(fù),作為用戶(hù)的唯一標(biāo)示。可自動(dòng)生成。</p><p>  name字段為學(xué)生的姓名信息,可通過(guò)它登錄系統(tǒng)。</p><p>  password字段為此用戶(hù)的密碼,最多可維護(hù)進(jìn)15個(gè)字符。在系統(tǒng)登錄時(shí),填寫(xiě)的姓名與密碼必須同時(shí)驗(yàn)證成功才能正

41、確的登錄系統(tǒng)。</p><p>  classBM字段為學(xué)生所屬班級(jí)代碼,每條學(xué)生信息必須維護(hù)此字段,否則無(wú)法在用戶(hù)列表中正確顯示。</p><p>  2.1.2 chatlog表簡(jiǎn)介</p><p>  chatlog表視圖如表2-3所示:</p><p>  表2-3 chatlog表</p><p>  cha

42、tlog表共有FROMUSER、TOUSER、DATETIMEN、LOGS四字段,分表存放聊天記錄的發(fā)送方、接收方、時(shí)間、內(nèi)容。</p><p>  FROMUSER字段為聊天記錄發(fā)送方姓名,與表2中name字段外鍵關(guān)系,所以必須為user中用戶(hù)名稱(chēng)一致。</p><p>  TOUSER字段為聊天記錄接收方姓名,與表2中name字段外鍵關(guān)系,所以必須為user中用戶(hù)名稱(chēng)一致。</p

43、><p>  DATETIMEN字段為聊天記錄在服務(wù)器中轉(zhuǎn)的時(shí)間(精確到毫秒),此字段與FROMUSER、TOUSER字段共同作為此表的主鍵,保證了每條記錄主鍵不沖突。</p><p>  LOGS此字段用以存放聊天記錄,字段數(shù)據(jù)類(lèi)型為T(mén)EXT,所以可輕松用于可進(jìn)行大數(shù)據(jù)編輯。</p><p>  2.2 基本實(shí)現(xiàn)原理</p><p>  2.2

44、.1 WINSOCK接口</p><p>  WINSOCK標(biāo)準(zhǔn)定義了一個(gè)DLL接口,通常叫做WINSOCK.DLL或者WSOCK32.DLL。無(wú)論機(jī)器上安裝了哪一個(gè)DLL,只要函數(shù)的名字,參數(shù)含義以及最終的功能是相同的,應(yīng)用程序就可以調(diào)用這些函數(shù)。在插口編程里一個(gè)重要的概念就是一個(gè)插口的端口。局域網(wǎng)內(nèi)的每一個(gè)站點(diǎn)都有一個(gè)數(shù)字地址稱(chēng)為IP地址,通常是由“.”分開(kāi)的四個(gè)數(shù)。在機(jī)器上運(yùn)行的程序可以隨心所欲地用端口與其

45、他機(jī)器進(jìn)行通信。多數(shù)端口的工作是基于連接的:兩個(gè)程序在每一端用一個(gè)端口形成一個(gè)連接,然后沿著該連接收發(fā)數(shù)據(jù)。有些應(yīng)用程序傾向無(wú)連接地發(fā)送,但是這些數(shù)據(jù)的到達(dá)是沒(méi)有保障的。 WINSOCK.DLL實(shí)際上是作為WinSock應(yīng)用程序和TCP/IP協(xié)議棧之間的中間層。用戶(hù)的應(yīng)用程序告訴WINSOCK.DLL需要做什么,WINSOCK.DLL將這些命令傳送到TCP/IP協(xié)議棧,由TCP/IP協(xié)議棧傳送到網(wǎng)絡(luò)。但是重要的事情是用戶(hù)必須注意

46、用戶(hù)使用的WINSOCK.DLL必須和TCP/IP的版本號(hào)一致。</p><p>  2.2.2客戶(hù)機(jī)/服務(wù)器模式</p><p>  由于Winsock支持多種協(xié)議上的網(wǎng)絡(luò)程序開(kāi)發(fā), 比如TCP、UDP、和IP等等。由于這次課程設(shè)計(jì)是實(shí)現(xiàn)點(diǎn)到點(diǎn)的可靠連接,所以在此使用TCP連接方式。在這個(gè)連接中,雙方分為客戶(hù)和服務(wù)器,他們各自的功能不同。</p><p>  客戶(hù)

47、機(jī)一方,TCP/IP應(yīng)用程序功能如下:</p><p> ?。?) 打開(kāi)通信信道(申請(qǐng)一套接字),并連接到服務(wù)器在主機(jī)的保留端口,該端口對(duì)應(yīng)服務(wù)器的TCP/IP進(jìn)程。</p><p> ?。?) 向服務(wù)器發(fā)出請(qǐng)求報(bào)文,等待接收應(yīng)答。</p><p> ?。?) 從服務(wù)器方收到最終應(yīng)答結(jié)果,或在不再請(qǐng)求時(shí)關(guān)閉信道并終止客戶(hù)機(jī)進(jìn)程。</p><p&g

48、t;  服務(wù)器一方,TCP/IP應(yīng)用程序動(dòng)作如下:</p><p> ?。?) 打開(kāi)通信信道(申請(qǐng)一套接字),通知本地主機(jī)在某一保留端口接收客戶(hù)機(jī)請(qǐng)求。</p><p> ?。?) 等待客戶(hù)請(qǐng)求到達(dá)指定端口。</p><p> ?。?) 接收到請(qǐng)求,啟動(dòng)一新進(jìn)程處理用戶(hù)請(qǐng)求,同時(shí)釋放舊進(jìn)程以響應(yīng)新的客戶(hù)請(qǐng)求,一旦服務(wù)完成,關(guān)閉新進(jìn)程與客戶(hù)的通信鏈路。</p&g

49、t;<p>  (4) 繼續(xù)等待客戶(hù)機(jī)請(qǐng)求。</p><p> ?。?) 如果不想響應(yīng)客戶(hù)機(jī)請(qǐng)求,關(guān)閉服務(wù)器進(jìn)程。</p><p>  綜上所述,TCP/IP應(yīng)用中的服務(wù)器程序必須先于客戶(hù)機(jī)進(jìn)程啟動(dòng),直到對(duì)客戶(hù)機(jī)的響應(yīng)結(jié)束或強(qiáng)迫終止。其面向連接的應(yīng)用程序流程圖如圖2-1。</p><p>  圖2-1 C/S模式</p><p>

50、;  2.3 二者的結(jié)合(DBA)</p><p>  1.與C# 的連接:</p><p>  C# 提供了與底層數(shù)據(jù)庫(kù)系統(tǒng)緊密的連接。它支持不同的關(guān)系數(shù)據(jù)庫(kù)管理系統(tǒng)并充分發(fā)揮每一個(gè)數(shù)據(jù)庫(kù)的特長(zhǎng),生成獨(dú)立應(yīng)用或脫離服務(wù)器運(yùn)行的應(yīng)用程序。C# 連接數(shù)據(jù)庫(kù)的方式有兩種:</p><p>  方式一,通過(guò)使用C# 的 DATA控件;方式二,通過(guò)使用由C# 提供的專(zhuān)用的直

51、接與數(shù)據(jù)庫(kù)相連的接口。</p><p>  2.Mysql驅(qū)動(dòng)與DATA 控件的橋梁作用:</p><p>  使用Mysql公司的.NET驅(qū)動(dòng)包mysql-connector-net-6.0.3,并引用驅(qū)動(dòng)包內(nèi)已編譯好Mysql類(lèi)組件,便可以更方便的在VisualStudio2008中操作Mysql數(shù)據(jù)庫(kù)。</p><p>  DATA在數(shù)據(jù)庫(kù)中的信息與將信息顯示

52、給用戶(hù)看的C# 程序之間架起了一座橋梁。我們可以設(shè)置DATA控件的各個(gè)屬性,告訴它要調(diào)用哪個(gè)數(shù)據(jù)庫(kù)的哪個(gè)部分。缺省情況下,DATA控件根據(jù)數(shù)據(jù)庫(kù)中的一個(gè)或多個(gè)數(shù)據(jù)表建立一個(gè)dynaset-type(動(dòng)態(tài)集合)類(lèi)型的記錄集合。一個(gè)記錄集合是動(dòng)態(tài)的也就意味著,當(dāng)原來(lái)的數(shù)據(jù)表中的內(nèi)容改變了以后,該記錄集合中的記錄也會(huì)隨之改變。</p><p>  DATA控件還提供了用來(lái)瀏覽不同記錄的各種跳轉(zhuǎn)按鈕。將DATA控件放置在

53、窗體中之后,我們還必須在該控件與要處理的數(shù)據(jù)庫(kù)之間建立聯(lián)系。</p><p><b>  3.客戶(hù)端編程實(shí)現(xiàn)</b></p><p>  客戶(hù)端安裝在與服務(wù)器同一局域網(wǎng)的任意一臺(tái)計(jì)算機(jī)上,用戶(hù)通過(guò)正確用戶(hù)名與密碼便可登錄,并進(jìn)行與服務(wù)器或者其他客戶(hù)端的即時(shí)通信。</p><p>  下面將對(duì)客戶(hù)端的各功能進(jìn)行介紹:</p><

54、;p>  3.1 用戶(hù)登陸功能</p><p>  登陸界面如圖3-1所示:</p><p>  圖3-1 登陸界面圖</p><p>  賬號(hào)文本框:填寫(xiě)用戶(hù)名;</p><p>  密碼文本框:填寫(xiě)用戶(hù)密碼;</p><p>  服務(wù)器IP框:填寫(xiě)服務(wù)器所在計(jì)算機(jī)的局域網(wǎng)IP地址;</p>&l

55、t;p>  服務(wù)器端口文本框:填寫(xiě)服務(wù)器所開(kāi)此服務(wù)的端口號(hào),本系統(tǒng)缺省默認(rèn)為服務(wù)器的“1234”端口。</p><p>  3.1.1 連接服務(wù)器</p><p>  使用類(lèi):System.Net.Sockets.TcpClent為T(mén)CP網(wǎng)絡(luò)服務(wù)提供客戶(hù)端連接,類(lèi): System.Net.Sockets.NetworkStream提供用于網(wǎng)絡(luò)訪問(wèn)的基礎(chǔ)數(shù)據(jù)流。聲明為全局變量代碼如下:

56、</p><p>  TcpClient tcpClinet;//與服務(wù)器的連接(客戶(hù)端)</p><p>  private NetworkStream stream;//與服務(wù)器數(shù)據(jù)交互的流通道</p><p>  將用戶(hù)名、密碼、服務(wù)器IP、服務(wù)器端口號(hào)填寫(xiě)完成后,點(diǎn)擊登陸按鈕,將實(shí)例化TcpClient類(lèi)的新實(shí)例,并使用指定的IP地址與端口號(hào)將客戶(hù)端連接到T

57、CP主機(jī)。代碼如下:</p><p>  tcpClinet = new TcpClient();</p><p>  tcpClinet.Connect(IPAddress.Parse(txtServerIP.Text), Int32.Parse(txtDK.Text));//連接遠(yuǎn)程服務(wù)器</p><p>  其中txtServerIP.Text為服務(wù)器IP文本

58、框內(nèi)容 txtDK.Text為服務(wù)器端口號(hào)文本框內(nèi)容。</p><p>  然后返回用于發(fā)送和接收數(shù)據(jù)的NetworkStream:</p><p>  stream = tcpClinet.GetStream();</p><p>  3.1.2 開(kāi)啟新線程用于接收服務(wù)器發(fā)回的消息</p><p>  在計(jì)算機(jī)的同一線程內(nèi)同時(shí)處理發(fā)出與接收

59、的消息是沒(méi)有保證的,所以編寫(xiě)Incept()函數(shù)來(lái)接受服務(wù)器的請(qǐng)求。并開(kāi)啟另外一個(gè)線程,用于接收服務(wù)器發(fā)回的消息,并作出相應(yīng)的處理。聲明新線程,并啟動(dòng),代碼如下:</p><p>  ThreadStart incept = new ThreadStart(this.Incept);</p><p>  Thread thread = new Thread(incept);</p&g

60、t;<p>  thread.Start();</p><p>  3.1.3 向服務(wù)器發(fā)送用戶(hù)名與密碼信息</p><p>  因?yàn)橛糜诰W(wǎng)絡(luò)訪問(wèn)的基礎(chǔ)數(shù)據(jù)流的數(shù)據(jù)類(lèi)型為字符編碼,所以將用戶(hù)名與密碼轉(zhuǎn)化為字符編碼數(shù)組,然后寫(xiě)入基礎(chǔ)數(shù)據(jù)流NetworkStream,服務(wù)器便能接收到消息。</p><p>  創(chuàng)建字符串,以“CON”作為前綴,并以“|”符

61、號(hào)將用戶(hù)名與密碼隔開(kāi),以便服務(wù)器進(jìn)行分析,代碼如下:</p><p>  string userName = txtID.Text.ToString();</p><p>  string cmd = "CON|" + userName+ "|" + txtPASSWORD.Text + "|";</p><p

62、>  消息格式為:“CON|用戶(hù)名|密碼|”。</p><p>  然后將此字符串轉(zhuǎn)化為字符編碼數(shù)組,并寫(xiě)入NetworkStream,代碼如下:</p><p>  Byte[] outbytes = System.Text.Encoding.Default.</p><p>  GetBytes(cmd.ToCharArray());</p>

63、<p>  stream.Write(outbytes, 0, outbytes.Length);//將指令發(fā)送給服務(wù)器</p><p>  若經(jīng)服務(wù)器驗(yàn)證無(wú)誤后,便會(huì)發(fā)回驗(yàn)證成功的指令,客戶(hù)端進(jìn)入系統(tǒng)。</p><p>  3.2 接收服務(wù)器發(fā)回的指令</p><p>  在新的線程內(nèi),啟動(dòng)接收函數(shù),接收服務(wù)器發(fā)回的不同信息,并判斷、處理。以便客戶(hù)端進(jìn)

64、行不同的操作。</p><p>  3.2.1 接收發(fā)回的原始消息并還原</p><p>  因?yàn)榉?wù)器發(fā)回的指令同樣為字符編碼數(shù)組,所以先聲明一個(gè)Byte類(lèi)型的數(shù)組,用以接收服務(wù)器的原始信息:</p><p>  byte[] buff = new byte[10000000];</p><p>  int len;//消息長(zhǎng)度</p

65、><p>  len = stream.Read(buff, 0, buff.Length);</p><p>  然后將收到的原始指令還原為字符串格式:</p><p>  String msg= System.Text.Encoding.Default.GetString(buff, 0, len);</p><p>  3.2.2 分析處理

66、服務(wù)器發(fā)回的指令</p><p>  因?yàn)榉?wù)器發(fā)回的消息與客戶(hù)端發(fā)出的消息類(lèi)似,都是以指令名稱(chēng)作為前綴,并以“|”符號(hào)作為分隔符,所以,聲明一個(gè)字符串型數(shù)組,并把消息內(nèi)以“|”符號(hào)隔開(kāi)的各字符串放入此數(shù)組中:</p><p>  string[] token = msg.Split(new Char[] { '|' });</p><p>  在t

67、oken[0]內(nèi)放置的便為消息指令的標(biāo)示符。這樣,可以通過(guò)對(duì)token[0]內(nèi)字符串的判斷達(dá)到分析指令的目的。</p><p>  3.3 登陸后界面初始化</p><p>  3.3.1 驗(yàn)證成功與進(jìn)入主界面</p><p>  在密碼驗(yàn)證成功后,服務(wù)器將返回登陸成功消息,消息格式為:“EnterOK|”??蛻?hù)端接收此消息,處理后,一個(gè)字符串?dāng)?shù)據(jù)類(lèi)型的數(shù)組,<

68、;/p><p>  客戶(hù)端經(jīng)判斷后,如上消息,進(jìn)行相應(yīng)操作,代碼如下:</p><p>  If (token[0] == "EnterOK")</p><p><b>  {</b></p><p>  groupBox1.Dock = DockStyle.Fill;</p><p&

69、gt;  btnEnter.Enabled = false;</p><p><b>  }</b></p><p>  系統(tǒng)轉(zhuǎn)到用戶(hù)操作界面并將“確定”按鈕凍結(jié),防止多次向服務(wù)器發(fā)送連接指令,引發(fā)“此用戶(hù)已登錄”錯(cuò)誤。操作界面如圖3-2所示:</p><p>  圖3-2 系統(tǒng)主界面</p><p>  3.3.2 初

70、始化用戶(hù)列表</p><p>  進(jìn)入主界面后,首先會(huì)收到服務(wù)器發(fā)送的用戶(hù)列表,其原始消息的本身為一個(gè)DataSet,接收后將其還原:</p><p><b>  //創(chuàng)建內(nèi)存流</b></p><p>  MemoryStream memStream = new MemoryStream(buff);</p><p>

71、  memStream.Seek(0, SeekOrigin.Begin);//指定開(kāi)始位置</p><p>  //產(chǎn)生二進(jìn)制序列化格式</p><p>  IFormatter formatter = new BinaryFormatter();</p><p>  //反串行化到內(nèi)存中</p><p>  object obj = fo

72、rmatter.Deserialize(memStream);</p><p><b>  //類(lèi)型檢驗(yàn)</b></p><p>  if (obj is DataSet)</p><p><b>  {</b></p><p>  DataSet DS = (DataSet)obj;</p&

73、gt;<p><b>  }</b></p><p>  此時(shí),DataSet的新實(shí)例DS中的USERLIST表中。</p><p>  接下來(lái)將用戶(hù)列表展示在主界面上(將DS中USERLIST表內(nèi)數(shù)據(jù)展現(xiàn)在主界面上TreeView控件中)。因?yàn)榇瞬僮鳛榭缇€程操作,所以首先聲明一個(gè)委托,用于把DataSet中的內(nèi)容展現(xiàn)在TreeView控件上,并設(shè)置頭像

74、為不在線狀態(tài),委托于展現(xiàn)函數(shù)如下所示:</p><p>  private delegate void SetUsersListDel(DataSet dsList);//用于在TreeView中展示所有用戶(hù)</p><p>  private void SetUsersList(DataSet dsList)</p><p><b>  {</b&

75、gt;</p><p>  this.Invoke(new SetUsersListDel(SetAllUsersList),</p><p>  new object[]{dsList});</p><p><b>  }</b></p><p>  private void SetAllUsersList(DataS

76、et dsList)</p><p><b>  {</b></p><p>  foreach (TreeNode tn in treeView1.Nodes)</p><p><b>  {</b></p><p>  foreach (DataRow dr in dsList.Tables[&

77、quot;USERLIST"].Rows)</p><p><b>  {</b></p><p>  if (dr["classBM"].ToString() == tn.Tag.ToString())</p><p><b>  {</b></p><p>  Tr

78、eeNode tnChild = new TreeNode();</p><p>  tnChild.Text = dr["NAME"].ToString();</p><p>  tnChild.Tag = dr["ID"].ToString();</p><p>  tnChild.ImageIndex = 4;</

79、p><p>  tn.Nodes.Add(tnChild);</p><p><b>  }</b></p><p><b>  }</b></p><p><b>  }</b></p><p><b>  }</b></p&g

80、t;<p>  接收進(jìn)程中調(diào)用此委托的代碼如下:</p><p>  if (DS.Tables[0].TableName == "USERLIST")</p><p><b>  {</b></p><p>  SetUsersList(DS);//主進(jìn)程委托,用于在窗體TreeView中展現(xiàn)DS</p

81、><p><b>  }</b></p><p>  3.3.3 顯示在線用戶(hù)</p><p>  當(dāng)有新用戶(hù)上線時(shí),服務(wù)器便會(huì)將所有的在線用戶(hù)列表發(fā)送給包括此用戶(hù)在內(nèi)所有的在線用戶(hù),客戶(hù)端接收此列表后,將在線用戶(hù)的頭像設(shè)置為在線狀態(tài),因?yàn)榇瞬僮魍瑯訛榭缇€程操作,所以使用委托,代碼如下:</p><p>  private

82、delegate void SetUsersListDelOnline(string[] token);//展示在線用戶(hù)</p><p>  private void SetUsersOnlineList(string[] token)</p><p><b>  {</b></p><p>  this.Invoke(new SetUsers

83、ListDelOnline(SetAllUserOnlineList), new object[] { token });</p><p><b>  }</b></p><p><b>  //在線用戶(hù)列表</b></p><p>  private void SetAllUserOnlineList(string[]

84、token)</p><p><b>  {</b></p><p>  for (int i = 1; i < token.Length - 1; i++)</p><p><b>  {</b></p><p>  string _onlineUser = token[i].ToStrin

85、g();</p><p>  foreach (TreeNode tn in treeView1.Nodes)</p><p><b>  {</b></p><p>  foreach (TreeNode _tn in tn.Nodes)</p><p><b>  {</b></p>

86、<p>  if (_tn.Text == _onlineUser)</p><p><b>  {</b></p><p>  _tn.ImageIndex = 3;//上線標(biāo)志</p><p><b>  }</b></p><p><b>  }</b>&l

87、t;/p><p><b>  }</b></p><p><b>  }</b></p><p><b>  }</b></p><p>  接收進(jìn)程中調(diào)用委托的代碼:</p><p>  else if (token[0] == "ULIST&q

88、uot;)</p><p><b>  {</b></p><p>  SetUsersOnlineList(token);//更新在線用戶(hù)列表</p><p><b>  }</b></p><p>  此時(shí),在主界面上的用戶(hù)列表內(nèi),便將所有用戶(hù)還在線用戶(hù)都顯示出來(lái),如圖3-3所示:</p&

89、gt;<p><b>  圖3-3 用戶(hù)列表</b></p><p>  灰色頭像為不在線用戶(hù),點(diǎn)亮的頭像為在線用戶(hù)。</p><p><b>  3.4 聊天功能</b></p><p>  此模塊的功能為,向指定用戶(hù)發(fā)送即時(shí)消息,通過(guò)服務(wù)器中轉(zhuǎn)、處理,最后接收用戶(hù)收到消息。并彈出對(duì)話框。</p>

90、;<p>  3.4.1 發(fā)送消息</p><p>  雙擊用戶(hù)節(jié)點(diǎn),彈出聊天窗口(以模式窗體方式彈出),并將對(duì)方用戶(hù)的用戶(hù)名傳入聊天窗口。代碼如下所示:</p><p>  private void treeView1_NodeMouseDoubleClick(object sender, </p><p>  TreeNodeMouseClickE

91、ventArgs e)</p><p><b>  {</b></p><p>  if (e.Node.Parent == null)</p><p><b>  {</b></p><p>  return;//若為根節(jié)點(diǎn)(班級(jí)節(jié)點(diǎn)),不做操作</p><p><b

92、>  }</b></p><p>  string ToUser = e.Node.Text;//對(duì)方用戶(hù)名</p><p>  string Msg = "";//內(nèi)容</p><p>  frmChatMain frm = new frmChatMain();</p><p>  frm.ToUser

93、 = ToUser;</p><p>  DialogResult dr=frm.ShowDialog(); </p><p><b>  }</b></p><p>  聊天窗口標(biāo)題為“與XXX聊天中”,XXX為好友用戶(hù)名,如圖3-4所示:</p><p>  圖3-4 發(fā)送消息框</p><p&g

94、t;  在聊天窗口(下側(cè)文本框)內(nèi)填寫(xiě)發(fā)送內(nèi)容,點(diǎn)擊發(fā)送按鈕,聊天窗口(模式窗體)自動(dòng)關(guān)閉,并將所需參數(shù)返回,最后將消息以“CHAT|本機(jī)用戶(hù)名|對(duì)方用戶(hù)名|消息內(nèi)容”的格式發(fā)送給服務(wù)器,代碼如下:</p><p>  if (dr == DialogResult.OK)</p><p><b>  {</b></p><p>  Msg =

95、frm.Msg;</p><p>  string cmd = "CHAT|"+ userName + "|" + ToUser + "|" + Msg + "|";//格式為:CHAT|本用戶(hù)名|對(duì)方用戶(hù)名|內(nèi)容</p><p>  Byte[] outbytes = </p><p>

96、;  System.Text.Encoding.Default.GetBytes(cmd.ToCharArray());</p><p>  //將指令發(fā)送給服務(wù)器</p><p>  stream.Write(outbytes, 0, outbytes.Length);</p><p><b>  }</b></p><p

97、>  服務(wù)器接收此消息后,將內(nèi)容發(fā)送給接收方,便達(dá)到了即時(shí)通信的目的。</p><p>  3.4.2 接收消息</p><p>  當(dāng)其他用戶(hù)向本用戶(hù)發(fā)送即時(shí)消息時(shí),在本機(jī)用以接收服務(wù)器返回消息的副線程內(nèi),會(huì)收到一個(gè)編碼數(shù)組,通過(guò)客戶(hù)端處理后,指令標(biāo)示符放在了token數(shù)組的第一個(gè)單元內(nèi)。若此指令為“CHAT”,則彈出新窗口,顯示內(nèi)容。代碼如下:</p><p&

98、gt;  else if (token[0] == "CHAT")</p><p><b>  {</b></p><p>  string FromUser = token[1].ToString();</p><p>  string Msg = token[2].ToString();</p><p

99、>  frmChatMain frm = new frmChatMain();</p><p>  frm.ToUser = FromUser;</p><p>  frm.Msg = Msg;</p><p>  DialogResult dr = frm.ShowDialog();</p><p><b>  }</

100、b></p><p>  消息內(nèi)容顯示在消息框內(nèi),如圖3-5所示:</p><p>  圖3-5 接收消息框</p><p>  同樣可在下側(cè)回復(fù)框內(nèi)填寫(xiě)回復(fù)消息,點(diǎn)擊“發(fā)送”按鈕,向?qū)Ψ桨l(fā)送回復(fù)消息,代碼如下所示:</p><p>  if (dr == DialogResult.OK)</p><p><

101、;b>  {</b></p><p>  Msg = frm.Msg;</p><p>  string cmd = "CHAT|" + userName + "|" + FromUser + "|" + </p><p>  Msg + "|";//格式為:CHAT|

102、本用戶(hù)名|對(duì)方用戶(hù)名|內(nèi)容</p><p>  Byte[] outbytes = </p><p>  System.Text.Encoding.Default.GetBytes(cmd.ToCharArray());</p><p>  //將指令發(fā)送給服務(wù)器</p><p>  stream.Write(outbytes, 0, out

103、bytes.Length);</p><p><b>  }</b></p><p>  若點(diǎn)擊關(guān)閉按鈕,客戶(hù)端不做任何操作。至此,聊天功能全部介紹完畢。</p><p>  3.5 查詢(xún)聊天記錄功能</p><p>  當(dāng)用戶(hù)不在線時(shí),便不能及時(shí)收到消息,只能在再次上線后通過(guò)查詢(xún)聊天記錄功能查詢(xún)離線消息。在服務(wù)器所在計(jì)

104、算機(jī)的數(shù)據(jù)庫(kù)中,存儲(chǔ)著所有用戶(hù)的所有在線離線消息,為日后的查詢(xún)提供了可能。</p><p>  鼠標(biāo)在用戶(hù)列表中單擊需要查詢(xún)歷史記錄的用戶(hù)名稱(chēng),然后單擊“聊天記錄”按鈕,客戶(hù)端創(chuàng)建字符串,以“QUERYLOGS”為前綴,并將此用戶(hù)用戶(hù)名,對(duì)方用戶(hù)名加入字符串,發(fā)送給服務(wù)器。字符格式為“QUERYLOGS|此機(jī)用戶(hù)名|對(duì)方用戶(hù)名|”。編寫(xiě)代碼如下所示:</p><p>  private v

105、oid btnQuery_Click(object sender, EventArgs e)</p><p><b>  {</b></p><p>  if (userLogs == "")</p><p><b>  {</b></p><p>  MessageBox.Sh

106、ow("請(qǐng)先選擇好友,再進(jìn)行查詢(xún)", "提示");</p><p><b>  return;</b></p><p><b>  }</b></p><p>  //格式為:QUERY|本用戶(hù)名|對(duì)方用戶(hù)名</p><p>  string cmd = &q

107、uot;QUERYLOGS|" + userName + "|" + userLogs + "|";</p><p>  Byte[] outbytes = </p><p>  System.Text.Encoding.Default.GetBytes(cmd.ToCharArray());</p><p>  /

108、/將指令發(fā)送給服務(wù)器</p><p>  stream.Write(outbytes, 0, outbytes.Length);</p><p><b>  }</b></p><p>  將上述字符串發(fā)送給服務(wù)器后,經(jīng)過(guò)服務(wù)器處理,將會(huì)發(fā)回DataSet數(shù)據(jù),客戶(hù)端收到此消息指令后,將DataSet中名稱(chēng)為“QUERYLOGS”的DataTa

109、ble的數(shù)據(jù)展示在彈出窗體的dataGridView中。</p><p>  在接收服務(wù)器指令的系統(tǒng)副進(jìn)程中,客戶(hù)端分析服務(wù)器發(fā)回的消息指令,處理后彈出新窗體的代碼如下所示:</p><p>  if (DS.Tables[0].TableName == "QUERYLOGS")</p><p><b>  {</b><

110、;/p><p>  frmQueryLogs frm = new frmQueryLogs();</p><p>  frm.FROMUSER = userName;</p><p>  frm.TOUSER = userLogs;</p><p>  frm.DATASET = DS;</p><p>  frm.Sho

111、wDialog();</p><p><b>  } </b></p><p>  編寫(xiě)上述代碼中所彈出的新窗體,窗體中加入dataGridView控件,窗體標(biāo)題為“與XXX的聊天記錄”,“XXX”為對(duì)方用戶(hù)名。dataGridView控件內(nèi)顯示有發(fā)送方、接收方、發(fā)送時(shí)間、內(nèi)容四個(gè)字段。其中發(fā)送時(shí)間精確到毫秒。聊天記錄窗體顯示如圖3-6所示:</p>&

112、lt;p>  圖3-6 聊天記錄窗體</p><p>  上圖窗體內(nèi)在Form_Load事件內(nèi)編寫(xiě)代碼設(shè)置窗體標(biāo)題,dataGridView控件的數(shù)據(jù)源、各列顯示名稱(chēng)。代碼如下:</p><p>  private void frmQueryLogs_Load(object sender, EventArgs e)</p><p><b>  {&l

113、t;/b></p><p>  this.Text = "與好友:" + _toUser + "的聊天記錄";</p><p>  dataGridView1.DataSource = _ds.Tables[0];</p><p>  dataGridView1.Columns[0].HeaderText = "

114、;發(fā)送方:";</p><p>  dataGridView1.Columns[1].HeaderText = "接受方:";</p><p>  dataGridView1.Columns[2].HeaderText = "發(fā)送時(shí)間:";</p><p>  dataGridView1.Columns[3].Hea

115、derText = "內(nèi)容:";</p><p>  dataGridView1.Columns[3].Width = 300;</p><p><b>  }</b></p><p><b>  3.6 用戶(hù)離線</b></p><p>  當(dāng)用戶(hù)離線時(shí),服務(wù)器及時(shí)作出反應(yīng),將

116、此用戶(hù)狀態(tài)置為離線。并將離線消息發(fā)送給其他在線用戶(hù),以便在線用戶(hù)更新在線用戶(hù)列表。</p><p>  3.6.1 發(fā)送離線請(qǐng)求</p><p>  當(dāng)用戶(hù)離線時(shí),點(diǎn)擊主操作界面的“退出”按鈕,客戶(hù)端創(chuàng)建離線請(qǐng)求字符串,并以“EXIT”作為前綴,并加入此用戶(hù)用戶(hù)名。字符串格式為“EXIT|用戶(hù)名|”,并將此請(qǐng)求發(fā)送給服務(wù)器,然后關(guān)閉主操作界面窗體,實(shí)現(xiàn)代碼如下:</p>&l

117、t;p>  private void btnExit_Click(object sender, EventArgs e)</p><p><b>  {</b></p><p>  string cmd = "EXIT|" + userName + "|";</p><p>  Byte[] out

118、bytes = System.Text.Encoding.Default.GetBytes(cmd.ToCharArray());</p><p>  stream.Write(outbytes, 0, outbytes.Length);//將指令發(fā)送給服務(wù)器</p><p>  this.Close();</p><p><b>  }</b>

119、;</p><p>  3.6.2 接收用戶(hù)離線消息</p><p>  當(dāng)其他用戶(hù)離線時(shí),服務(wù)器創(chuàng)建字符串,以“EXIT”作為前綴。在客戶(hù)端接收進(jìn)程內(nèi),將收到的指令處理后放入token字符串?dāng)?shù)組,數(shù)組的token[1]內(nèi)存放離線用戶(hù)用戶(hù)名,通過(guò)委托與編寫(xiě)的SetUserOfflineList函數(shù),將離線用戶(hù)更新為離線狀態(tài),委托與SetUserOfflineList函數(shù)如下所示:</

120、p><p>  private delegate void SetUsersListDelOffline(string[] token);//離線用戶(hù)</p><p>  private void SetUserOffline(string[] token)</p><p><b>  {</b></p><p>  thi

溫馨提示

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

最新文檔

評(píng)論

0/150

提交評(píng)論