下載本文檔
版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)
文檔簡介
1、第 5 章網(wǎng)絡(luò)與多線程技術(shù)教學提示:了解網(wǎng)絡(luò)編程的基本概念,了解基于 TCP Socket(面向連接的)網(wǎng)絡(luò)通信與 UDP Socket(無連接的)數(shù)據(jù)報通信的編程原理及區(qū)別;掌握 Socket 編程模式及 包中的常用類;了解多線程技術(shù)的概念及在網(wǎng)絡(luò)編程中的應(yīng)用,運用 File 類進行文件操作;理解流、標準輸入/輸出流的概念,運用 DataInputStream 和 DataOutputStream 類讀寫二進制文件;會編寫簡單的網(wǎng)絡(luò)通信程序。教學要求:知 識 要 點能 力 要 求相 關(guān) 知 識Socket 類、ServerSocket 類 Datagracket 類、 DatagramSoc
2、ket 類 InetAddress 類File 類 DataInputStream 類 DataOutputStream 類 Thread 類會編寫有連接的網(wǎng)絡(luò)通信程序理解無連接的數(shù)據(jù)報通信程序會使用InetAddress 類會使用常用組件 會使用輸入過濾流會使用輸出過濾流會使用線程類java.lang.Thread 類 java.lang.Runnable 類 I/O 流Hashtable 類 Enumeration 類 WindowAdapter 類、 WindowEvent 類 readUTF()方法 writeUTF()方法 close()方法 Runnable 接口會使用哈希表會使用
3、枚舉類會使用事件適配器類實現(xiàn)接口會從輸入流讀信息會用輸出流寫信息 會關(guān)閉流、關(guān)閉連接會在程序中新開線程removeAll 方法 hasMoreElements 方法 getInputStream 方法 getOutputStream 方法5.1網(wǎng)絡(luò)聊天室5.1.1程序說明在程序中使用 包中的類可以實現(xiàn)網(wǎng)絡(luò)通信。 包中定義的兩個類 Socket和 ServerSocket,分別用來實現(xiàn)客戶端和服務(wù)器端的雙向連接。Java 將底層的網(wǎng)絡(luò)通信細節(jié)予以,使得使用的編程模型是一個文件模型,即可以像操作流一樣來操作網(wǎng)絡(luò)數(shù)據(jù)傳輸。另外使用 Java 的多線程技術(shù)實現(xiàn)在網(wǎng)絡(luò)連接中一個服務(wù)器同時為多個客戶端服務(wù)
4、的功能。即使用的 TCP 協(xié)議是面向連接的,在傳送數(shù)據(jù)之前必須與目標節(jié)點建立連接,數(shù)據(jù)傳輸結(jié)束后關(guān)閉連接。本節(jié)將要編寫一個基于流式套接字的面向連接的網(wǎng)絡(luò)聊天室程序,客戶端使用 Applet瀏覽器與服務(wù)器端的 Java 應(yīng)用程序進行通信,即客戶端與服務(wù)器端建立套接字連接后,用戶輸入昵稱就可以與其他用戶聊天。聊天室界面有公聊區(qū)和私聊區(qū),用戶使用鼠標雙擊聊天列表中某個聊天者的昵稱就可以與之進行私聊;當有新用戶進入聊天室時,所有用戶都能看到該用戶的昵稱;當某用戶關(guān)閉瀏覽器或退出聊天室時,該昵稱被刪除,聊天室顯示該用戶離開的消息。設(shè)已有服 務(wù)器端程 序 (MyChatServer.java) ,及已經(jīng)
5、編譯好的 字節(jié)碼文 件 (MyChatServer.class 和 Server_thread.class)放在同一文件夾中(設(shè)為:D:網(wǎng)絡(luò)聊天室)。服務(wù)器端程序可以在 DOS 控制臺使用 java 解釋器運行;或者為方便使用可以制作一個雙擊鼠標左鍵打開的批處理文件(MyChatServer.bat),也放在“網(wǎng)絡(luò)聊天室”文件夾中。設(shè)已有客戶端主程序(MyC ntChat.java)和兩個 Java 子程序(ChatArea.java、InputName TextField.java) 、已 經(jīng)編 譯好的 字 節(jié)碼文 件 (MyC ntChat.class 、 ChatArea.class 及
6、 InputNameTextField.class)、網(wǎng)頁文件(MyC ntChat.html),都放在同一文件夾(設(shè)為:D:網(wǎng)絡(luò)聊天室)??蛻舳顺绦蚩梢酝ㄟ^使用 IE 打開網(wǎng)頁運行,也可以通過使用 AppletViewer 打開網(wǎng)頁運行。AppletViewer 是 Java JDK 附帶的工具,與使用 IE 打開網(wǎng)頁不同的是, AppletViewer 只運行網(wǎng)頁上的 Applet 成分,忽略網(wǎng)頁上的其他成分。AppletViewer 需要在 DOS 控制臺運行,為方便使用,創(chuàng)建一個調(diào)用 AppletViewer 打開網(wǎng)頁的批處理文件 (MyC ntChat.bat),也放在“網(wǎng)絡(luò)聊天室”
7、文件夾中。使用 DOS 控制臺的客戶端程序的運行結(jié)果如圖 5.1 所示。圖 5.1 客戶端程序的運行結(jié)果131使用 DOS 控制臺的服務(wù)器端程序的運行結(jié)果如圖 5.2 所示。圖 5.2 服務(wù)器端程序的運行結(jié)果客戶端用戶 1 輸入昵稱及進行公聊、私聊的程序運行結(jié)果如圖 5.3 所示。圖 5.3 客戶端 1 程序運行結(jié)果客戶端用戶 2 輸入昵稱及進行公聊、私聊的程序運行結(jié)果如圖 5.4 所示。圖 5.4 客戶端 2 程序運行結(jié)果132服務(wù)器端多客戶端的程序運行結(jié)果如圖 5.5 所示。圖 5.5 程序運行結(jié)果5.1.2實現(xiàn)方案網(wǎng)絡(luò)聊天室程序共由 4 個 Java 源文件和一個網(wǎng)頁文件組成,即 MyC
8、hatServer.java、 MyC ntChat.java、ChatArea.java、InputNameTextField.java 和 MyC ntChat.html。服務(wù)器端程序(MyChatServer.java) 由主類(MyChatServer) 和線程類(Server_thread) 組成,程序中使用的主要方法有:main(主方法)、Server_thread(構(gòu)造方法,創(chuàng)建客戶端通信服務(wù)線程)、run(接口方法, 客戶端信息)。客戶端程序由主類(MyC ntChat.java)、客戶端聊天界面類(ChatArea.java)和客戶端輸入昵稱界面類(InputNameText
9、Field.java)組成,主類中使用的主要方法有:init(客戶端初始化方法)、start(瀏覽器程序開始工作方法)和 run(接口方法);ChatArea 類中的主要方法有:ChatArea( 創(chuàng)建聊天界面) 、setSocketConnection( 與服務(wù)器建立套接字連接的方法) 、actionPerformed( 接口方法,實現(xiàn)處理事件) 和 run( 接口方法, 服務(wù)器信息) ;InputNameTextField 類中的主要方法有:InputNameTextField(構(gòu)造方法,創(chuàng)建用戶輸入昵稱界面)、set(設(shè)置能否聊天)、get(判斷能否聊天)、setSocketConnec
10、tion(實現(xiàn)與服務(wù)器建立連接的方法)、actionPerformed(接口方法,實現(xiàn)處理事件)和 run(接口方法,來的信息)。1) 服務(wù)器端程序的整體框架服務(wù)器發(fā)133import java.io.*; import .*; import java.util.*;public class MyChatServerpublic sic void main(String args)/客戶端呼叫/與客戶端套接字建立起連接的服務(wù)器端套接字/存放與各聊天客戶端通信的服務(wù)器線程的散列表peopleList=new Hashtable(); while(true)134try /創(chuàng)建一個 ServerS
11、ocket,在端口 3333客戶請求catch(IOException e1)System.out.prln(正在);try /一旦有客戶請求,就返回一個 Socket 對象用于同客戶進行交互socket=server.accept();InetAddress address=socket.getInetAddress(); System.out.prln(用戶的 IP:+address);catch (IOException e)if(socket!=null) /與客戶端通信的服務(wù)器端線程/服務(wù)器端線程啟動elsecontinue;class Server_thread extends T
12、hreadString nall,sex=null;/聊天者昵稱、 Socket socketa=null;/文件對象/數(shù)據(jù)輸入流/數(shù)據(jù)輸出流Hashtable peopleList=null; /存放昵稱的散列表 Server_thread(Socketshtable list)peopleList=list; socke;try /對得到的輸入流進行讀操作/對輸出流進行寫操作catch (IOException e)135public void run()while(true)String s=null; try /等待客戶端發(fā)來信息if(s.startsWith(:) /如果用戶提交了昵
13、稱和/截取昵稱/截取/檢查散列表中是否已有截取到昵稱的聊天者 if(boo=false)peopleList.put(name,this);/將昵稱添加到散列表/通過 OUT 向線路寫入信息/獲取所有與客戶端通信的服務(wù)器線程 while(enums.hasMoreElements()Server_thread th=(Server_thread)enums.nexement();/將當前聊天者的信息通知所有用戶 th.out.writeUTF(聊天者:+name+sex);/將其他聊天者的信息通知當前用戶,即本線程 if(th!=this)out.writeUTF(聊天者:++t
14、h.sex);else /如果該用戶存在,提示用戶重新輸入 out.writeUTF(不可以聊天:);else if(s.startsWith(公共聊天內(nèi)容:)String message=bstring(s.indexOf(:)+1); Enumeration enums=peopleLisements();/獲取所有與客戶端通信的服務(wù)器線程while(enums.hasMoreElements()(Server_thread)enums.nexement().out.writeUTF(聊天內(nèi)容: +message);else if(s.startsWith(用戶離開:)Enumeratio
15、n enums=peopleLisements(); while(enums.hasMoreElements() try136Server_thread th=(Server_thread)enums.nexement(); if(th!=this&th.isAlive()th.out.writeUTF(用戶離線:+name);catch(IOException eee)/刪除昵稱/關(guān)閉當前連接System.out.prln(name+用戶離開了);/結(jié)束線程else if(s.startsWith(私人聊天內(nèi)容:)String 悄悄話=bstring(s.indexOf(:)+1,s.ind
16、exOf(#); String toPeople=bstring(s.indexOf(#)+1);/找到要接受悄悄話的線程Server_thread toThread=(Server_threeopleList.get(toPeople); if(toThread!=null)toThread.out.writeUTF(私人聊天內(nèi)容:+悄悄話);else /通知當前用戶接受私聊的用戶已經(jīng)離線catch(IOException ee) /當聊天者關(guān)閉瀏覽器時,導(dǎo)致發(fā)生異常/獲取所有的與客戶端通信的服務(wù)器線程 Enumeration enums=peopleLisements();while(en
17、ums.hasMoreElements() /判斷接口中是否還有元素 tryServer_thread th=(Server_thread)enums.nexement(); if(th!=this&th.isAlive()th.out.writeUTF(用戶離線:+name);catch(IOException eee)peopleList.remove(name); try服務(wù)器端程序由引入和主類、線程類。由于程序中使用了服務(wù)器套接字類ServerSocket、套接字類 Socket,因而引入了 包;使用了文件和目錄路徑名的抽象表示形式類 File、數(shù)據(jù)輸出流類 DataOutputStr
18、eam、數(shù)據(jù)輸入流類 DataInputStream,因而引入了java.io 包;使用了哈希表類Hashtable、Enumeration 接口,所以引入了java.util 包。在主類類體中有一個 main 方法,在方法體中了服務(wù)器套接字對象、套接字對象及哈希表對象; Server_thread 類繼承了 Thread 類,在該類體中了 Socket、File、DataOutputStream、DataInputStream 和 Hashtable 對象;在 Server_thread 構(gòu)造方法中實現(xiàn)與客戶端通信,在 run 方法中實現(xiàn)啟動服務(wù)器端線程,使用 break 結(jié)束線程。程序的編
19、程要點已在整體框架中標出,在 5.1.3 節(jié)中將會詳細。新建“網(wǎng)絡(luò)聊天室”文件夾,打開 JCreator(也可使用其他的 Java 代碼編輯器或集成開發(fā)工具),單擊上的【New】按鈕,在出現(xiàn)的框中選擇【Files】選,在該選上選擇【Java File】選項,輸入程序名“MyChatServer”,并選擇工作位置為“網(wǎng)絡(luò)聊天室”文件夾,單擊【確定】按進入編輯器。輸入前面的程序整體框架,其中注釋說明部分的代碼,在 5.1.3 節(jié)中可以查到,全部代上的【Save】按鈕保存文件。選擇【Build】|【Compile錯誤,可按照編譯提示信息進行修改,然后保存并重新編譯,碼輸入完成并檢查無誤后單擊File
20、】菜單命令進行編譯,直到提示“Pro程序。s completed”,編譯成功。選擇【Build】|【Execute File】菜單命令運行也可使用 Java JDK 提供的 Java 工具運行程序,在 DOS 控制臺轉(zhuǎn)入“網(wǎng)絡(luò)聊天室”目錄,輸入如下命令:C:j2sdk1.4.2_14binjava MyChatServer本例采用獨立的 JDK,安裝 JDK 的路徑為 C:j2sdk1.4.2_14,Java 工具在 bin 子目錄下,為方便使用,可以將該 DOS 命令放到一個批處理文件中(設(shè)為 MyChatServer.bat)。打開記事本,輸入批處理命令:C:j2sdk1.4.2_14bi
21、njava MyChatServer保存時,選擇文件位置為“網(wǎng)絡(luò)聊天室”文件夾,文件類型為“所有文件(*.*)”,文件名為“MyChatServer.bat”,文件名可以隨意,但擴展名必須是“.bat”。運行時,在“我的電腦”中的“網(wǎng)絡(luò)聊天室”文件夾下,雙擊該批處理文件即可。137 /關(guān)閉當前連接 socketa.close();catch(IOException eee)System.out.prln(name+用戶離開了); break; /結(jié)束本線程2)客戶端程序的整體框架138import java.awt.*; import java.io.*; import .*; import
22、java.applet.*;import java.util.Hashtable;public class MyCntChat extends Applet implements Runnable/客戶端套接字對象/服務(wù)器信息的輸入流/向服務(wù)器發(fā)送信息的輸出流/用戶提交昵稱界面/用戶聊天界面/存放聊天者昵稱的散列表Label 提示條;/ 顯示提示信息組件Panel north, center;Thread thread;/客戶端啟動的線程 public void init()this.setBackground(Color.pink); width=getSize().width;/獲取當前容
23、器 Applet 的寬 height=getSize().height; /獲取當前容器 Applet 的高/創(chuàng)建對象setLayout(new BorderLayout(); /設(shè)置布局用戶提交昵稱界面=new InputNameTextField(listTable); h=用戶提交昵稱界面.getSize().height;用戶聊天界面=new ChatArea(,listTable,width,height-(h+5);/設(shè)置用戶聊天界面不可見提示條=new Label(正在連接到服務(wù)器,請稍等.);提示條.setForeground(Color.red);north=nenel(ne
24、w FlowLayout(FlowLayout.LEFT); center=nenel();nordd(用戶提交昵稱界面);nordd(提示條); center.add(用戶聊天界面);add(north,BorderLayout.NORTH); add(center,BorderLayoENTER);/確認容器對它的組件進行布局public void start()if(socket!=null&in!=null&out!=null)/清除此前的套接字信息 try/關(guān)閉套接字/關(guān)閉輸入流/關(guān)閉輸出流/關(guān)閉用戶聊天界面139catch(Exception ee)try/端口 3333 獲得服務(wù)
25、器端的 IP 地址/獲得輸入流進行讀操作/獲得輸出流進行寫操作catch (IOException ee)提示條.setText(連接失敗);if(socket!=null)/獲取服務(wù)器端地址提示條.setText(連接:+address+成功);用戶提交昵稱界面.setSocketConnection(socket,in,out); north.validate(); /確認當前容器和對其所有子組件布局if(thread=null) /啟動新線程thread=new Thread(this);/線程啟動public void stop()trysocket.close(); thread=n
26、ull;catch(IOException e)this.showSus(e.toString();public void run()while(thread!=null)if(用戶提交昵稱界面.get 能否聊天()=true)/顯示用戶聊天界面用戶聊天界面.setName(用戶提交昵稱界面.getName(); 用戶聊天界面.setSocketConnection(socket,in,out);提示條.setText(祝您聊天愉快!); center.validate(); /確認容器和它的所有子組件140break;tryThread.sleep(100);catch(Exception
27、e)* import java.awt.*;import .*; import java.awt.event.*; import java.io.*;import java.util.Hashtable;public class ChatArea extends Panel implementionListener,RunnableSocket socket=null;/與服務(wù)器端建立連接的套接字 DataInputStream in=null; /服務(wù)器信息的輸入流 DataOutputStream out=null; /向服務(wù)器發(fā)送信息的輸出流/服務(wù)器信息的線程/公聊顯示區(qū)、私聊顯示區(qū)/輸
28、入聊天內(nèi)容/發(fā)送內(nèi)容、刷新公聊區(qū)和刷新私聊區(qū) Label 提示條=null;String nall;/聊天者昵稱Hashtable listTable;/存放聊天者昵稱的散列表/顯示全部聊天者的昵稱的列表框組件/選擇私聊者的下拉列表width,height;/聊天區(qū)的寬和高/創(chuàng)建聊天界面public ChatArea(String name,Hashtable listTable,width,height)setLayout(null); setBackground(Color.pink); this.width=width; this.height=height; setSize(width
29、,height); this.listTable=listTable; =name; threadMessage=new Thread(this);公聊顯示區(qū)=new TextArea(10,10);私聊顯示區(qū)=new TextArea(10,10);確定=new Button(發(fā)送信息到:);刷新公聊區(qū)=new Button(刷新公聊區(qū));刷新私聊區(qū)=new Button(刷新私聊區(qū));141提示條=new Label(雙擊聊天者可私聊,Label.CENTER);送出信息=new TextField(28);確定.addActionListener(this);送出信息.
30、addActionListener(this); 刷新公聊區(qū).addActionListener(this);刷新私聊區(qū).addActionListener(this);ponent=new List();/雙擊列表中的昵稱可選中聊天者與之進行私聊 privateChist=new Choice(); privateChist.add(大家(*);/默認用戶輸入內(nèi)容發(fā)給所有聊天者add(公聊顯示區(qū));公聊顯示區(qū).setBounds(10,10,(width-120)/2,(height-120); add(私聊顯示區(qū));私聊顯示區(qū).setBounds(10+(width-120)/2,10,(
31、width-120)/2,(height-120); add(ponent);ponent.setBounds(10+(width-120),10,100,(height-160); add(提示條);提示條.setBounds(10+(width-120),10+(height-160),110,40); Panel pSouth=nenel();pSoudd(送出信息);pSoudd(確定);pSoudd(privateChist); pSoudd(刷新公聊區(qū));pSoudd(刷新私聊區(qū)); add(pSouth);pSouth.setBounds(10,20+(height-120),w
32、idth-20,60);public void setName(String s)name=s;/與服務(wù)器建立套接字連接public void setSocketConnection(Socket socket,DataInputStream in,DataOutputStream out)this.socket=socket; this.in=in; this.out=out;try /啟動線程catch(Exception e)/處理事件public void actionPerformed(ActionEvent e)142if(e.getSource()=確定|e.getSource(
33、)=送出信息)String message=;String people=privateChist.getSelectedItem();/獲取對象的昵稱 message=送出信息.getText(); if(message.length()0)/將聊天內(nèi)容發(fā)送給服務(wù)器try if(people.equals(大家)out.writeUTF(公共聊天內(nèi)容:+name+說:+message);elseout.writeUTF(私人聊天內(nèi)容:+name+悄悄地說:+message+#+people);catch(IOException event)else if(e.getSource()ponen
34、t)privateChist.insert(ponent.getSelectedItem(),0); privateChist.repa();else if(e.getSource()=刷新公聊區(qū))公聊顯示區(qū).setText(null);else if(e.getSource()=刷新私聊區(qū))私聊顯示區(qū).setText(null);/服務(wù)器信息public void run()while(true)String s=null; try/等待服務(wù)器信息if(s.startsWith(聊天內(nèi)容:)/服務(wù)器發(fā)來的信息String content=bstring(s.indexOf(:)+1);143
35、公聊顯示區(qū).append(n+content);if(s.startsWith(私人聊天內(nèi)容:)/服務(wù)器發(fā)來的信息String content=bstring(s.indexOf(:)+1);私聊顯示區(qū).append(n+content);else if(s.startsWith(聊天者:)String people=bstring(s.indexOf(:)+1,s.indexOf(); String sex=bstring(s.indexOf()+2); listTable.put(people,people+(+sex+);ponent.add(String)listTable.get(p
36、eople);/刷新 List,顯示新用戶昵稱else if(s.startsWith(用戶離線:)/刪除離線用戶信息String awayPeopleName=bstring(s.indexOf(:)+1); ponent.remove(String)listTable.get(awayPeopleName); ponent.repa();公聊顯示區(qū).append(n+(String)listTable.get(awayPeopleName)+離線);listTable.remove(awayPeopleName);Thread.sleep(5);catch(IOException e)/服
37、務(wù)器關(guān)閉套接字連接時,導(dǎo)致異常ponent.removeAll(); ponent.repa();listTable.clear();公聊顯示區(qū).setText(與服務(wù)器的連接已中斷n 必須刷新瀏覽器才能再次聊天); break;catch(erruptedException e)* import java.awt.*;import .*; import java.awt.event.*; import java.io.*;import java.util.Hashtable;public class InputNameTextField extends Panel implementionL
38、istener,Runnable144/輸入昵稱的文本框/選擇的單選框Button 進入聊天室=null,退出聊天室=null;/選擇進入、退出聊天室/客戶端套接字/服務(wù)器發(fā)來的信息/向服務(wù)器發(fā)送消息/負責服務(wù)端信息的線程能否聊天=false;/判斷能否聊天Hashtable listTable;/存放聊天者昵稱的散列表/創(chuàng)建用戶輸入昵稱界面public InputNameTextField(Hashtable listTable)this.setBackground(Color.pink); this.listTable=listTable; nameFile=new TextField(1
39、0); group=new CheckboxGroup();male=new Checkbox(男,true,group);female=new Checkbox(女,false,group);進入聊天室=new Button(進入聊天室);退出聊天室=new Button(退出聊天室);進入聊天室.addActionListener(this);退出聊天室.addActionListener(this);thread=new Thread(this); add(new Label(昵稱:); add(nameFile);add(male); add(female); add(進入聊天室);a
40、dd(退出聊天室);退出聊天室.setEnabled(false);/設(shè)置能否聊天public void set 能否聊天(b)能否聊天=b;/判斷能否聊天publicget 能否聊天()return 能否聊天;/獲取聊天者的昵稱public String getName()return name;/設(shè)置聊天者的昵稱public void setName(String s)145name=s;public void setSocketConnection(Socket socket,DataInputStream in,DataOutputStream out)this.socket=sock
41、et; this.in=in; this.out=out;try /啟動線程thread.start();catch(Exception e)nameFile.setText(+e);public Socket getSocket()return socket;public void actionPerformed(ActionEvent e)if(e.getSource()=進入聊天室)退出聊天室.setEnabled(true); if(能否聊天=true)nameFile.setText(您正在聊天:+name);elsethis.setName(nameFile.getText();S
42、tring sex=group.getSelectedCheckbox().getLabel(); if(socket!=null&name!=null)tryout.writeUTF(:+name+:+sex);catch(IOException ee)nameFile.setText(沒有連通服務(wù)器+ee);if(e.getSource()=退出聊天室)try客戶端程序由 3 個 Java 源程序組成。ChatArea 類和 InputNameTextField 類依賴于主類 MyC ntChat,主類負責創(chuàng)建網(wǎng)絡(luò)聊天室客戶端的 Java Applet 小程序,如與服務(wù)器連接成功,程序則做
43、出相應(yīng)提示并顯示輸入昵稱界面;當用戶輸入昵稱后,進入用戶聊天界面,可以看到聊天者列表、公聊區(qū)、私聊區(qū);用戶在文本框中輸入信息后,就可以進行公聊或私聊。InputNameTextField 類主要負責向服務(wù)器發(fā)送當前聊天者的昵稱,獲取其他聊天者的昵稱,并將所有聊天者的昵稱添加到列表中。ChatArea 類負責管理客戶聊天界面,該界面146out.writeUTF(用戶離開:);catch(IOException ee)public void run()String message=null; while(true)if(in!=null)trymessage=in.readUTF();catch
44、(IOException e)nameFile.setText(和服務(wù)器斷開+e);if(message.startsWith(可以聊天:)能否聊天=true; break;else if(message.startsWith(聊天者:)String people=message.substring(message.indexOf(:)+1); listTable.put(people,people);/將目前的聊天者昵稱添加到散列表中else if(message.startsWith(不可以聊天:)能否聊天=false;nameFile.setText(該昵稱已被占用);可以把當前聊天者要
45、發(fā)送的給所有聊天者或指定聊天者;也可以其他人的信息,并可以判斷是公聊信息還是私聊信息,然后分別顯示在相應(yīng)的聊天區(qū)域。由于客戶端程序主類繼承了 Applet 類,因而引入了 java.applet 包;3 個類中由于使用了實現(xiàn)套接字類 Socket,因而引入了 包;由于使用了組件,因而引入了 java.awt包;使用了數(shù)據(jù)輸出流類 DataOutputStream、數(shù)據(jù)輸入流類 DataInputStream,因而引入了 java.io 包;使用了哈希表類 Hashtable,因而引入了 java.util.Hashtable 類;由于有事件處理,因而引入了 java.awt.event 包。程
46、序的編程要點已在整體框架中標出,在 5.1.3 節(jié)中將會詳細。前面已建“D:網(wǎng)絡(luò)聊天室”文件夾,將客戶端程序的 3 個*.java 文件和編譯好生成的所有字節(jié)碼*.class 文件都放在該文件夾中。打開 JCreator(也可使用其他的 Java 代碼編輯器或集成開發(fā)工具),單擊上的【New】按鈕,在出現(xiàn)的框中選擇【Files】選,在該選上選擇【Java File】選項,輸入程序名“MyCntChat”,并選擇工作位置為“網(wǎng)絡(luò)聊天室”文件夾,單擊【確定】按進入編輯器。輸入前面的程序整體框架,其中注釋說明部分的代碼,在 5.1.3 節(jié)中可以查到,全部代碼輸入完成并檢查無誤后單擊File】菜單命令
47、進行編譯,上的【Save】按鈕保存文件。選擇【Build】|【Compile錯誤,可按照編譯提示信息進行修改,然后保存并重新編譯,直到提示“Pros completed”,編譯成功。設(shè)計一個簡單的包含 Applet 標記的網(wǎng)頁(MyCntChat.html),代碼如下:打開 JCreator(也可使用其他的 HTML 代碼編輯器或可視化設(shè)計器),單擊上的【New】按鈕,在出現(xiàn)的框中選擇【Files】選,在該選上選擇【HTML File】選項,輸入網(wǎng)頁文件名“MyCntChat”,并選擇工作位置為“網(wǎng)絡(luò)聊天室”文件夾,單擊【確定】按進入編輯器。輸入上述代碼,檢查無誤后單擊上的【Save】按鈕保存
48、文件,在“網(wǎng)絡(luò)聊天室”文件夾中將出現(xiàn) MyCntChat.html 文件,網(wǎng)頁制作完成。使用 IE 打開網(wǎng)頁即可運行其中的 Applet 程序。也可使用Java JDK 提供的AppletViewer 工具打開網(wǎng)頁,只運行網(wǎng)頁上的Applet 成分,在 DOS 控制臺轉(zhuǎn)到“網(wǎng)絡(luò)聊天室”,輸入以下命令:C:j2sdk1.4.2_14binAppletViewer MyCntChat.html為方便使用,可以將該 DOS 命令放到一個批處理文件中(設(shè)為 MyC nChat.bat)。打開記事本,輸入上述命令,保存時,選擇文件位置為“網(wǎng)絡(luò)聊天室”文件夾,文件類型為“所有文件(*.*)”,文件名為“M
49、yC nChat.bat”,文件主名可以隨意,但擴展名必須是“.bat”。147運行時,在“電腦”中的“網(wǎng)絡(luò)聊天室”文件夾下,雙擊該批處理文件即可。5.1.3代碼及分析在程序的整體框架中,說明編程要點的注釋部分對應(yīng)的代碼及分析如下。1) 服務(wù)器端程序(1)在 main 方法中。(2)在 Server_thread 類中的域。(3)在 Server_thread 構(gòu)造方法中。(4)在 run 方法中。148/等待客戶端發(fā)來的信息 s=in.readUTF();/截取昵稱name=bstring(s.indexOf(:)+1,s.indexOf();/截取sex=bstring(s.lastInd
50、exOf(:)+1);/檢查散列表中是否已有截取到昵稱的聊天者 boo=peopleList.containsKey(name);/通過 OUT 向線路寫入信息out.writeUTF(可以聊天:);/獲取所有與客戶端通信的服務(wù)器線程/對得到的輸入流進行讀操作in=new DataInputStream(socketa.getInputStream();/對輸出流進行寫操作out=new DataOutputStream(socketa.getOutputStream();/文件對象File file=null;/數(shù)據(jù)輸出流 DataOutputStream out=null;/數(shù)據(jù)輸出流Da
51、taInputStream in=null;/客戶端呼叫ServerSocket server=null;/與客戶端套接字建立起連接的服務(wù)器端套接字 Socket socket=null;/存放與各聊天者客戶端通信的服務(wù)器線程的散列表Hashtable peopleList;/創(chuàng)建一個 ServerSocket 在端口 3333客戶請求server=new ServerSocket(3333);/與客戶端通信而啟動的服務(wù)器端線程Server_threeopleThread=new Server_thread(socket,peopleList);/服務(wù)器端線程啟動peopleThread.st
52、art();在服務(wù)器端程序中,存放與各聊天客戶端通信的服務(wù)器線程的散列表使用 Hashtable 類實現(xiàn),該散列表將鍵定義為相應(yīng)的值。任何非 null 對象都可以用作鍵或值。將昵稱添加到散列表時調(diào)用 put 方法,從散列表中移去昵稱時調(diào)用 remove 方法,指定私聊者昵稱時調(diào)用 get 方法。Server_thread 類是java.lang.Thread 類的子類,Thread 類是負責向其他類提供線程支持的最主要的類,要使一個類具有線程功能,在Java 中只要簡單地從Thread 類派生一個子類就可以了;Thread 類最重要的方法是 run 方法。run 方法是新線程執(zhí)行的方法,因此生
53、成 java.lang.Thread 的子類時,必須有相應(yīng)的 run 方法。啟動線程需調(diào)用 start 方法實現(xiàn)。使用過濾流DataInputStream、DataOutputStream 為輸入/輸出流,調(diào)用getInputStream()方法獲得輸入流,調(diào)用getOutputStream 方法獲得輸出流。為了防止傳輸中文信息時產(chǎn)生亂碼,使用 readUTF 方法和 writeUTF 方法進行讀和寫信息。2) 客戶端程序(1) 在 MyCntChat 類中。域:init 方法:149/獲取當前容器 Applet 的寬width=getSize().width;/獲取當前容器 Applet 的
54、高height=getSize().height;/客戶端套接字對象 Socket socket=null;/服務(wù)器信息的輸入流DataInputStream in=null;/向服務(wù)器發(fā)送信息的輸出流 DataOutputStream out=null;/用戶提交昵稱界面InputNameTextField 用戶提交昵稱界面=null;/用戶聊天界面ChatArea 用戶聊天界面=null;/存放聊天者昵稱的散列表Hashtable listTable;/客戶端啟動的線程Thread thread;Enumeration enums=peopleLisements();/刪除昵稱 peopl
55、eList.remove(name);/關(guān)閉當前連接socketa.close();/結(jié)束線程 break;/通知當前用戶接受私聊的用戶已經(jīng)離線out.writeUTF(私人聊天內(nèi)容:+toPeople+已經(jīng)離線);start 方法:run 方法:(2) 在 ChatArea 類中。域:150/服務(wù)器信息的線程Thread threadMessage=null;/公聊顯示區(qū)、私聊顯示區(qū)TextArea 公聊顯示區(qū),私聊顯示區(qū)=null;/輸入聊天內(nèi)容TextField 送出信息=null;/負責發(fā)送內(nèi)容、刷新公聊區(qū)和刷新私聊區(qū) Button 確定,刷新公聊區(qū),刷新私聊區(qū);/存放聊天者昵稱的散列
56、表 Hashtable listTable;/顯示全部聊天者的昵稱的列表框組件Listponent=null;/選擇私聊者的下拉列表Choice privateChist;/顯示用戶聊天界面用戶聊天界面.setVisible(true);/關(guān)閉套接字 socket.close();/關(guān)閉輸入流in.close();/關(guān)閉輸出流 olose();/關(guān)閉用戶聊天界面用戶聊天界面.setVisible(false);/端口 3333 獲得服務(wù)器端的 IP 地址socket = new Socket(this.getCodeBase().getHost(), 3333);/獲得輸入流進行讀操作in=n
57、ew DataInputStream(socket.getInputStream();/獲得輸出流進行寫操作out=new DataOutputStream(socket.getOutputStream();/獲取服務(wù)器端地址InetAddress address=socket.getInetAddress();/線程啟動thread.start();/創(chuàng)建對象listTable=new Hashtable();/設(shè)置用戶聊天界面不可見用戶聊天界面.setVisible(false);/確認容器對它的組件進行布局validate();構(gòu)造方法 ChatArea:setSocketConnect
58、ion 方法:actionPerformed 方法:3)在 InputNameTextField 類中的域在客戶端程序中,實現(xiàn)多線程的方法是實現(xiàn) Runnable 接口,通過實現(xiàn) Runnable 接口的方法創(chuàng)建每一個對象的線程。為實現(xiàn) Runnable 接口,一個類僅需實現(xiàn)一個 run 方法,啟動線程仍調(diào)用 start 方法。在使用語句 socket=new Socket(this.getCodeBase().getHost(),3333)實現(xiàn)從端口 3333 獲得服務(wù)器端IP 地址時,要注意在建立Socket 連接時,服務(wù)器端和客戶端的端致,否則建立不了連接,并且必須有主機 IP 地址或主
59、機名參數(shù)。必須設(shè)為一在讀/寫信息方面與服務(wù)器端的解決方法相同,已在服務(wù)器程序分析中敘述過。5.1.4相關(guān)知識1. 多線程支持多線程技術(shù)是Java 語言的重要特點,多線程是相對于進程或單線程而言的,它具有并發(fā)性、執(zhí)行效率高的特點。在多線程機制中,不同的線程處理不同的任務(wù),它們之間151/輸入昵稱的文本框 TextField nameFile=null;/選擇的單選框Checkbox male=null,female=null;/客戶端套接字Socket socket=null;/服務(wù)器發(fā)來的信息DataInputStream in=null;/向服務(wù)器發(fā)送消息 DataOutputStream out=null;/負責服務(wù)端信息的線程Thread thread=null;/獲取對象的昵稱people=people.substring(0,people.indexOf();/等待服務(wù)器信息 s=in.readUTF();/刷新 List,顯示新用戶昵稱ponent.repa();/啟動線程threadMessage.start();/雙擊列表中的昵稱可選中聊天者與之進行私聊 ponent.addActionListener(this);/默認用戶輸入內(nèi)容發(fā)給所有聊天者privateChist.select(0);互不,不會由于一個線程的等待而影響其他線程的運行,這樣容易實現(xiàn)網(wǎng)絡(luò)上
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
- 6. 下載文件中如有侵權(quán)或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 光伏發(fā)電項目屋頂租賃合同
- 廣西小學教學樓合同協(xié)議書
- 海外打工合同書
- 合同到期聲明范本
- 2024年廣州客運資格證應(yīng)用能力試題及答案詳解
- 2024對外建筑工程承包合同
- 2024家庭農(nóng)場土地租賃合同
- 深圳大學《自然辯證法》2021-2022學年第一學期期末試卷
- 魚肉購銷合同(2篇)
- 種植松樹協(xié)議書(2篇)
- 建設(shè)項目設(shè)計管理方案
- 2024年屆海南航空控股股份有限公司招聘筆試參考題庫含答案解析
- 前程無憂在線測試題庫及答案行測
- 手術(shù)室突發(fā)事件的緊急處理與應(yīng)急演練
- 《軍事理論》課程標準
- 倉庫貨物條碼管理培訓(xùn)
- 第六章-中國早期社會學中的社區(qū)學派-《中國社會學史》必備
- 太陽能發(fā)電技術(shù)在航天與航空領(lǐng)域的應(yīng)用
- 大學生預(yù)防猝死知識講座
- (2)反壟斷法(字向東)
- 行政事業(yè)單位合同管理內(nèi)部控制制度
評論
0/150
提交評論