Java 网络编程 -- 基于TCP 实现聊天室 群聊 私聊
生活随笔
收集整理的這篇文章主要介紹了
Java 网络编程 -- 基于TCP 实现聊天室 群聊 私聊
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
分析:
聊天室需要多個客戶端和一個服務端。
服務端負責轉發消息。
客戶端可以發送消息、接收消息。
……
還是上代碼吧。
基礎版:
搭建結構,實現多個客戶端和服務端連接,保證服務端能正常轉發消息。
我們約定:
當服務端在初始化、發送、接收時出現異常時分別輸出:
------1------
------2------
------3------
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),并添加給其他用戶發送消息方法
添加容器:
2、在初始化發送端,寫入自己用戶名并在初始化就發送
客戶端啟動時,輸入用戶名
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 实现聊天室 群聊 私聊的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: siebel基础配置
- 下一篇: java美元兑换,(Java实现) 美元