Java網絡編程案例---聊天室


  網絡編程是指編寫運行在多個設備(計算機)的程序,這些設備都通過網絡連接起來。

  java.net包中JavaSE的API包含有類和接口,它們提供低層次的通信細節。你可以直接使用這些類和接口,來專注於解決問題,而不用關注通信細節。

  java.net包中提供了兩種常見的網絡協議的支持:

  TCP:TCP是傳輸控制協議的縮寫,它保障了兩個應用程序之間的可靠通信。通常用於互聯網協議,被稱TCP/IP。

  UDP:UDP是用戶數據報協議的縮寫,一個無連接的協議。提供了應用程序之間要發送的數據的數據報。

  本案例以TCP協議為例,結合多線程,實現一個多人同時聊天的聊天室。

  釋放資源:

  Utils.java

 1 package com.bjwyj.chat;
 2 
 3 import java.io.Closeable;
 4 
 5 public class Utils {
 6     /**
 7      * 釋放資源
 8      */
 9     public static void close(Closeable... targets) {
10         for(Closeable target:targets) {
11             try {
12                 if(target!=null) {
13                     target.close();
14                 }
15             }catch(Exception e) {
16                 e.printStackTrace();
17             }
18         }
19     }
20 }

  服務器端:

  Chat.java

  1 package com.bjwyj.chat;
  2 
  3 import java.io.DataInputStream;
  4 import java.io.DataOutputStream;
  5 import java.io.IOException;
  6 import java.net.ServerSocket;
  7 import java.net.Socket;
  8 import java.util.concurrent.CopyOnWriteArrayList;
  9 
 10 /**
 11  * 在線聊天室:服務端
 12  * 目標:加入容器實現群聊和私聊
 13  * 
 14  * @author 吳永吉
 15  *
 16  */
 17 public class Chat {
 18     private static CopyOnWriteArrayList<Channel> all = new CopyOnWriteArrayList<>();
 19     public static void main(String[] args) throws IOException {
 20         System.out.println("------server------");
 21         //1.指定端口:使用ServerSocket創建服務器
 22         ServerSocket server = new ServerSocket(9999);
 23         //2.阻塞式等待連接accept
 24         while(true) {
 25             Socket client = server.accept();
 26             System.out.println("一個客戶端建立了連接");
 27             Channel c = new Channel(client);
 28             all.add(c); //管理所有的成員
 29             new Thread(c).start();
 30         }
 31     }
 32     //一個客戶代表一個Channel
 33     static class Channel implements Runnable{
 34         private DataInputStream dis;
 35         private DataOutputStream dos;
 36         private Socket client;
 37         private boolean isRunning;
 38         private String name;
 39         
 40         public Channel(Socket client) {
 41             isRunning = true;
 42             this.client = client;
 43             try {
 44                 dis = new DataInputStream(client.getInputStream());
 45                 dos = new DataOutputStream(client.getOutputStream());
 46                 //獲取名稱
 47                 this.name = receive();
 48                 //歡迎你的到來
 49                 this.send("歡迎上線");
 50                 this.sendOthers(this.name+"上線啦!",true);
 51             }catch(Exception e) {
 52                 release();
 53             }
 54         }
 55         
 56         //接收消息
 57         public String receive() {
 58             String msg = "";
 59             try {
 60                 msg = dis.readUTF();
 61             } catch (IOException e) {
 62                 System.out.println("-------Chat receive------");
 63                 release();
 64             }
 65             return msg;
 66         }
 67         //發送消息
 68         public void send(String msg) {
 69             try {
 70                 dos.writeUTF(msg);
 71                 dos.flush();
 72             } catch (IOException e) {
 73                 System.out.println("--------Chat send-------");
 74                 release();
 75             }
 76         }
 77         /**
 78          * 群聊:獲取自己的消息,發給其他人
 79          * 私聊:約定數據格式:@xxx:msg
 80          * @param msg
 81          */
 82         public void sendOthers(String msg,boolean isSys) {
 83             boolean isPrivate = msg.startsWith("@");
 84             if(isPrivate) { //私聊
 85                 int idx = msg.indexOf(":");
 86                 //獲取目標和數據
 87                 String targetName = msg.substring(1,idx);
 88                 msg = msg.substring(idx+1);
 89                 for(Channel other:all) {
 90                     if(other.name.equals(targetName)) { //目標
 91                         other.send(this.name+"悄悄的對你說:"+msg);
 92                         break;
 93                     }
 94                 }
 95             }else { //群聊
 96                 for(Channel other:all) {
 97                     if(this==other) { //自己
 98                         continue;
 99                     }
100                     if(!isSys) {
101                         other.send(this.name+"對所有人說:"+msg); //群聊消息
102                     }else {
103                         other.send(msg); //系統消息
104                     }
105                 }
106             }
107         }
108         //關閉資源
109         public void release() {
110             this.isRunning = false;
111             Utils.close(dis,dos,client);
112             //退出
113             all.remove(this);
114             sendOthers(this.name+"下線了!",true);
115         }
116 
117         @Override
118         public void run() {
119             while(isRunning) {
120                 String msg = receive();
121                 if(!msg.equals("")) {
122                     //send(msg);
123                     sendOthers(msg,false);
124                 }
125             }
126         }
127     }
128 }

  客戶端:

  Send.java

 1 package com.bjwyj.chat;
 2 
 3 import java.io.BufferedReader;
 4 import java.io.DataOutputStream;
 5 import java.io.IOException;
 6 import java.io.InputStreamReader;
 7 import java.net.Socket;
 8 
 9 /**
10  * 使用多線程封裝了客戶發送端:
11  * 1.發送消息
12  * 2.從控制台獲取消息
13  * 3.釋放資源
14  * 4.重寫run
15  * @author 吳永吉
16  *
17  */
18 public class Send implements Runnable{
19     private BufferedReader console;
20     private DataOutputStream dos;
21     private Socket client;
22     private boolean isRunning;
23     private String name;
24     
25     public Send(Socket client,String name) {
26         isRunning = true;
27         this.client = client;
28         this.name = name;
29         console = new BufferedReader(new InputStreamReader(System.in));
30         try {
31             dos = new DataOutputStream(client.getOutputStream());
32             //發送名稱
33             send(name);
34         } catch (IOException e) {
35             System.out.println("------Client Send------");
36             this.release();
37         }
38     }
39     
40     @Override
41     public void run() {
42         while(isRunning) {
43             String msg = this.getStringFromConsole();
44             if(!msg.equals("")) {
45                 this.send(msg);
46             }
47         }
48     }
49     
50     /**
51      * 發送消息
52      */
53     private void send(String msg) {
54         try {
55             dos.writeUTF(msg);
56             dos.flush();
57         } catch (IOException e) {
58             System.out.println("------Client send------");
59             release();
60         }
61     }
62     
63     /**
64      * 從控制台獲取消息
65      */
66     private String getStringFromConsole() {
67         try {
68             return console.readLine();
69         } catch (IOException e) {
70             System.out.println("------Client console------");
71             release();
72         }
73         return "";
74     }
75     
76     //釋放資源
77     private void release() {
78         this.isRunning = false;
79         Utils.close(dos,client);
80     }
81 }

  Receive.java

 1 package com.bjwyj.chat;
 2 
 3 import java.io.DataInputStream;
 4 import java.io.IOException;
 5 import java.net.Socket;
 6 
 7 /**
 8  * 使用多線程封裝了客戶接收端
 9  * 1.接收消息
10  * 2.釋放資源
11  * 3.重寫run
12  * @author 吳永吉
13  *
14  */
15 public class Receive implements Runnable{
16     private DataInputStream dis;
17     private Socket client;
18     private boolean isRunning;
19     
20     public Receive(Socket client) {
21         this.isRunning = true;
22         this.client = client;
23         try {
24             dis = new DataInputStream(client.getInputStream());
25         } catch (IOException e) {
26             System.out.println("------Client Receive------");
27             this.release();
28         }
29     }
30     
31     //接收消息
32     public String receive() {
33         String msg = "";
34         try {
35             msg = dis.readUTF();
36         } catch (IOException e) {
37             System.out.println("-------Receive receive------");
38             release();
39         }
40         return msg;
41     }
42     
43     @Override
44     public void run() {
45         while(isRunning) {
46             String msg = this.receive();
47             if(!msg.equals("")) {
48                 System.out.println(msg);
49             }
50         }
51     }
52     
53     //釋放資源
54     private void release() {
55         this.isRunning = false;
56         Utils.close(dis,client);
57     }
58 }

  Client.java

 1 package com.bjwyj.chat;
 2 
 3 import java.io.BufferedReader;
 4 import java.io.IOException;
 5 import java.io.InputStreamReader;
 6 import java.net.Socket;
 7 import java.net.UnknownHostException;
 8 
 9 /**
10  * 在線聊天室:客戶端
11  * 
12  * @author 吳永吉
13  *
14  */
15 public class Client {
16     public static void main(String[] args) throws UnknownHostException, IOException {
17         System.out.println("------client------");
18         BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
19         System.out.println("請輸入名稱:");
20         String name = br.readLine();
21         //建立連接:使用Socket創建客戶端+服務器的地址和端口號
22         Socket client = new Socket("localhost",9999);
23         //客戶端發送消息
24         new Thread(new Send(client,name)).start();
25         //獲取消息
26         new Thread(new Receive(client)).start();
27     }
28 }

  運行結果:


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM