操作系統(tǒng)課程設(shè)計--- 多線程管理與線程通信_第1頁
已閱讀1頁,還剩28頁未讀, 繼續(xù)免費閱讀

下載本文檔

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

文檔簡介

1、<p>  操作系統(tǒng)課程設(shè)計論文</p><p>  題 目 多線程管理與線程通信 </p><p>  學 院 </p><p>  專 業(yè) 計算機科學與技術(shù) </p><p>  學生姓名

2、 </p><p>  導師姓名 </p><p><b>  內(nèi)容摘要</b></p><p>  隨著科學技術(shù)的發(fā)展,通信變得越來越重要,如何實現(xiàn)不同主機之間的通信,成為越來越多人關(guān)心的問題。本次課程通過實現(xiàn)兩個端口,一個服務端

3、口,通過多線程為客戶端提供了一個交流的平臺。客戶通過客戶端建立用戶,進行信息交流。</p><p><b>  1、理解線程</b></p><p>  要講解線程,不得不說一下進程,進程是應用程序的執(zhí)行實例,每個進程是由私有的虛擬地址空間、代碼、數(shù)據(jù)和其它系統(tǒng)資源組成。進程在運行時創(chuàng)建的資源隨著進程的終止而死亡。線程的基本思想很簡單,它是一個獨立的執(zhí)行流,是進程內(nèi)部

4、的一個獨立的執(zhí)行單元,相當于一個子程序,它對應于Visual C++中的CwinThread類對象。單獨一個執(zhí)行程序運行時,缺省地包含的一個主線程,主線程以函數(shù)地址的形式出現(xiàn),提供程序的啟動點,如main()或WinMain()函數(shù)等。當主線程終止時,進程也隨之終止。根據(jù)實際需要,應用程序可以分解成許多獨立執(zhí)行的線程,每個線程并行的運行在同一進程中。</p><p>  一個進程中的所有線程都在該進程的虛擬地址空

5、間中,使用該進程的全局變量和系統(tǒng)資源。操作系統(tǒng)給每個線程分配不同的CPU時間片,在某一個時刻,CPU只執(zhí)行一個時間片內(nèi)的線程,多個時間片中的相應線程在CPU內(nèi)輪流執(zhí)行,由于每個時間片時間很短,所以對用戶來說,仿佛各個線程在計算機中是并行處理的。操作系統(tǒng)是根據(jù)線程的優(yōu)先級來安排CPU的時間,優(yōu)先級高的線程優(yōu)先運行,優(yōu)先級低的線程則繼續(xù)等待。</p><p>  線程被分為兩種:用戶界面線程和工作線程(又稱為后臺線程

6、)。用戶界面線程通常用來處理用戶的輸入并響應各種事件和消息,其實,應用程序的主執(zhí)行線程CWinAPP對象就是一個用戶界面線程,當應用程序啟動時自動創(chuàng)建和啟動,同樣它的終止也意味著該程序的結(jié)束,進程終止。工作線程用來執(zhí)行程序的后臺處理任務,比如計算、調(diào)度、對串口的讀寫操作等,它和用戶界面線程的區(qū)別是它不用從CWinThread類派生來創(chuàng)建,對它來說最重要的是如何實現(xiàn)工作線程任務的運行控制函數(shù)。工作線程和用戶界面線程啟動時要調(diào)用同一個函數(shù)的

7、不同版本;最后需要讀者明白的是,一個進程中的所有線程共享它們父進程的變量,但同時每個線程可以擁有自己的變量。 </p><p>  2、線程的管理和操作</p><p><b> ?。ㄒ唬┚€程的啟動</b></p><p>  創(chuàng)建一個用戶界面線程,首先要從類CwinThread產(chǎn)生一個派生類,同時必須使用DECLARE_DYNCREATE和I

8、MPLEMENT_DYNCREATE來聲明和實現(xiàn)這個CwinThread派生類。第二步是根據(jù)需要重載該派生類的一些成員函數(shù)如:ExitInstance()、InitInstance()、OnIdle()、PreTranslateMessage()等函數(shù)。最后調(diào)用AfxBeginThread()函數(shù)的一個版本:CWinThread* AfxBeginThread( CRuntimeClass* pThreadClass, int nPri

9、ority = THREAD_PRIORITY_NORMAL, UINT nStackSize = 0, DWORD dwCreateFlags = 0, LPSECURITY_ATTRIBUTES lpSecurityAttrs = NULL ) 啟動該用戶界面線程,其中第一個參數(shù)為指向定義的用戶界面線程類指針變量,第二個參數(shù)為線程的優(yōu)先級,第三個參數(shù)為線程所對應的堆棧大小,第四個參數(shù)為線程創(chuàng)建時的附加標志,缺省為正常狀態(tài),如為CRE

10、A</p><p>  對于工作線程來說,啟動一個線程,首先需要編寫一個希望與應用程序的其余部分并行運行的函數(shù)如Fun1(),接著定義一個指向CwinThread對象的指針變量*pThread,調(diào)用AfxBeginThread(Fun1,param,priority)函數(shù),返回值賦給pThread變量的同時一并啟動該線程來執(zhí)行上面的Fun1()函數(shù),其中Fun1是線程要運行的函數(shù)的名字,也既是上面所說的控制函數(shù)的

11、名字,param是準備傳送給線程函數(shù)Fun1的任意32位值,priority則是定義該線程的優(yōu)先級別,它是預定義的常數(shù),讀者可參考MSDN。</p><p><b>  (二)線程的優(yōu)先級</b></p><p>  以下的CwinThread類的成員函數(shù)用于線程優(yōu)先級的操作:</p><p>  int GetThreadPriority()

12、;</p><p>  BOOL SetThradPriority()(int nPriority);</p><p>  上述的二個函數(shù)分別用來獲取和設(shè)置線程的優(yōu)先級,這里的優(yōu)先級,是相對于該線程所處的優(yōu)先權(quán)層次而言的,處于同一優(yōu)先權(quán)層次的線程,優(yōu)先級高的線程先運行;處于不同優(yōu)先權(quán)層次上的線程,誰的優(yōu)先權(quán)層次高,誰先運行。至于優(yōu)先級設(shè)置所需的常數(shù),自己參考MSDN就可以了,要注意的是要想

13、設(shè)置線程的優(yōu)先級,這個線程在創(chuàng)建時必須具有THREAD_SET_INFORMATION訪問權(quán)限。對于線程的優(yōu)先權(quán)層次的設(shè)置,CwinThread類沒有提供相應的函數(shù),但是可以通過Win32 SDK函數(shù)GetPriorityClass()和SetPriorityClass()來實現(xiàn)。</p><p> ?。ㄈ┚€程的懸掛和恢復</p><p>  CWinThread類中包含了應用程序懸掛和

14、恢復它所創(chuàng)建的線程的函數(shù),其中SuspendThread()用來懸掛線程,暫停線程的執(zhí)行;ResumeThread()用來恢復線程的執(zhí)行。如果你對一個線程連續(xù)若干次執(zhí)行SuspendThread(),則需要連續(xù)執(zhí)行相應次的ResumeThread()來恢復線程的運行。</p><p><b> ?。ㄋ模┙Y(jié)束線程</b></p><p>  終止線程有三種途徑,線程可以

15、在自身內(nèi)部調(diào)用AfxEndThread()來終止自身的運行;可以在線程的外部調(diào)用BOOL TerminateThread( HANDLE hThread, DWORD dwExitCode )來強行終止一個線程的運行,然后調(diào)用CloseHandle()函數(shù)釋放線程所占用的堆棧;第三種方法是改變?nèi)肿兞?,使線程的執(zhí)行函數(shù)返回,則該線程終止</p><p>  關(guān)鍵詞:多線程 通信 服務端口 客戶端</p>

16、;<p><b>  目 錄</b></p><p><b>  1.課程設(shè)計1</b></p><p>  1.1功能主要設(shè)計內(nèi)容1</p><p>  1.2 主要設(shè)計原理1</p><p>  2.課程設(shè)計需求分析2</p><p><

17、b>  3.概要設(shè)計2</b></p><p>  3.1 整體設(shè)計框架2</p><p>  3.2 各模塊的基本算法2</p><p>  3.2.1 多線程原理2</p><p><b>  4.系統(tǒng)實現(xiàn)3</b></p><p><b>  4.1

18、原理3</b></p><p>  4.2 運行環(huán)境Eclipse簡介3</p><p>  4.3 流程圖描述5</p><p>  4.3 代碼描述10</p><p>  4.3.1 服務端代碼10</p><p>  4.3.2 客戶端代碼14</p><p>&

19、lt;b>  5.系統(tǒng)測試17</b></p><p>  5.1系統(tǒng)功能測試17</p><p><b>  6.總結(jié)22</b></p><p>  參 考 文 獻24</p><p><b>  1.課程設(shè)計</b></p><p>  1.1

20、功能主要設(shè)計內(nèi)容</p><p>  本設(shè)計主要采用java語言編寫,設(shè)計一個模擬的多線程通信,可以實現(xiàn)客戶端通過服務端,實現(xiàn)客戶端與客戶端之間進行通信。主要分為兩部分,一部分為Seriver Socket端和Client Socket端。</p><p>  1.2 主要設(shè)計原理</p><p>  線程是進程中能夠執(zhí)行的實體,是進程的組成部分,也是處理器調(diào)度和分

21、派的基本單位。允許進程包含多個可并發(fā)的線程,這些線程共享進程所獲得的主存空間和資源,可以完成某一項任務而協(xié)同工作。</p><p>  在java語言中,多線程的機制是通過虛擬CPU來實現(xiàn)的??梢孕蜗蟮睦斫鉃?,在一個java程序內(nèi)部虛擬了多臺計算機,每臺計算機對應一個線程,有自己的CPU,可以獲取所需要的代碼和數(shù)據(jù),因此能獨立執(zhí)行任務,相互間還可以共用代碼和數(shù)據(jù)。Java的線程是通過java.lang.Threa

22、d類來實現(xiàn)的,它內(nèi)部實現(xiàn)了虛擬CPU的功能,能夠接收和處理傳遞給它的代碼數(shù)據(jù),并提供了獨立的運行控制功能。每個線程都是某個特定Thread對象所對應的run()方法來完成其操作的,方法run()稱為線程體。</p><p>  在計算機網(wǎng)絡(luò)技術(shù)中,兩個進程間可以通過一個雙向的網(wǎng)絡(luò)通信連接實現(xiàn)數(shù)據(jù)交換,這種通信鏈路的端點被稱為“套接字”,套接字在具體實現(xiàn)中又分為服務套接字和客戶端套字??蛻舳擞袃煞N,通常用來實現(xiàn)“客

23、戶—服務器”連接和數(shù)據(jù)傳輸。</p><p>  當進程間通過網(wǎng)絡(luò)進行通信時,java技術(shù)仍使用它的流模型。每個Socket對象都封裝了相應的一個輸入流和一個輸出流對象。如果一個進程要通過網(wǎng)絡(luò)向另一個進程發(fā)送數(shù)據(jù),只需簡單地將數(shù)據(jù)寫到與其Socket相關(guān)聯(lián)的輸出流中去,相對應的,一個進程可以從相關(guān)聯(lián)的輸入流來讀取另一個進程所寫出的數(shù)據(jù)。建立網(wǎng)絡(luò)連接之后,使用與Socket相關(guān)聯(lián)的I/O流一旦打開,其使用方式和先前

24、其它I/O流的使用方式完全相同。</p><p>  兩臺計算機之間如果要建立網(wǎng)絡(luò)連接,一臺機器中必須運行一個進程來等待連接,而另一臺機器必須試圖連接到前一臺機器。這和電話系統(tǒng)類似,必須由一方發(fā)起呼叫,而此時另一方必須處于等待呼叫狀態(tài)。所不同的時,Socket通信的兩端不是對等的—等待連接請求的一端稱為服務器,而主動發(fā)起連接的一端稱為客戶機。建立連接時所需的尋址信息包括:遠程計算機的機器名或IP地址;試圖連接的對

25、方端口號。</p><p>  2.課程設(shè)計需求分析</p><p>  隨著網(wǎng)絡(luò)的快速發(fā)展,人與人之間的交越來越多,如何讓雙方或者是更多人同時進行通信已經(jīng)變得越來越重要。在當今信息世界里,聊天工具的使用是非常頻繁的,如MSN、QQ、校內(nèi)通,之類的聊天工具許多人都正在使用。</p><p>  此次課程設(shè)計通過多線程通信,主要采用了建立客戶端與用戶端之間進行通信,雖

26、然其功能簡單,但基本實現(xiàn)了多個用戶同時進行通信。</p><p><b>  3.概要設(shè)計</b></p><p>  3.1 整體設(shè)計框架</p><p>  本程序主要分為兩部分,一部分為TestServer端(服務端),主要用于監(jiān)聽通信端口,接收客戶端連接請求,每當有新用戶上線時會進行如下處理:</p><p> 

27、 1.打開與該用戶相關(guān)聯(lián)的I/O流</p><p><b>  2.接收新用戶名</b></p><p>  3.將新用戶信息(包括用戶名和對應的輸出流對象)加入到在線用戶列表中去</p><p>  4.啟動一個新的線程,該線程負責監(jiān)聽并轉(zhuǎn)發(fā)此新用戶的發(fā)言信息</p><p>  另一部分為TestClient端(客戶

28、端),主要是用于創(chuàng)建Socket對象,連接服務器的9999端口,建立連接后,通過創(chuàng)建新進程進行多個用戶之間的通信。其主要是包括以下幾個主要方面:</p><p><b>  1.創(chuàng)建界面</b></p><p><b>  2.輸入用戶的名字</b></p><p><b>  3.建立連接</b>&

29、lt;/p><p>  4.創(chuàng)建進程,實現(xiàn)進程之間的通信</p><p>  3.2 各模塊的基本算法</p><p>  3.2.1 多線程原理</p><p>  每個正在系統(tǒng)上運行的程序都是一個進程。每個進程包含一到多個線程。進程也可能是整個程序或者是部分程序的動態(tài)執(zhí)行。線程是一組指令的集合,或者是程序的特殊段,它可以在程序里獨立執(zhí)行。

30、也可以把它理解為代碼運行的上下文。所以線程基本上是輕量級的進程,它負責在單個程序里執(zhí)行多任務。通常由操作系統(tǒng)負責多個線程的調(diào)度和執(zhí)行。線程是程序中一個單一的順序控制流程.在單個程序中同時運行多個線程完成不同的工作,稱為多線程. 線程和進程的區(qū)別在于,子進程和父進程有不同的代碼和數(shù)據(jù)空間,而多個線程則共享數(shù)據(jù)空間,每個線程有自己的執(zhí)行堆棧和程序計數(shù)器為其執(zhí)行上下文.多線程主要是為了節(jié)約CPU時間,發(fā)揮利用,根據(jù)具體情況而定. 線程的運行中

31、需要使用計算機的內(nèi)存資源和CPU。</p><p>  一個采用了多線程技術(shù)的應用程序可以更好地利用系統(tǒng)資源。其主要優(yōu)勢在于充分利用了CPU的空閑時間片,可以用盡可能少的時間來對用戶的要求做出響應,使得進程的整體運行效率得到較大提高,同時增強了應用程序的靈活性。更為重要的是,由于同一進程的所有線程是共享同一內(nèi)存,所以不需要特殊的數(shù)據(jù)傳送機制,不需要建立共享存儲區(qū)或共享文件,從而使得不同任務之間的協(xié)調(diào)操作與運行、數(shù)

32、據(jù)的交互、資源的分配等問題更加易于解決。</p><p><b>  4.系統(tǒng)實現(xiàn)</b></p><p><b>  4.1 原理</b></p><p>  通過Socket建立連接,以ChatServer作為服務器,作為一個中間平臺進行進行交流,然后通過ChatClient作為客戶端,建立多個用戶,分別輸入用戶名登陸

33、,輸入交流的信息。當用戶要通信時,只需在其它寫入要的內(nèi)容,通過DataOutputStream(s.getOutputStream())將其寫進去。通過線程自動的將其寫入到服務端的內(nèi)容顯示到各個用戶去。里面主要是用到了Hashtable<String,DataOutputStream>,它的作用是實現(xiàn)一個哈希表,該哈希表將鍵映射到相應的值,顯示相應的信息來自哪個用戶,方法put()將指定 key 映射到此哈希表中的指定 va

34、lue,通過名字對應相應的消息。Remove(Object key)從哈希表中移除該鍵及其相應的值。如果該鍵不在哈希表中,則此方法不執(zhí)行任何操作。</p><p>  4.2 運行環(huán)境Eclipse簡介</p><p>  Eclipse是著名的跨平臺的自由集成開發(fā)環(huán)境(IDE)。最初主要用來Java語言開發(fā),但是目前亦有人通過插件使其作為其他計算機語言比如C++和Python的開發(fā)工具。

35、Eclipse的本身只是一個框架平臺,但是眾多插件的支持使得Eclipse擁有其他功能相對固定的IDE軟件很難具有的靈活性。許多軟件開發(fā)商以Eclipse為框架開發(fā)自己的IDE。</p><p>  Eclipse是一個開放源代碼的軟件開發(fā)項目,專注于為高度集成的工具開發(fā)提供一個全功能的、具有商業(yè)品質(zhì)的工業(yè)平臺。它主要由Eclipse項目、Eclipse工具項目和Eclipse技術(shù)項目三個項目組成,具體包括四個部

36、分組成——Eclipse Platform、JDT、CDT和PDE.JDT支持Java開發(fā)、CDT支持C開發(fā)、PDE用來支持插件開發(fā),Eclipse Platform則是一個開放的可擴展IDE,提供了一個通用的開發(fā)平臺。它提供建造塊和構(gòu)造并運行集成軟件開發(fā)工具的基礎(chǔ)。Eclipse Platform允許工具建造者獨立開發(fā)與他人工具無縫集成的工具從而無須分辨一個工具功能在哪里結(jié)束,而另一個工具功能在哪里開始。</p><

37、;p>  Eclipse SDK(軟件開發(fā)者包)是Eclipse Platform、JDT和PDE所生產(chǎn)的組件合并,它們可以一次下載。這些部分在一起提供了一個具有豐富特性的開發(fā)環(huán)境,允許開發(fā)者有效地建造可以無縫集成到Eclipse Platform中的工具。Eclipse SDK由Eclipse項目生產(chǎn)的工具和來自其它開放源代碼的第三方軟件組合而成。Eclipse項目生產(chǎn)的軟件以 CPL發(fā)布,第三方組件有各自自身的許可協(xié)議.<

38、;/p><p><b>  4.3 流程圖描述</b></p><p>  圖1 ChatServer服務器流程圖</p><p>  圖2 ChatServer服務器流程圖</p><p><b>  圖3 窗口器流程圖</b></p><p>  圖4 線程運行流程表<

39、/p><p>  圖5 Socke通信模型</p><p><b>  4.3 代碼描述</b></p><p>  4.3.1 服務端代碼</p><p>  import java.io.*;</p><p>  import java.net.*;</p><p>  

40、import java.awt.*;</p><p>  import java.awt.event.*;</p><p>  public class ChatClient {</p><p>  private String name;</p><p>  private Socket s;</p><p>  p

41、rivate DataInputStream dis;</p><p>  private DataOutputStream dos;</p><p>  private Frame f;</p><p>  private TextArea ta;</p><p>  private TextField tf;</p><

42、;p>  private boolean runnable = true;</p><p>  public static void main(String args[]) {</p><p>  ChatClient cc = new ChatClient();</p><p>  cc.createUI();</p><p>

43、  cc.inputName();</p><p>  cc.connect();</p><p>  cc.createThread();</p><p><b>  }</b></p><p>  public void createUI(){</p><p>  f = new Fra

44、me("Client");</p><p>  ta = new TextArea();</p><p>  tf = new TextField();</p><p>  Button send = new Button("Send");</p><p>  Panel p = new Panel()

45、;</p><p>  p.setLayout(new BorderLayout());</p><p>  p.add(tf,"Center");</p><p>  p.add(send,"East");</p><p>  f.add(ta,"Center");</p&g

46、t;<p>  f.add(p,"South");</p><p>  MyClientListener listener = new MyClientListener(this);</p><p>  send.addActionListener(listener);</p><p>  tf.addActionListener(

47、listener);</p><p>  f.addWindowListener(new WindowAdapter(){</p><p>  public void windowClosing(WindowEvent e){</p><p>  ChatClient.this.shutDown();</p><p><b>  

48、}</b></p><p><b>  });</b></p><p>  f.setSize(400,400);</p><p>  f.setLocation(600,0);</p><p>  f.setVisible(true);</p><p><b>  }&

49、lt;/b></p><p>  public void inputName(){</p><p>  String name = javax.swing.JOptionPane.showInputDialog("Input Your Name:");</p><p>  this.setName(name);</p>&l

50、t;p>  f.setTitle(name);</p><p><b>  }</b></p><p>  public void connect(){</p><p><b>  try {</b></p><p>  s = new Socket("127.0.0.1&quo

51、t;,9999);</p><p>  dos = new DataOutputStream(s.getOutputStream());</p><p>  dis = new DataInputStream(s.getInputStream());</p><p>  dos.writeUTF(name);</p><p>  }catch

52、 (IOException e) {</p><p>  e.printStackTrace();</p><p><b>  }</b></p><p><b>  }</b></p><p>  public void createThread(){</p><p>

53、;  MyClientReader reader = new MyClientReader(this);</p><p>  reader.start(); </p><p><b>  }</b></p><p>  public void stop(){</p><p>  runnable = false;<

54、;/p><p><b>  }</b></p><p>  public void shutDown(){</p><p><b>  try{</b></p><p>  dos.writeUTF("再見");</p><p>  ta.append(&qu

55、ot;Exit in 5 seconds!");</p><p>  this.stop();</p><p>  Thread.sleep(1000);</p><p>  dis.close();</p><p>  dos.close();</p><p>  s.close();</p&g

56、t;<p>  }catch(Exception e){</p><p><b>  }</b></p><p>  System.exit(0);</p><p><b>  }</b></p><p>  public boolean getRunnable(){<

57、;/p><p>  return runnable;</p><p><b>  }</b></p><p>  public void setName(String name){</p><p>  this.name = name;</p><p><b>  }</b>

58、;</p><p>  public DataInputStream getDataInputStream(){</p><p>  return dis;</p><p><b>  }</b></p><p>  public DataOutputStream getDataOutputStream(){</

59、p><p>  return dos;</p><p><b>  }</b></p><p>  public TextArea getTextArea(){</p><p>  return ta;</p><p><b>  }</b></p><p

60、>  public TextField getTextField(){</p><p>  return tf;</p><p><b>  }</b></p><p><b>  }</b></p><p>  class MyClientListener implements Actio

61、nListener{</p><p>  private ChatClient client;</p><p>  public MyClientListener(ChatClient client){</p><p>  this.client = client;</p><p><b>  }</b></p&

62、gt;<p>  public void actionPerformed(ActionEvent e){</p><p>  TextField tf = client.getTextField();</p><p>  String info = tf.getText();</p><p><b>  try{</b></

63、p><p>  client.getDataOutputStream().writeUTF(info);</p><p>  }catch (IOException e1) {</p><p>  e1.printStackTrace();</p><p><b>  }</b></p><p>

64、;  if(info.equals("bye")){</p><p>  client.shutDown();</p><p><b>  }</b></p><p>  tf.setText("");</p><p><b>  }</b></p&

65、gt;<p><b>  }</b></p><p>  class MyClientReader extends Thread{</p><p>  private ChatClient client;</p><p>  public MyClientReader(ChatClient client){</p>

66、<p>  this.client = client;</p><p><b>  }</b></p><p>  public void run(){</p><p>  String info;</p><p>  DataInputStream dis = client.getDataInputStre

67、am();</p><p>  TextArea ta = client.getTextArea();</p><p><b>  try{</b></p><p>  while(client.getRunnable()){</p><p>  info = dis.readUTF();</p><

68、p>  ta.append(info + "\n");</p><p><b>  }</b></p><p>  }catch (IOException e) {</p><p><b>  }</b></p><p><b>  } </b>

69、;</p><p><b>  }</b></p><p>  4.3.2 客戶端代碼</p><p>  import java.io.*;</p><p>  import java.net.*;</p><p>  import java.util.*;</p><p&g

70、t;  public class ChatServer {</p><p>  public static void main(String args[]) {</p><p>  Hashtable<String,DataOutputStream> userList = new Hashtable<String,DataOutputStream>(); </

71、p><p>  String name;</p><p>  DataInputStream dis;</p><p>  DataOutputStream dos;</p><p><b>  try{</b></p><p>  ServerSocket ss = new ServerSocket

72、(9999);</p><p>  while(true){</p><p>  Socket s = ss.accept();</p><p>  dis = new DataInputStream(s.getInputStream());</p><p>  dos = new DataOutputStream(s.getOutputS

73、tream());</p><p>  name = dis.readUTF();</p><p>  userList.put(name,dos);</p><p>  new MyServerReader(name,dis,userList).start();</p><p><b>  }</b></p>

74、;<p>  }catch(Exception e){</p><p>  e.printStackTrace();</p><p><b>  }</b></p><p><b>  }</b></p><p><b>  }</b></p>&

75、lt;p>  class MyServerReader extends Thread{</p><p>  private String name;</p><p>  private DataInputStream dis;</p><p>  private Hashtable<String,DataOutputStream> userList

76、;</p><p>  public MyServerReader(String name,DataInputStream dis,Hashtable<String,DataOutputStream> userList ){</p><p>  this.name = name;</p><p>  this.dis = dis;</p>

77、<p>  this.userList = userList;</p><p><b>  }</b></p><p>  public void run(){</p><p>  String info;</p><p><b>  try{</b></p><p&

78、gt;  transmitMessage(name + " in!","--Server Info--");</p><p>  while(true){</p><p>  info = dis.readUTF();</p><p>  if(info.equals("bye")){</p>

79、<p>  DataOutputStream dos = (DataOutputStream)(userList.get(name));</p><p>  Thread.sleep(1000);</p><p>  dos.close();</p><p>  dis.close();</p><p>  userList.r

80、emove(name);</p><p>  transmitMessage(name + " out!","--Server Info--");</p><p><b>  break;</b></p><p>  }else if(info.length()>0){</p>&l

81、t;p>  transmitMessage(info,name);</p><p><b>  }</b></p><p><b>  }</b></p><p>  }catch (Exception e) {</p><p><b>  }</b></p&

82、gt;<p><b>  } </b></p><p>  public void transmitMessage(String msg,String name){</p><p>  Collection doses = userList.values();</p><p>  DataOutputStream dos;<

83、/p><p>  for(Object o: doses){</p><p>  dos = (DataOutputStream)o;</p><p><b>  try{</b></p><p>  dos.writeUTF(name + ":" + msg);</p><p>

84、  }catch(Exception e){</p><p><b>  }</b></p><p><b>  }</b></p><p><b>  }</b></p><p><b>  }</b></p><p>

85、<b>  5.系統(tǒng)測試</b></p><p><b>  5.1系統(tǒng)功能測試</b></p><p>  圖6 啟動服務器ChatServer</p><p>  圖7 啟動客戶服務器ChatClient</p><p><b>  圖8 用戶登陸界面</b></p&

86、gt;<p>  注:服務器要始終打開,不斷監(jiān)聽著客戶端是否有用戶進入或交流,一旦服務器停止,則會出現(xiàn)錯誤。</p><p>  圖9 錯誤關(guān)閉服務器</p><p>  圖10 再次啟動客戶服務器</p><p>  圖11 兩個用戶進行信息交流</p><p>  圖12 再次啟動客戶服務器</p><p

87、>  圖13 三個用戶進行信息交流</p><p>  圖14 啟動多個用戶,實現(xiàn)多個用戶信息交流</p><p><b>  圖15 關(guān)閉用戶</b></p><p>  關(guān)閉用戶之后,會提示,哪個用戶已經(jīng)退出,通過1秒的時間,它自動地退出。</p><p>  圖16 關(guān)閉用戶之后,其它用戶繼續(xù)信息交流<

88、/p><p><b>  6.總結(jié)</b></p><p>  在課程設(shè)計的第一個星期里,我認真地復習了關(guān)于線程的內(nèi)容以及java中關(guān)于Socket通信的內(nèi)容,基本掌握了有關(guān)的知識。在第一天里,主要是構(gòu)思一下思路,寫出需求分析。在寫需求分析分析時,我去網(wǎng)上看了相關(guān)線程通信的內(nèi)容,同時也看了一些有關(guān)通信方面的程序。第二天開始寫基本的框架,把程序分為兩個部分,分為一個客戶端和

89、一個服務端。在接下來的日子,我一步一步地把程序完善,用的時間比較長,因為個人的知識有限,很多時候要會遇到許多問題。</p><p>  通過這次課程設(shè)計,使我加深了對線程以及多線程知識的掌握。如何實現(xiàn)多個線程之間的通信,剛開始的時候,我想用一個文件把服務器和客戶端的交流的內(nèi)容通過FileOutputStream流將它寫進一個指定的文件里面,然后再通過FileInputStream流把它讀出來。這樣雖然可以實現(xiàn),但

90、卻必須在電腦上另外建立一個文件。后來想到了用網(wǎng)絡(luò)編輯,通過Socket與ServerSocket,兩臺計算機課建立網(wǎng)絡(luò)連接,只需通過Socket并將其連接到指定的IP地址的指定端口號,然后就建立I/O連接進行讀和寫的操作。</p><p>  此課程設(shè)計中,我嘗試用不同的方法去做。在輸入多個用戶時,要如何將他們輸出的名字和對應的信息一起對應起來呢?很常規(guī)的方法就是在線程里面添加線程的名字和信息。后來找到了可以用H

91、ashtable表,它的作用是實現(xiàn)一個哈希表,該哈希表將鍵映射到相應的值,顯示相應的信息來自哪個用戶,方法put()將指定 key 映射到此哈希表中的指定 value,通過名字對應相應的消息。Remove(Object key)從哈希表中移除該鍵及其相應的值。如果該鍵不在哈希表中,則此方法不執(zhí)行任何操作。</p><p>  關(guān)于界面,我只是適當?shù)膶W習一些比較有用的,如組件和容器,布局管理器,監(jiān)聽器,文本組件等。

92、建立事件源組件,調(diào)用其成員addActionListener()與監(jiān)聽器對象建立了監(jiān)聽與被監(jiān)聽的關(guān)系。當用戶用戶點擊時,對象會自動觸發(fā)ActionEvent事件,并以該事件對象作為實參自動調(diào)用相應事件處理方法actionPerformed();</p><p>  通過此次實驗,我基本了解了線程通信的原理,在里面我學到許多東西。而且學習到許多知識都是先前不知道的。通過不斷地學習,不懂的在網(wǎng)上找資料,和同學老師一起

93、交流,這樣一步一步地尋求答案,把困難解決。最后把程序給做好。</p><p>  這次實驗還便我意識到,如果以后要做軟件這一行,必須要對每個問題都要認真地弄清楚,只有真正的掌握了原理,你才能運用自如。另外,一旦你有了思路就馬上把它記下來,不要再猶豫,因為有時你會突發(fā)想到一些你坐在電腦前無法想到的東西。還要有一顆堅持不懈的心,對于遇到的問題,你最好自己想,把它解決,實在想不到,去網(wǎng)上找一下資料,看一下別人怎么講。再

94、者,可以和老師,同學一起交流。最后就是平時要多在網(wǎng)上看一些程序或者找一些程序設(shè)計題,通過做程序設(shè)計題提高自己程序的編寫能力。</p><p><b>  參 考 文 獻</b></p><p>  [1] ]嚴蔚敏,吳偉民等。數(shù)據(jù)結(jié)構(gòu)(C語言版) 。北京:清華大學出版,2001。</p><p>  [2]譚浩強等。C程序設(shè)計(第三版)。北京:

95、清華大學出版社,2006。</p><p>  [3]Mark Allen著馮舜璽譯。數(shù)據(jù)結(jié)構(gòu)與算法分析。北京:機械工業(yè)出版社,2007。</p><p>  [4]孫鐘秀,費翔林,駱斌等。操作系統(tǒng)教程。北京:高等教育出版社,2008。</p><p>  [5]張利國,劉偉等。Java SE 應用程序設(shè)計。北京:北京理工大學出版社</p><p

溫馨提示

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

評論

0/150

提交評論