摘要:隨著網絡技術與計算機開發語言的發展,越來越多的程序員利用Java來編寫網絡程序。本文介紹了Socket的通信機制,并使用Java語言、套接字接口(Socket API)技術和多線程相結合的模式實現了多客戶端與服務器的并發通信的多人聊天系統。
關鍵詞:Java;Socket;多客戶并發;網絡通信
中圖分類號:TP393文獻標識碼:A文章編號:1009-3044(2008)20-30253-03
Design Implement of Chat System Based on Socket Multi-user Parallel Communication
MO Zu-qin, OUYANG Yan-jie, MA Kang
(Dept of Computer Eng, Shiyan Technical Institute Eng, Shiyan 442000, China)
Abstract: As internet technic and computer language develop, more and more programmers make use of Java to compile net programme. This paper introduces the mechanism of communications and using the combination of Java language, Socket API technic and the multithreading to implement chat system in which multi-user and server can communicate parallel.
key words: Java; Socket; multi-user send parallel; Net communication
1 引言
Java是一種可以編寫跨平臺應用軟件的面向對象的程序設計語言,網絡應用是Java語言取得成功的領域之一,它已經成為現在Internet上最流行的一種編程語言。網絡編程的目的就是直接或間接地通過網絡協議與其它計算機進行通訊。兩臺計算機通訊需解決兩個主要問題:一是如何準確定位網絡上的主機;二是找到主機后如何可靠有效地進行數據傳輸。
Java語言作為網絡編程語言,提供了強大的網絡編程接口。針對網絡通信的不同層次,Java提供的網絡功能有四大類:InetAddress、URL、Socket、Datagram。Socket是Internet使用的協議組TCP/IP的組合,實現了兩臺主機之間通過端口進行網絡通信。Java.net包中提供Socket類,隱藏了Socket的實現細節,不需要開發者編寫接口程序,而可以快速的實現網絡的通信。[1]
2 Socket的通信
2.1 Socket通信機制
在Java中,可以使用兩種Socket方式,即流式Socket和數據報式Socket。流式Socket提供了雙向的、有序的、無重復、可靠的的數據流服務,采用的是一種TCP協議。數據報式Socket支持雙向的數據流,但不保證是可靠的、有序的、無重復的傳輸,采用的是UDP協議。[1]兩種Socket相比較而言,流式Socket具有較高的安全性,但有一定的額外開銷。而數據報式Socket與之相反。筆者根據實際情況采用的是流式Socket方式。
基于TCP協議的流式Socket實現網絡通信的類有兩個:在客戶端的Socket類和在服務器端的ServerSocket類。無論一個Socket通信程序的功能多么齊全,程序多么復雜,Socket基本
結構都是一樣的,都包括以下四個基本步驟:
(1)在客戶端和服務器端創建Socket和ServerSocket實例;
(2)打開連接到Socket的輸入/輸出流;
(3)利用輸入/輸出流,按照一定的協議對Socket進行讀/寫操作;
(4)關閉輸入/輸出流和Socket。
Socket通信機制框圖見圖1。
2.2 Socket的多客戶端并發通信
支持多個客戶端的Socket通信實現方法有多種:方法一,在一臺計算機上一次啟動多個服務器程序(端口號必須不同);方法二,將服務器程序寫成多線程的,不同處理線程為不同的客戶服務,主線程只負責循環等待,處理線程負責網絡連接,接收客戶輸入的信息。
實現多個客戶與服務器并發通信,就像服務器與自己連接一樣,筆者認為最好引入多線程機制。多線程正好是Java提供的一個重要機制,支持多個程序并發執行。服務器端每當建立一個新的Socket連接,主線程就啟動一個新的線程,負責服務器與客戶端的通信;而主線程繼續等待下一個客戶端的連接。當客戶端斷開連接后,子線程釋放其占用的所有Socket資源[3]。多線程支持多客戶端的具體框圖見圖2。
3 多客戶端聊天程序的設計
系統主要分為兩大部分:TCP服務器Server和客戶端Client。
3.1 服務器端程序編寫
服務器端等待用戶連接,如有用戶發送連接請求后,創建一個用戶實例,記錄客戶端的相關信息,維護與該用戶的連接。根據聊天的接收人信息,再將接收的數據傳輸給客戶端。當用戶斷開連接時,關閉用戶實例,斷開此用戶連接。[2]主要步驟如下:
(1) 啟動服務器
try {
server=new ServerSocket(port);//初始化服務器套接字
while(true){socket=server.accept(); //等待客戶連接
System.err.println(socket.getInetAddress()+\"連接\\"); //得到客戶機地址
Client client=new Client(socket);//實例化一個客戶線程
clients.addElement(client);//增加客戶線程到向量中
client.start(); //啟動線程
notifyChatRoom(); //監視聊天室連接變化
} }catch(Exception ex) {
ex.printStackTrace(); //輸出出錯信息}
(2) 更新在線用戶
for(int i=0;i {//elementAt方法返回在特定位置的元素,返回的元素為Object對象 Client c=(Client)clients.elementAt(i); newUser.append(\":\"+c.name);//客戶端姓名字符串,取得客戶端的名字 }sendClients(newUser); //把取得的客戶端名字發送給每個客戶端 (3) 多線程的實現 聊天室的服務器采用多線程實現,每當一個新的用戶連接到服務器時,就實例化一個新的線程來與該客戶端通信。Client類負責維護客戶端的相關信息,比如IP地址、聊天室中的用戶名、連接端口等,并實現了信息發送的send方法。主要代碼如下。 //得到輸入流 BufferedReader reader = new BufferedReader(new InputStreamReader(s.getInputStream())); PrintStream ps=new PrintStream(s.getOutputStream()); //得到輸出流 String info=reader.readLine(); //讀取接受到的信息 ps.println(msg); //輸出信息 ps.flush(); public void run(){while(true){ String line=1; try{line=reader.readLine();//讀取數據流 }catch(IOException ex){ ex.printStackTrace(); //輸出錯誤信息 MyChatServer.disconnect(this); //斷開連接 MyChatServer.notifyChatRoom(); //更新信息 return;} …… 3.2 客戶端程序編寫 提供良好的用戶界面,便于用戶連接、查看在線用戶、發送信息。當與服務器建立連接后,發送聊天信息。同時,檢測服務器端有無數據發送,接收數據,更新顯示。 (1)界面設計(代碼略) (2)事件處理 建立連接的事件處理代碼: try{if (socket==1){ socket= new Socket(InetAddress.getLocalHost(),5656); //實例化一個套接字 ps=new PrintStream(socket.getOutputStream());//獲取輸出流 StringBuffer info=new StringBuffer(\"INFO: \"); String userinfo=jTextField1.getText()+\":\"+InetAddress.getLocalHost().toString(); ps.println(info.append(userinfo));//輸出信息 ps.flush(); listen=new Listen(this,jTextField1.getText(),socket); //實例化監聽線程 listen.start(); /啟動線程 }}catch (Exception ex){} 發送信息的代碼: if(socket!=1){StringBuffer msg=new StringBuffer(\"MSG: \"); String msgtxt=new String(jTextField2.getText()); ps.println(msg.append(jTextField2.getText())); //發送信息 ps.flush(); (3)監聽線程的實現 Listen類用于與服務器進行通信,并維護一些連接信息。部分代碼如下。 public Listen(MyChatClient p,String n,Socket s) { …… public void run(){ String msg=1; while(socket!=1){ try{msg=reader.readLine();//讀取服務器端傳來信息 }catch(IOException ex){ client.disconnect(); //出錯則斷開連接 }if (msg==1) { /從服務器傳來的信息為空則斷開此次連接 client.listen=1; client.socket=1; client.list1.removeAll(); return;}……}} 3.3 運行結果 本程序的運行界面如圖3所示。 4 結束語 Java語言具有平臺獨立、面向對象、多線程、簡單性、解釋性等許多優點,是目前廣泛流行的編程語言。筆者使用Socket與多線程機制相結合的方法,編寫了簡便的客戶端與服務器的并發通信聊天程序。此程序具有成本低、節省帶寬和跨平臺可移植性的優點。隨著寬帶網絡的進一步發展,我們還可以開發基于Socket的多人視頻聊天軟件。 參考文獻: [1] 王靜,曲鳳娟.基于Socket的多用戶并發通信的設計[J].福建電腦,2007(3):164. [2] 袁海燕,王文濤.Java實用程序設計100例[M].北京:人民郵電出版社,2005:226-229. [3] 陳更力,張青.基于Java Socket網絡編程的一種新實現[J].電腦開發與應用,2006(6):13. 注:“本文中所涉及到的圖表、注解、公式等內容請以PDF格式閱讀原文。”