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

歡迎訪問 生活随笔!

生活随笔

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

java

【Java网络编程(四)】手写TCP聊天室——控制台版

發布時間:2024/2/28 java 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【Java网络编程(四)】手写TCP聊天室——控制台版 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

版本1:群聊功能

使用TCP

運行方式:先開服務端,再開任意個數客戶端。在控制臺可以實現群聊功能。

效果

代碼
服務端

package cn.hanquan.groupchat;import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; import java.net.ServerSocket; import java.net.Socket; import java.util.concurrent.CopyOnWriteArrayList;/** 在線聊天室:服務端* 服務器不生產內容,只是轉發*/ public class Chat {public static CopyOnWriteArrayList<Channel> allChannel = new CopyOnWriteArrayList<>();public static void main(String[] args) throws IOException {System.out.println("-----Server-----");ServerSocket server = new ServerSocket(8888);// 指定端口 創建服務器while (true) {Socket client = server.accept();// 阻塞式等待鏈接System.out.println("A client succesfully connected.");new Thread(new Channel(client)).start();// 新線程}}static class Channel implements Runnable {private Socket client;private DataOutputStream dos;private DataInputStream dis;boolean isRunning = true;public Channel(Socket client) {allChannel.add(this);this.client = client;try {this.dos = new DataOutputStream(client.getOutputStream());this.dis = new DataInputStream(client.getInputStream());} catch (IOException e) {System.out.println("構造器異常" + e);}}// 接收消息public String receive() {String msg = null;try {msg = dis.readUTF();} catch (IOException e) {isRunning = false;release();}return msg;}// 發送消息給當前Channelpublic void send(String msg) {if (msg == null)return;try {dos.writeUTF(msg);dos.flush();} catch (IOException e) {isRunning = false;release();}}// 發送消息給所有Chanelpublic void sendAll(String msg) {for (Channel channel : allChannel) {if (channel == this)// 不發給自己continue;channel.send(msg);}}// 釋放資源public void release() {new Utils().close(dis, dos, client);}@Overridepublic void run() {while (isRunning) {String msg = receive();sendAll(msg);}}} }

客戶端

package cn.hanquan.groupchat;import java.io.BufferedReader; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; import java.io.InputStreamReader; import java.net.Socket; import java.net.UnknownHostException; import java.util.Scanner;/** 在線聊天室:客戶端*/ public class Client {public static void main(String[] args) throws UnknownHostException, IOException {System.out.println("-----Client-----");Socket client = new Socket("localhost", 8888);// 建立鏈接new Thread(new Send(client)).start();new Thread(new Receive(client)).start();}// 發送public static class Send implements Runnable {String name;Socket client;DataOutputStream dos;BufferedReader console;DataInputStream dis;boolean isRunning = true;public Send(Socket client) {this.name = inputName();this.client = client;try {dos = new DataOutputStream(client.getOutputStream());console = new BufferedReader(new InputStreamReader(System.in));dis = new DataInputStream(client.getInputStream());} catch (Exception e) {System.out.println("構造器異常" + e);}}@Overridepublic void run() {while (isRunning) {String str = null;try {str = console.readLine();} catch (IOException e) {e.printStackTrace();}send(str);}}public String receive() {String msg = null;try {msg = dis.readUTF();} catch (IOException e) {e.printStackTrace();}return msg;}public void send(String msg) {try {dos.writeUTF(this.name + ": " + msg);dos.flush();} catch (IOException e) {e.printStackTrace();}}public void release() {new Utils().close(dis, dos, client);}public String inputName() {System.out.println("請輸入用戶名:");BufferedReader sc = new BufferedReader(new InputStreamReader(System.in));String name = null;try {name = sc.readLine();} catch (IOException e) {e.printStackTrace();}System.out.println("歡迎: " + name+" 進入聊天室~ 你現在可以暢所欲言~");// c.close();return name;}}// 接收public static class Receive implements Runnable {Socket client;DataOutputStream dos;BufferedReader console;DataInputStream dis;boolean isRunning = true;public Receive(Socket client) {this.client = client;try {dos = new DataOutputStream(client.getOutputStream());console = new BufferedReader(new InputStreamReader(System.in));dis = new DataInputStream(client.getInputStream());} catch (Exception e) {System.out.println("構造器異常" + e);}}@Overridepublic void run() {while (isRunning) {String msg = receive();System.out.println(msg);}}public String receive() {String msg = null;try {msg = dis.readUTF();} catch (IOException e) {e.printStackTrace();}return msg;}public void release() {new Utils().close(dis, dos, client);}} }

工具類

package cn.hanquan.groupchat;import java.io.Closeable;public class Utils {public void close(Closeable... targets) {for (Closeable t : targets) {try {if (null != t) {t.close();}} catch (Exception e) {e.printStackTrace();}}} }

版本2: 進入提醒功能

示例

-----Client-----
請輸入用戶名:
布小谷
布小谷, Welcome ~
(系統消息) [魔鬼] 進入了聊天室
(系統消息) [逆風微笑的程序猿] 進入了聊天室
魔鬼: 我要出去了
再見哦
逆風微笑的程序猿: 再見啊

服務端

package cn.hanquan.groupchat;import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; import java.net.ServerSocket; import java.net.Socket; import java.util.concurrent.CopyOnWriteArrayList;/** 在線聊天室:服務端* 服務器不生產內容,只是轉發* * 改進:* 增加系統消息功能,新人登錄之后系統消息提示(群發時候加個bool即可)* 用戶關閉后,從容器中刪除allChannel.remove(this);并且系統發出廣播退出通知*/ public class Chat {public static CopyOnWriteArrayList<Channel> allChannel = new CopyOnWriteArrayList<>();public static void main(String[] args) throws IOException {System.out.println("-----Server-----");ServerSocket server = new ServerSocket(8888);// 指定端口 創建服務器while (true) {Socket client = server.accept();// 阻塞式等待鏈接System.out.println("A client succesfully connected.");new Thread(new Channel(client)).start();// 新線程}}// 一個Channel線程就是一個Client連接static class Channel implements Runnable {private Socket client;private DataOutputStream dos;private DataInputStream dis;public String clientName;boolean isRunning = true;public Channel(Socket client) {allChannel.add(this);this.client = client;try {this.dos = new DataOutputStream(client.getOutputStream());this.dis = new DataInputStream(client.getInputStream());} catch (IOException e) {System.out.println("構造器異常" + e);}}// 接收消息public String receive() {String msg = null;try {msg = dis.readUTF();} catch (IOException e) {isRunning = false;release();}if (msg != null) {if (msg.indexOf("(系統消息)") == 0) {this.clientName = msg.substring(msg.indexOf("[") + 1, msg.indexOf("]"));}}return msg;}// 發送消息給當前Channelpublic void send(String msg) {if (msg == null)return;try {dos.writeUTF(msg);dos.flush();} catch (IOException e) {isRunning = false;release();allChannel.remove(this);}}// 發送消息給所有Channelpublic void sendAll(String msg) {for (Channel channel : allChannel) {if (channel == this)// 不發給自己continue;channel.send(msg);}}// 釋放資源public void release() {new Utils().close(dis, dos, client);}@Overridepublic void run() {while (isRunning) {String msg = receive();sendAll(msg);}}} }

客戶端

package cn.hanquan.groupchat;import java.io.BufferedReader; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; import java.io.InputStreamReader; import java.net.Socket; import java.net.UnknownHostException; import java.util.Scanner;/** 在線聊天室:客戶端*/ public class Client {public static void main(String[] args) throws UnknownHostException, IOException {System.out.println("-----Client-----");Socket client = new Socket("localhost", 8888);// 建立鏈接new Thread(new Send(client)).start();new Thread(new Receive(client)).start();}// 發送public static class Send implements Runnable {String uname;Socket client;DataOutputStream dos;BufferedReader console;DataInputStream dis;boolean isRunning = true;// 構造器public Send(Socket client) {this.uname = inputName();this.client = client;try {dos = new DataOutputStream(client.getOutputStream());console = new BufferedReader(new InputStreamReader(System.in));dis = new DataInputStream(client.getInputStream());} catch (Exception e) {System.out.println("構造器異常" + e);}send("進入了聊天室", true);}@Overridepublic void run() {while (isRunning) {String str = null;try {str = console.readLine();} catch (IOException e) {e.printStackTrace();}send(str, false);}}// 接收public String receive() {String msg = null;try {msg = dis.readUTF();} catch (IOException e) {e.printStackTrace();}return msg;}// 發送public void send(String msg, boolean system) {try {if (system)dos.writeUTF("(系統消息) [" + this.uname + "] " + msg);elsedos.writeUTF(this.uname + ": " + msg);dos.flush();} catch (IOException e) {e.printStackTrace();}}// 釋放public void release() {new Utils().close(dis, dos, client);}public String inputName() {System.out.println("請輸入用戶名:");BufferedReader sc = new BufferedReader(new InputStreamReader(System.in));String name = null;try {name = sc.readLine();} catch (IOException e) {e.printStackTrace();}System.out.println(name + ", Welcome ~ ");return name;}}// 接收public static class Receive implements Runnable {Socket client;DataOutputStream dos;BufferedReader console;DataInputStream dis;boolean isRunning = true;public Receive(Socket client) {this.client = client;try {dos = new DataOutputStream(client.getOutputStream());console = new BufferedReader(new InputStreamReader(System.in));dis = new DataInputStream(client.getInputStream());} catch (Exception e) {System.out.println("構造器異常" + e);}}@Overridepublic void run() {while (isRunning) {String msg = receive();System.out.println(msg);}}public String receive() {String msg = null;try {msg = dis.readUTF();} catch (IOException e) {e.printStackTrace();}return msg;}public void release() {new Utils().close(dis, dos, client);}} }

工具類

版本2的工具類和版本1的工具類相同,沒有改動

package cn.hanquan.groupchat;import java.io.Closeable;public class Utils {public void close(Closeable... targets) {for (Closeable t : targets) {try {if (null != t) {t.close();}} catch (Exception e) {e.printStackTrace();}}} }

運行效果

先運行一個Chat.java

再運行一個Client.java(name:魔鬼)
再運行一個Client.java(name:布小谷)
再運行一個Client.java(name:逆風微笑的程序猿)

再退出一個Client.java(name:魔鬼)

…此版本后來有改動。因為一個線程退出后,其數據不再有效,因此無法使用其類內部的sendall方法。所以取消退出提醒功能。如果想要全局提醒,可以考慮加入一個獨立的紫銅消息線程

版本3: 群聊/私聊

此版本增加了私聊功能~

規定的私聊語法:

@某人 你要說的話

是最終版了,但是里面有一些用戶可能輸入非法字符串的bug,比如輸入@@就直接string outofbound崩了,這些bug的修復,還需要進一步過濾字符串,在這里就先不改了。

服務端

package cn.hanquan.groupchat;import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; import java.net.ServerSocket; import java.net.Socket; import java.util.concurrent.CopyOnWriteArrayList;/** 在線聊天室:服務端* 服務器不生產內容,只是轉發* * 改進:* 增加系統消息功能,新人登錄之后系統消息提示(群發時候加個bool即可)* 用戶關閉后,從容器中刪除allChannel.remove(this);并且系統發出廣播退出通知*/ public class Chat {public static CopyOnWriteArrayList<Channel> allChannel = new CopyOnWriteArrayList<>();public static void main(String[] args) throws IOException {System.out.println("-----Server-----");ServerSocket server = new ServerSocket(8888);// 指定端口 創建服務器while (true) {Socket client = server.accept();// 阻塞式等待鏈接System.out.println("A client succesfully connected.");new Thread(new Channel(client)).start();// 新線程}}// 一個Channel線程就是一個Client連接static class Channel implements Runnable {private Socket client;private DataOutputStream dos;private DataInputStream dis;public String clientName;boolean isRunning = true;public Channel(Socket client) {allChannel.add(this);this.client = client;try {this.dos = new DataOutputStream(client.getOutputStream());this.dis = new DataInputStream(client.getInputStream());} catch (IOException e) {System.out.println("構造器異常" + e);}}// 接收消息public String receive() {String msg = null;try {msg = dis.readUTF();} catch (IOException e) {isRunning = false;release();}if (msg != null) {if (msg.indexOf("(系統消息)") == 0) {this.clientName = msg.substring(msg.indexOf("[") + 1, msg.indexOf("]"));}}return msg;}// 發送消息給當前Channelpublic void send(String msg) {if (msg == null)return;try {dos.writeUTF(msg);dos.flush();} catch (IOException e) {isRunning = false;release();allChannel.remove(this);}}// 發送消息給所有Channelpublic void sendAll(String msg) {try {if (msg.indexOf("@") != -1) {// 私聊格式 @SomeOne say...String toName = msg.substring(msg.indexOf("@") + 1, msg.indexOf(" ", msg.indexOf("@") + 1));for (Channel channel : allChannel) {if (channel.clientName.equals(toName)) { // 發給自己指定人channel.send(msg);break;}}} else {// 群發for (Channel channel : allChannel) {if (channel == this)// 不發給自己continue;channel.send(msg);}}} catch (NullPointerException e) {System.out.println("One client exit");isRunning = false;release();allChannel.remove(this);}}// 釋放資源public void release() {new Utils().close(dis, dos, client);}@Overridepublic void run() {while (isRunning) {String msg = receive();sendAll(msg);}}} }

客戶端

package cn.hanquan.groupchat;import java.io.BufferedReader; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; import java.io.InputStreamReader; import java.net.Socket; import java.net.UnknownHostException; import java.util.Scanner;/** 在線聊天室:客戶端*/ public class Client {public static void main(String[] args) throws UnknownHostException, IOException {System.out.println("-----Client-----");Socket client = new Socket("localhost", 8888);// 建立鏈接new Thread(new Send(client)).start();new Thread(new Receive(client)).start();}// 發送public static class Send implements Runnable {String uname;Socket client;DataOutputStream dos;BufferedReader console;DataInputStream dis;boolean isRunning = true;// 構造器public Send(Socket client) {this.uname = inputName();this.client = client;try {dos = new DataOutputStream(client.getOutputStream());console = new BufferedReader(new InputStreamReader(System.in));dis = new DataInputStream(client.getInputStream());} catch (Exception e) {System.out.println("構造器異常" + e);}send("進入了聊天室", true);}@Overridepublic void run() {while (isRunning) {String str = null;try {str = console.readLine();} catch (IOException e) {e.printStackTrace();}send(str, false);}}// 接收public String receive() {String msg = null;try {msg = dis.readUTF();} catch (IOException e) {e.printStackTrace();}return msg;}// 發送public void send(String msg, boolean system) {try {if (system)dos.writeUTF("(系統消息) [" + this.uname + "] " + msg);elsedos.writeUTF(this.uname + ": " + msg);dos.flush();} catch (IOException e) {e.printStackTrace();}}// 釋放public void release() {new Utils().close(dis, dos, client);}public String inputName() {System.out.println("請輸入用戶名:");BufferedReader sc = new BufferedReader(new InputStreamReader(System.in));String name = null;try {name = sc.readLine();} catch (IOException e) {e.printStackTrace();}System.out.println(name + ", Welcome ~ ");return name;}}// 接收public static class Receive implements Runnable {Socket client;DataOutputStream dos;BufferedReader console;DataInputStream dis;boolean isRunning = true;public Receive(Socket client) {this.client = client;try {dos = new DataOutputStream(client.getOutputStream());console = new BufferedReader(new InputStreamReader(System.in));dis = new DataInputStream(client.getInputStream());} catch (Exception e) {System.out.println("構造器異常" + e);}}@Overridepublic void run() {while (isRunning) {String msg = receive();System.out.println(msg);}}public String receive() {String msg = null;try {msg = dis.readUTF();} catch (IOException e) {e.printStackTrace();}return msg;}public void release() {new Utils().close(dis, dos, client);}} }

工具類

package cn.hanquan.groupchat;import java.io.Closeable;public class Utils {public void close(Closeable... targets) {for (Closeable t : targets) {try {if (null != t) {t.close();}} catch (Exception e) {e.printStackTrace();}}} }

運行效果

總結

以上是生活随笔為你收集整理的【Java网络编程(四)】手写TCP聊天室——控制台版的全部內容,希望文章能夠幫你解決所遇到的問題。

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