JavaSE學完之後,用java實現的聊天室融合了不少java知識.java
好比GUI簡單的圖形界面,集合,IO,多線程,socket,監聽等.服務器
那麼這個聊天系統是如何實現的呢?網絡
首先咱們要有界面.如圖所示.多線程
這僅僅是一個簡單的Frame窗口界面.socket
首先package : 包入境,至關於這個類文件的絕對路徑,與別人重複概率減少ide
import : 導入包/類的意思.當要想調用某個包中的類的方法,就要用到import 優化
extends : ChatClient01繼承Frame,至關於,繼承了父類Frame裏面的全部方法this
接下來如圖中代碼所示,聲明接下來要用到的變量,變量聲明三步:指定數據類型,指定變量名,賦值spa
main : 程序的入口線程
實例化ChatClient01而後調用LaunchFrame()裏面的方法,而且把它實現.
this : 就是指當前對象.
pack() : 調用pack()方法,這個方法就是依據你放置的組件設定窗口的大小 使之正好能容納你放置的全部組件
setVisible() : 設置可視化窗口可見.
窗口實現了,接下來就該實現對窗口的一些響應.
這個過程就是對這個Frame窗口進行了監聽,感應,讓他實現某些功能.
這裏就已經鏈接到了服務器.使用到了socket,那麼socket就是網絡上的兩個程序經過一個雙向的通信鏈接實現數據的交換,這個雙向鏈路的一端稱爲一個Socket
說簡單就就像插座.
Socket通信的過程:1 建立socket
2 打開連接到socket的輸入輸出流
3 對socket進行讀寫操做
4 關閉socket
這個就能夠實現發送功能了.
這裏就實現了多個線程同時發送接收,實現對話.
那麼這一步步是怎麼實現的,我簡單說一下個人理解.
界面--->控件監聽/感應--->添加服務器--->連接服務器--->把數據發送到服務器,而且得到客戶端數據並輸出--->接受多線程客戶端請求--->優化--->關閉數據接受線程
整體來講,就差很少完整了.其中可能在涉及到服務端以及多線程客戶請求的時候可能有些麻煩,但細心一點,認真一點,會ok
剛開始的程序只能實現Server和一個客戶的對話,爲了實如今服務器方給多個客戶提供服務的功能,須要對開始單線程的程序進行改造,利用多線程實現多客戶機制.
聊天室服務端:
public class ChatServer {
boolean started = false;
ServerSocket ssoc = null;//對象變量
ArrayList<Client> clients = new ArrayList<Client>();//存放對象的集合
public static void main(String[] args) {
new ChatServer().serverStart();
}
private void serverStart(){
try {
ssoc = new ServerSocket(8888);//建立一個ServerSocket在端口8888監聽客戶請求
started = true;
} catch (BindException e) { //出錯,出錯信息
System.out.println("服務器端口已經被佔用");
System.out.println("請關閉服務器從新啓動");
System.exit(0);
} catch (IOException e) {
e.printStackTrace();
}
try {
while (started) {//循環等待客戶端鏈接
Socket soc;
try {
soc = ssoc.accept();//使用accept()阻塞等待客戶請求,有客戶,請求到來則產生一個Socket對象,並繼續執行 boolean bConnected = false; Client c = new Client(soc); new Thread(c).start();//開始一個線程 clients.add(c); } catch (Exception e) { e.printStackTrace(); } } } catch (Exception e) { // TODO: handle exception } } private class Client implements Runnable { private DataOutputStream dos = null; DataInputStream dis = null; Socket soc = null; boolean started = false; boolean bConnected = false; public Client(Socket soc) { try { this.soc = soc; dis = new DataInputStream(soc.getInputStream());//獲得輸入流 dos = new DataOutputStream(soc.getOutputStream());//獲得輸出流 bConnected = true; } catch (Exception e) { e.printStackTrace(); } } @Override public void run() { //針對每一個socket進行 try { while (bConnected) { String str = dis.readUTF(); System.out.println(str); for (int i = 0; i < clients.size(); i++) { Client c = clients.get(i); c.send(str); } } } catch (EOFException e) { System.out.println("客戶端退出"); } catch (IOException e) { e.printStackTrace(); } finally { try { if (dis != null) { dis.close(); } if (soc != null) {//socket不爲空 soc.close();//關閉socket } } catch (Exception e2) { e2.printStackTrace(); } } } public void send(String str) {//發送 try { dos.writeUTF(str); } catch (IOException e) { e.printStackTrace(); } } }}