日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > java >内容正文

java

Java 网络编程 -- 基于TCP 实现聊天室 群聊 私聊

發布時間:2023/12/16 java 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Java 网络编程 -- 基于TCP 实现聊天室 群聊 私聊 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

分析:
聊天室需要多個客戶端和一個服務端。
服務端負責轉發消息。
客戶端可以發送消息、接收消息。

消息分類:群聊消息:發送除自己外所有人私聊消息:只發送@的人系統消息:根據情況分只發送個人和其他人 技術方面:客戶端和服務端收發消息,需要使用IO流,封裝一個IOUtils工具類用來釋放資源。客戶端需要同時收發消息,需要啟動發送和接收兩個消息,互不干擾服務端需要接收每個客戶端消息和對多個客戶端發送消息,每連接上一個客戶端需要啟動一個線程,讓后面進來的客戶端不需要等待前面的客戶端退出后才能建立連接。

……

還是上代碼吧。

基礎版:

搭建結構,實現多個客戶端和服務端連接,保證服務端能正常轉發消息。
我們約定:
當服務端在初始化、發送、接收時出現異常時分別輸出:
------1------
------2------
------3------

當客戶端,初始化發送線程、初始化接收線程、發送、接收異常時分別輸出: ======1===== ======2===== ======3===== ======4=====

1、IO工具類

package com.xzlf.chat;import java.io.Closeable; import java.io.IOException;/*** 工具類* @author xzlf**/ public class IOUtils {/*** 釋放資源* @param closeables*/public static void close(Closeable...closeables) {for (Closeable closeable : closeables) {if(null != closeable) {try {closeable.close();} catch (IOException e) {e.printStackTrace();}}}} }

2、服務端

package com.xzlf.chat;import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; import java.net.ServerSocket; import java.net.Socket;/*** 聊天室:服務器* @author xzlf**/ public class TMultiChat {public static void main(String[] args) throws IOException {System.out.println("======server======");// 1、指定端口創建服務端ServerSocket server = new ServerSocket(8888);while(true) {// 2、每進來一個客戶端啟動一個線程Socket socket = server.accept();System.out.println("一個客戶端建立了連接");new Thread(new Channel(socket)).start();}}// 一個Channel 代表一個客戶端static class Channel implements Runnable{private Socket socket;private DataInputStream dis;private DataOutputStream dos;private boolean isRuning;public Channel(Socket socket) {this.socket = socket;this.isRuning = true;try {dis = new DataInputStream(socket.getInputStream());dos = new DataOutputStream(socket.getOutputStream());} catch (IOException e) {System.out.println("------1------");this.release();}}// 接收消息private String receive() {String msg = "";try {msg = dis.readUTF();} catch (IOException e) {System.out.println("------3------");this.release();}return msg;}// 發送消息private void send(String msg) {try {dos.writeUTF(msg);} catch (IOException e) {System.out.println("------2------");this.release();}}// 釋放資源private void release() {this.isRuning = false;IOUtils.close(dis, dos, socket);}@Overridepublic void run() {while(isRuning) {String msg = this.receive();if (!msg.equals("")) {this.send(msg);}}}} }

3、多線程封裝發送端

package com.xzlf.chat;import java.io.BufferedReader; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; import java.io.InputStreamReader; import java.io.ObjectInputStream.GetField; import java.net.Socket;/*** 利用多線程封裝發送端* * @author xzlf**/ public class Send implements Runnable{private Socket socket;private DataOutputStream dos;private BufferedReader console;private boolean isRuning;public Send(Socket socket) {this.socket = socket;this.isRuning = true;try {console = new BufferedReader(new InputStreamReader(System.in));dos = new DataOutputStream(socket.getOutputStream());} catch (IOException e) {System.out.println("======1=====");this.release();}}// 從控制臺獲取消息private String getStrFromConsole() {try {return console.readLine();} catch (IOException e) {e.printStackTrace();}return "";}// 發送消息public void send(String msg) {try {dos.writeUTF(msg);dos.flush();} catch (IOException e) {e.printStackTrace();System.out.println("======3=====");this.release();}}// 釋放資源private void release() {this.isRuning = false;IOUtils.close(dos, console, socket);}@Overridepublic void run() {while(isRuning) {String msg = getStrFromConsole();if (!msg.equals("")) {this.send(msg);}}}}

4、多線程封裝接收端

package com.xzlf.chat;import java.io.DataInputStream; import java.io.IOException; import java.net.Socket;/*** 使用多線程封裝接收端* @author xzlf**/ public class Receive implements Runnable {private Socket socket;private DataInputStream dis;private boolean isRuning;public Receive(Socket socket) {this.socket = socket;this.isRuning = true;try {dis = new DataInputStream(socket.getInputStream());} catch (IOException e) {System.out.println("======2=====");this.release();}}// 接收消息public String receive() {String msg = "";try {msg = dis.readUTF();} catch (IOException e) {System.out.println(e);System.out.println("======4=====");release();}return msg;}// 釋放資源private void release() {this.isRuning = false;IOUtils.close(dis, socket);}@Overridepublic void run() {while(isRuning) {String msg = receive();if(!msg.equals("")) {System.out.println(msg);}}} }

5、客戶端

package com.xzlf.chat;import java.io.IOException; import java.net.Socket; import java.net.UnknownHostException;/*** 聊天室:客戶端* @author xzlf**/ public class TMultiClient {public static void main(String[] args) throws UnknownHostException, IOException {System.out.println("======client======");// 1、指定ip + 端口 建立連接Socket socket = new Socket("localhost", 8888);// 2、客戶端收發消息new Thread(new Send(socket)).start();new Thread(new Receive(socket)).start();} }

運行服務端和客戶端:

先每個客戶端只能自己跟自己聊。

實現群聊:

1、加入容器(使用JUC包下的并發容器CopyOnWriteArrayList),并添加給其他用戶發送消息方法
添加容器:

public class Chat {private static CopyOnWriteArrayList<Channel> all = new CopyOnWriteArrayList<Channel>();public static void main(String[] args) throws IOException {System.out.println("======server======");// 1、指定端口創建服務端ServerSocket server = new ServerSocket(8888);while(true) {// 2、每進來一個客戶端啟動一個線程Socket socket = server.accept();Channel c = new Channel(socket);all.add(c);System.out.println("一個客戶端建立了連接");new Thread(c).start();}} 添加群發方法 // 群聊:發送消息給其他人private void sendOthers(String msg, boolean isSys) {for(Channel other : all) {if(other == this) {continue;}if (!isSys) {// 群聊消息other.send(this.name + "說:" + msg);}else {// 系統消息other.send(msg);}}}

2、在初始化發送端,寫入自己用戶名并在初始化就發送
客戶端啟動時,輸入用戶名

public class Client {public static void main(String[] args) throws UnknownHostException, IOException {System.out.println("======client======");BufferedReader br = new BufferedReader(new InputStreamReader(System.in));System.out.print("請輸入用戶名:");String name = br.readLine();// 1、指定ip + 端口 建立連接Socket socket = new Socket("localhost", 8888);// 2、客戶端收發消息new Thread(new Send(socket, name)).start();new Thread(new Receive(socket)).start();} } 發送線程初始化時立馬發送用戶名: public class Send implements Runnable{private Socket socket;private DataOutputStream dos;private BufferedReader console;private boolean isRuning;private String name;public Send(Socket socket, String name) {this.socket = socket;this.name = name;try {this.isRuning = true;console = new BufferedReader(new InputStreamReader(System.in));dos = new DataOutputStream(socket.getOutputStream());// 發送用戶名this.send(name);} catch (IOException e) {System.out.println("======1=====");this.release();}} 服務端的channel類中初始化時立馬接收用戶名并保存

3、服務端(靜態內部類Channel類中)在初始化時立即獲取用戶名并給用戶發送歡迎信息同時給其他用戶發提示信息(系統消息)

static class Channel implements Runnable{private Socket socket;private DataInputStream dis;private DataOutputStream dos;private boolean isRuning;private String name;public Channel(Socket socket) {this.socket = socket;this.isRuning = true;try {dis = new DataInputStream(socket.getInputStream());dos = new DataOutputStream(socket.getOutputStream());// 獲取用戶名this.name = receive();this.send("歡迎你的到來");this.sendOthers(this.name + "來了xxx聊天室", true);} catch (IOException e) {System.out.println("------1------");this.release();}}

4、用戶關閉線程,給其他用戶發送提示信息,提示用戶已離開

// 釋放資源private void release() {this.isRuning = false;IOUtils.close(dis, dos, socket);// 退出all.remove(this);sendOthers(this.name + "離開了聊天室。。。", true);}

運行測試:

實現私聊:

通過判斷用戶輸入信息是否包含“@xxx:”確定是否為私聊,修改群發方法:

/*** 群聊:獲取自己的信息,發送消息給其他人* 私聊:約定數據格式: @xxx:msg* @param msg* @param isSys*/private void sendOthers(String msg, boolean isSys) {if(msg.startsWith("@")) {// 私聊int endIndex = msg.indexOf(":");String targetName = msg.substring(1, endIndex);String info = msg.substring(endIndex + 1);for(Channel other : all) {if(other.name.equals(targetName)) {other.send(this.name + "悄悄對你說:" + info);}}}else {// 群聊for(Channel other : all) {if(other == this) {continue;}if (!isSys) {// 群聊消息other.send(this.name + "說:" + msg);}else {// 系統消息other.send(msg);}}}}

好了,現在已經實現了私聊。
運行測試一下:

總結

以上是生活随笔為你收集整理的Java 网络编程 -- 基于TCP 实现聊天室 群聊 私聊的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。