Java通過Socket實現(xiàn)簡單多人聊天室
本文實例為大家分享了Java通過Socket實現(xiàn)多人聊天室的具體代碼,供大家參考,具體內(nèi)容如下
Socket可以實現(xiàn)網(wǎng)絡上兩個程序通過雙向通道進行數(shù)據(jù)的交換,此外它是Java中網(wǎng)絡TCP/IP協(xié)議的封裝,例如可以進行網(wǎng)絡通信等等,下面我們就來簡單寫一下多人聊天室。
首先來分析一下要實現(xiàn)的流程
- 首先建立一個服務器端,構建ServerSocket并綁定端口
- 創(chuàng)建socket客戶端,連接到指定ip以及其端口
- 然后使用accept阻塞接收socket發(fā)出的連接請求
- 獲取連接后的socket客戶端的輸入流和輸出流
- 根據(jù)輸入流和輸出流進行兩者數(shù)據(jù)的通信
值得一提是:該Socket是同步阻塞的,因此在socket客戶端需要進行創(chuàng)建一個線程,來分別進行向服務器輸出,和接收服務器傳輸?shù)臄?shù)據(jù)。要解決同步阻塞這個問題可以去了解JAVA NIO。
Socket客戶端代碼如下:
import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.PrintWriter; import java.net.Socket; public class Client{ public static void main(String[] args) throws IOException { //創(chuàng)建連接指定Ip和端口的socket Socket socket = new Socket("127.0.0.1",5200); //獲取系統(tǒng)標準輸入流 BufferedReader reader = new BufferedReader(new InputStreamReader(System.in)); PrintWriter out = new PrintWriter(socket.getOutputStream()); BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream())); //創(chuàng)建一個線程用于讀取服務器的信息 new Thread(new Runnable() { @Override public void run() { try { while (true){ System.out.println(in.readLine()); } } catch (IOException e) { e.printStackTrace(); } } }).start(); //寫信息給客戶端 String line = reader.readLine(); while (!"end".equalsIgnoreCase(line)){ //將從鍵盤獲取的信息給到服務器 out.println(line); out.flush(); //顯示輸入的信息 line = reader.readLine(); } out.close(); in.close(); socket.close(); } }
由于要接收多個客戶端的請求,因此服務端需要多個線程進行分別來接收客戶端的請求。
Socket服務端代碼如下:
import java.io.IOException; import java.net.ServerSocket; import java.net.Socket; import java.util.List; import java.util.Vector; public class Servers { //將接收到的socket變成一個集合 protected static List<Socket> sockets = new Vector<>(); public static void main(String[] args) throws IOException { //創(chuàng)建服務端 ServerSocket server = new ServerSocket(5200); boolean flag = true; //接受客戶端請求 while (flag){ try { //阻塞等待客戶端的連接 Socket accept = server.accept(); synchronized (sockets){ sockets.add(accept); } //多個服務器線程進行對客戶端的響應 Thread thread = new Thread(new ServerThead(accept)); thread.start(); //捕獲異常。 }catch (Exception e){ flag = false; e.printStackTrace(); } } //關閉服務器 server.close(); } }
Server線程代碼如下:
import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.PrintWriter; import java.net.Socket; /** * 服務器線程,主要來處理多個客戶端的請求 */ public class ServerThead extends Servers implements Runnable{ Socket socket; String socketName; public ServerThead(Socket socket){ this.socket = socket; } @Override public void run() { try { BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream())); //設置該客戶端的端點地址 socketName = socket.getRemoteSocketAddress().toString(); System.out.println("Client@"+socketName+"已加入聊天"); print("Client@"+socketName+"已加入聊天"); boolean flag = true; while (flag) { //阻塞,等待該客戶端的輸出流 String line = reader.readLine(); //若客戶端退出,則退出連接。 if (line == null){ flag = false; continue; } String msg = "Client@"+socketName+":"+line; System.out.println(msg); //向在線客戶端輸出信息 print(msg); } closeConnect(); } catch (IOException e) { try { closeConnect(); } catch (IOException e1) { e1.printStackTrace(); } } } /** * 向所有在線客戶端socket轉發(fā)消息 * @param msg * @throws IOException */ private void print(String msg) throws IOException { PrintWriter out = null; synchronized (sockets){ for (Socket sc : sockets){ out = new PrintWriter(sc.getOutputStream()); out.println(msg); out.flush(); } } } /** * 關閉該socket的連接 * @throws IOException */ public void closeConnect() throws IOException { System.out.println("Client@"+socketName+"已退出聊天"); print("Client@"+socketName+"已退出聊天"); //移除沒連接上的客戶端 synchronized (sockets){ sockets.remove(socket); } socket.close(); } }
由于要接收多個客戶端的信息,并轉發(fā)到每一個已經(jīng)連接上的客戶端,因此創(chuàng)建了一個Vector集合來保存每一個客戶端Socket,由于是多個線程同時對這個Vector集合進行操作,因此加上synchronized關鍵字保證同步安全。
先運行服務器端,然后在運行多個客戶端就可以進行多人聊天了。
下面是運行的結果。
客戶端2
客戶端1
客戶端3
服務端
以上就是本文的全部內(nèi)容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。
相關文章
Java Spring詳解如何配置數(shù)據(jù)源注解開發(fā)以及整合Junit
Spring 是目前主流的 Java Web 開發(fā)框架,是 Java 世界最為成功的框架。該框架是一個輕量級的開源框架,具有很高的凝聚力和吸引力,本篇文章帶你了解如何配置數(shù)據(jù)源、注解開發(fā)以及整合Junit2021-10-10