最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Java實現(xiàn)簡單的聊天室功能

 更新時間:2022年06月10日 08:48:28   作者:老徐··  
這篇文章主要為大家詳細介紹了Java實現(xiàn)簡單的聊天室功能,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下

本文實例為大家分享了Java實現(xiàn)簡單聊天室功能的具體代碼,供大家參考,具體內(nèi)容如下

一、客戶端的創(chuàng)建

1.我們可以用Socket來創(chuàng)建客戶端

/**
? *@類名 Client
? *@描述 TODO 客戶端 1
? *@版本 1.0
? *@創(chuàng)建人 XuKang
? *@創(chuàng)建時間 2020/9/24 16:18
? **/
public class Client {
?? ?public static void main(String[] args) throws UnknownHostException, IOException {
?? ??? ?System.out.println("-----Client1-----");
?? ??? ?BufferedReader br =new BufferedReader(new InputStreamReader(System.in));
?? ??? ?System.out.println("請輸入用戶名:");
?? ??? ?String name =br.readLine();
?? ??? ?//1、建立連接: 使用Socket創(chuàng)建客戶端 +服務(wù)的地址和端口
?? ??? ?Socket client =new Socket("localhost",8888);
?? ??? ?//2、客戶端發(fā)送消息
?? ??? ?new Thread(new Send(client,name)).start(); ?
?? ??? ?new Thread(new Receive(client)).start();
?? ?}
}

2.這時我們需要接受其他客戶端發(fā)送的數(shù)據(jù),我們需要創(chuàng)建一個客戶端的接收方法和發(fā)送方法,我可以用阻塞式的方式進行接收和發(fā)送,考慮到多線程的安全性,可以實現(xiàn)Runnable

1.Send發(fā)送端:

/**
? *@類名 Send
? *@描述 TODO 使用多線程封裝:發(fā)送端
? *@版本 1.0
? *@創(chuàng)建人 XuKang
? *@創(chuàng)建時間 2020/9/24 16:23
? **/
public class Send implements Runnable {
?? ?private BufferedReader console ;
?? ?private DataOutputStream dos;
?? ?private Socket client;
?? ?private boolean isRunning;
?? ?private String name;
?? ?public Send(Socket client,String name) {
?? ??? ?this.client =client;
?? ??? ?console =new BufferedReader(new InputStreamReader(System.in));
?? ??? ?this.isRunning = true;
?? ??? ?this.name = name;
?? ??? ?try {
?? ??? ??? ?dos =new DataOutputStream(client.getOutputStream());
?? ??? ??? ?//發(fā)送名稱
?? ??? ??? ?send(name);
?? ??? ?} catch (IOException e) {
?? ??? ??? ?System.out.println("==1==");
?? ??? ??? ?this.release();
?? ??? ?}?? ?
?? ?}
?? ?@Override
?? ?public void run() {
?? ??? ?while(isRunning) {
?? ??? ??? ?String msg = getStrFromConsole();
?? ??? ??? ?if(!msg.equals("")) {
?? ??? ??? ??? ?send(msg);
?? ??? ??? ?}
?? ??? ?}
?? ?}?? ?
?? ?//發(fā)送消息
?? ?private void send(String msg) {
?? ??? ?try {
?? ??? ??? ?dos.writeUTF(msg);
?? ??? ??? ?dos.flush();
?? ??? ?} catch (IOException e) {
?? ??? ??? ?System.out.println(e);
?? ??? ??? ?System.out.println("===3==");
?? ??? ??? ?release();
?? ??? ?}
?? ?}
?? ?/**
?? ? * 從控制臺獲取消息
?? ? * @return
?? ? */
?? ?private String getStrFromConsole() {
?? ??? ?try {
?? ??? ??? ?return ?console.readLine();
?? ??? ?} catch (IOException e) {
?? ??? ??? ?e.printStackTrace();
?? ??? ?}
?? ??? ?return "";
?? ?}
?? ?//釋放資源
?? ?private void release() {
?? ??? ?this.isRunning = false;
?? ??? ?CloseUtils.close(dos,client);
?? ?}

}

2.接收端

/**
? *@類名 Receive
? *@描述 TODO 使用多線程封裝:接收端
? *@版本 1.0
? *@創(chuàng)建人 XuKang
? *@創(chuàng)建時間 2020/9/24 16:22
? **/
public class Receive implements Runnable {
?? ?private DataInputStream dis ;
?? ?private Socket client;
?? ?private boolean isRunning;
?? ?public Receive(Socket client) {
?? ??? ?this.client = client;
?? ??? ?this.isRunning = true;
?? ??? ?try {
?? ??? ??? ?dis =new DataInputStream(client.getInputStream());
?? ??? ?} catch (IOException e) {
?? ??? ??? ?System.out.println("====離開一位=====");
?? ??? ??? ?release();
?? ??? ?}
?? ?}
?? ?//接收消息
?? ?private String receive() {
?? ??? ?String msg ="";
?? ??? ?try {
?? ??? ??? ?msg =dis.readUTF();
?? ??? ?} catch (IOException e) {
?? ??? ??? ?System.out.println("====接收消息異常====");
?? ??? ??? ?release();
?? ??? ?}
?? ??? ?return msg;
?? ?}
?? ?
?? ?@Override
?? ?public void run() {?? ??? ?
?? ??? ?while(isRunning) {
?? ??? ??? ?String msg =receive();
?? ??? ??? ?if(!msg.equals("")) {
?? ??? ??? ??? ?System.out.println(msg);
?? ??? ??? ?}
?? ??? ?}
?? ?}
?? ?//釋放資源
?? ?private void release() {
?? ??? ?this.isRunning = false;
?? ??? ?CloseUtils.close(dis,client);
?? ?}

}

3.統(tǒng)一釋放資源的方法可以提出,服務(wù)的也用得上

/**
? *@類名 CloseUtils
? *@描述 TODO 工具類,統(tǒng)一釋放資源
? *@版本 1.0
? *@創(chuàng)建人 XuKang
? *@創(chuàng)建時間 2020/9/24 16:20
? **/
public class CloseUtils {
?? ?/**
?? ? * 釋放資源
?? ? */
?? ?public static void close(Closeable... targets ) {
?? ??? ?for(Closeable target:targets) {
?? ??? ??? ?try {
?? ??? ??? ??? ?if(null!=target) {
?? ??? ??? ??? ??? ?target.close();
?? ??? ??? ??? ?}
?? ??? ??? ?}catch(Exception e) {

?? ??? ??? ?}
?? ??? ?}
?? ?}
}

二、客戶端的創(chuàng)建

服務(wù)端用ServerSocket創(chuàng)建,如果我們吧服務(wù)的和客戶端看成事一個通信通道(Channel),那么每個客戶端的接入都會創(chuàng)建一個通信通道,那么通信通道的創(chuàng)建也需要實現(xiàn)多線程,可以實現(xiàn)Runnable接口,我們存放通道可以用線程容器CopyOnWriteArrayList來存放通道。

/**
? *@類名 Chat
? *@描述 TODO Socket服務(wù)端(測試類)
? *@版本 1.0
? *@創(chuàng)建人 XuKang
? *@創(chuàng)建時間 2020/9/24 16:17
? **/
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創(chuàng)建服務(wù)器
?? ??? ?ServerSocket server =new ServerSocket(8888);
?? ??? ?// 2、阻塞式等待連接 accept
?? ??? ?while(true) {
?? ??? ??? ??? ?Socket ?client =server.accept();?
?? ??? ??? ??? ?System.out.println("一個客戶端建立了連接");
?? ??? ??? ??? ?Channel c =new Channel(client);
?? ??? ??? ??? ?all.add(c); //管理所有的成員
?? ??? ??? ??? ?new Thread(c).start();?? ??? ??? ?
?? ??? ??? ?}?? ??? ?
?? ??? ?}
?? ??? ?//一個客戶代表一個Channel
?? ??? ?static class Channel implements Runnable{
?? ??? ??? ?private DataInputStream dis;
?? ??? ??? ?private DataOutputStream dos;
?? ??? ??? ?private Socket ?client;?? ??? ??? ?
?? ??? ??? ?private boolean isRunning;
?? ??? ??? ?private String name;
?? ??? ??? ?public Channel(Socket ?client) {
?? ??? ??? ??? ?this.client = client;
?? ??? ??? ??? ?try {
?? ??? ??? ??? ??? ?dis = new DataInputStream(client.getInputStream());
?? ??? ??? ??? ??? ?dos =new DataOutputStream(client.getOutputStream());
?? ??? ??? ??? ??? ?isRunning =true;
?? ??? ??? ??? ??? ?//獲取名稱
?? ??? ??? ??? ??? ?this.name =receive();//退出出聊天室
?? ??? ??? ??? ??? ?//歡迎你的到來
?? ??? ??? ??? ??? ?this.send("歡迎你的到來");
?? ??? ??? ??? ??? ?sendOthers(this.name+"來了徐康聊天室",true);//暫時固定為私聊
?? ??? ??? ??? ?} catch (IOException e) {
?? ??? ??? ??? ??? ?System.out.println("---1------");
?? ??? ??? ??? ??? ?release();?? ??? ??? ??? ??? ?
?? ??? ??? ??? ?}?? ??? ??? ?
?? ??? ??? ?}
?? ??? ??? ?//接收消息
?? ??? ??? ?private String receive() {
?? ??? ??? ??? ?String msg ="";
?? ??? ??? ??? ?try {
?? ??? ??? ??? ??? ?msg =dis.readUTF();
?? ??? ??? ??? ?} catch (IOException e) {
?? ??? ??? ??? ??? ?System.out.println("---2------");
?? ??? ??? ??? ??? ?release();
?? ??? ??? ??? ?}
?? ??? ??? ??? ?return msg;
?? ??? ??? ?}
?? ??? ??? ?//發(fā)送消息
?? ??? ??? ?private void send(String msg) {
?? ??? ??? ??? ?try {
?? ??? ??? ??? ??? ?dos.writeUTF(msg);
?? ??? ??? ??? ??? ?dos.flush();
?? ??? ??? ??? ?} catch (IOException e) {
?? ??? ??? ??? ??? ?System.out.println("---3------");
?? ??? ??? ??? ??? ?release();
?? ??? ??? ??? ?}
?? ??? ??? ?}
?? ??? ??? ?/**
?? ??? ??? ? * @方法名 sendOthers
?? ??? ??? ? * @描述 TODO 群聊:獲取自己的消息,發(fā)給其他人,需要設(shè)置isSys為false
?? ??? ??? ? * ?? ??? ? TODO 私聊: 約定數(shù)據(jù)格式: @xxx:msg
?? ??? ??? ? * @參數(shù) msg 發(fā)送內(nèi)容
?? ??? ??? ? * @返回值
?? ??? ??? ? * @創(chuàng)建人 XuKang
?? ??? ??? ? * @創(chuàng)建時間 2020/9/24 16:28
?? ??? ??? ? */
?? ??? ??? ?private void sendOthers(String msg,boolean isSys) {
?? ??? ??? ??? ?boolean isPrivate = msg.startsWith("@");
?? ??? ??? ??? ?if(isPrivate) { //私聊
?? ??? ??? ??? ??? ?int idx =msg.indexOf(":");
?? ??? ??? ??? ??? ?//獲取目標和數(shù)據(jù)
?? ??? ??? ??? ??? ?String targetName = msg.substring(1,idx);
?? ??? ??? ??? ??? ?msg = msg.substring(idx+1);
?? ??? ??? ??? ??? ?for(Channel other: all) {
?? ??? ??? ??? ??? ??? ?if(other.name.equals(targetName)) {//目標
?? ??? ??? ??? ??? ??? ??? ?other.send(this.name +"悄悄地對您說:"+msg);
?? ??? ??? ??? ??? ??? ??? ?break;
?? ??? ??? ??? ??? ??? ?}
?? ??? ??? ??? ??? ?}
?? ??? ??? ??? ?}else {?? ??? ??? ??? ?
?? ??? ??? ??? ??? ?for(Channel other: all) {
?? ??? ??? ??? ??? ??? ?if(other==this) { //自己
?? ??? ??? ??? ??? ??? ??? ?continue;
?? ??? ??? ??? ??? ??? ?}
?? ??? ??? ??? ??? ??? ?if(!isSys) {
?? ??? ??? ??? ??? ??? ??? ?other.send(this.name +"對所有人說:"+msg);//群聊消息
?? ??? ??? ??? ??? ??? ?}else {
?? ??? ??? ??? ??? ??? ??? ?other.send(msg); //系統(tǒng)消息
?? ??? ??? ??? ??? ??? ?}
?? ??? ??? ??? ??? ?}
?? ??? ??? ??? ?}
?? ??? ??? ?}
?? ??? ??? ?//釋放資源
?? ??? ??? ?private void release() {
?? ??? ??? ??? ?this.isRunning = false;
?? ??? ??? ??? ?CloseUtils.close(dis,dos,client);
?? ??? ??? ??? ?//退出
?? ??? ??? ??? ?all.remove(this);
?? ??? ??? ??? ?sendOthers(this.name+"離開大家庭...",true);
?? ??? ??? ?}
?? ??? ??? ?@Override
?? ??? ??? ?public void run() {
?? ??? ??? ??? ?while(isRunning) {
?? ??? ??? ??? ??? ?String msg = receive() ;
?? ??? ??? ??? ??? ?if(!msg.equals("")) {
?? ??? ??? ??? ??? ??? ?//send(msg);
?? ??? ??? ??? ??? ??? ?sendOthers(msg,false);
?? ??? ??? ??? ??? ?}
?? ??? ??? ??? ?}
?? ??? ??? ?}
?? ??? ?}
}

三、效果如下

1.啟動服務(wù)端

2.啟動客戶端

3.發(fā)送消息

總結(jié)

此案例只能用來打發(fā)時間,入門網(wǎng)絡(luò)編程可以參考一下,真正的開發(fā)不會這么弄。

以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • Java中常用的設(shè)計模式之責(zé)任鏈模式詳解

    Java中常用的設(shè)計模式之責(zé)任鏈模式詳解

    這篇文章主要為大家詳細介紹了Java中常用的設(shè)計模式之責(zé)任鏈模式,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助
    2022-02-02
  • Java中的RASP機制實現(xiàn)詳解

    Java中的RASP機制實現(xiàn)詳解

    這篇文章主要介紹了Java中的RASP實現(xiàn)詳解,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2019-08-08
  • @PropertySource 無法讀取配置文件的屬性值解決方案

    @PropertySource 無法讀取配置文件的屬性值解決方案

    這篇文章主要介紹了@PropertySource 無法讀取配置文件的屬性值解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-06-06
  • 詳解Java抽象類與普通類的區(qū)別

    詳解Java抽象類與普通類的區(qū)別

    今天給大家?guī)淼氖顷P(guān)于Java的相關(guān)知識,文章圍繞著Java抽象類與普通類的區(qū)別展開,文中有非常詳細的介紹及代碼示例,需要的朋友可以參考下
    2021-06-06
  • SpringBoot?@InitBinder注解綁定請求參數(shù)的過程詳解

    SpringBoot?@InitBinder注解綁定請求參數(shù)的過程詳解

    這篇文章主要介紹了SpringBoot?@InitBinder注解綁定請求參數(shù),本文給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2023-04-04
  • IDEA項目啟動時Flyway數(shù)據(jù)庫遷移中的checksum不匹配問題及最新解決方案

    IDEA項目啟動時Flyway數(shù)據(jù)庫遷移中的checksum不匹配問題及最新解決方案

    面對IDEA項目啟動時報出的Flyway遷移校驗和不匹配問題,核心在于保持遷移腳本的一致性、正確管理和理解Flyway的工作機制,本文介紹IDEA項目啟動時Flyway數(shù)據(jù)庫遷移中的checksum不匹配問題及最新解決方案,感興趣的朋友一起看看吧
    2024-01-01
  • 使用JAVA命令運行JAR包以及日志輸出詳解

    使用JAVA命令運行JAR包以及日志輸出詳解

    這篇文章主要給大家介紹了關(guān)于使用JAVA命令運行JAR包以及日志輸出的相關(guān)資料,文中通過代碼示例介紹的非常詳細,對大家學(xué)習(xí)或者使用java具有一定的參考借鑒價值,需要的朋友可以參考下
    2023-09-09
  • Java,C#使用二進制序列化、反序列化操作數(shù)據(jù)

    Java,C#使用二進制序列化、反序列化操作數(shù)據(jù)

    這篇文章主要介紹了Java,C#使用二進制序列化、反序列化操作數(shù)據(jù)的相關(guān)資料,需要的朋友可以參考下
    2014-10-10
  • SpringBoot整合RabbitMQ實現(xiàn)六種工作模式的示例

    SpringBoot整合RabbitMQ實現(xiàn)六種工作模式的示例

    這篇文章主要介紹了SpringBoot整合RabbitMQ實現(xiàn)六種工作模式,本文通過實例代碼給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2022-07-07
  • MyBatis配置不同級別的日志輸出

    MyBatis配置不同級別的日志輸出

    MyBatis提供多種日志框架集成,如SLF4J、Log4j2、Logback等,通過配置日志框架和調(diào)整日志級別,可以實現(xiàn)詳細的SQL日志記錄,本文就來介紹一下,感興趣的可以了解一下
    2024-12-12

最新評論

道真| 宝坻区| 正安县| 攀枝花市| 吴堡县| 宾川县| 河源市| 新野县| 防城港市| 马龙县| 阳朔县| 铜川市| 雷波县| 宁津县| 赞皇县| 澄迈县| 镇雄县| 洱源县| 宜兰县| 双峰县| 涡阳县| 广元市| 赣州市| 措勤县| 仪征市| 揭阳市| 巴林右旗| 马尔康县| 龙山县| 乐至县| 宜宾县| 连城县| 浦江县| 嫩江县| 宜兴市| 武冈市| 廉江市| 太白县| 临安市| 天祝| 如东县|